jni c code calls this for sha512.
438639
private static MessageDigest SHA512_Init() {
		Log.d("Ed25519", "SHA512_Init");
		try {
			return MessageDigest.getInstance("SHA-512");
		} catch (NoSuchAlgorithmException e) {
			e.printStackTrace();
		}
		return null;
	}
602514
public static byte[] sha512(byte [] message) {
            if (!(message!=null && message.length>0))
                return null;

            byte [] out = new byte[hashLength];

            crypto_hash(out, message);

            return out;
        }
683194
@Override
  public Hash2<Integer, V> createHashTable() {
    return new Hash2<Integer, V>(this) {
      @Override
      protected int modifiedHashCode(final int hc) {
        return IntHeapCache.this.modifiedHash(hc);
      }

      @Override
      protected boolean keyObjIsEqual(final Integer key, final Entry e) {
        return true;
      }
    };
  }
143231
public static void main(String[] args) throws Exception {
		String originalValue = "Amman123";
		byte[] encryptedValue = encrypt(originalValue.getBytes());
		String descryptedValue = new String(decrypt(encryptedValue), "UTF-8");
		byte[] hashed = hash(originalValue.toCharArray(), salt());

		System.out.println("Original value: " + originalValue);
		System.out.println("Encrypted value: " + new String(encryptedValue));
		System.out.println("Decryped value: " + descryptedValue);

		System.out.println("Hashing original value:" + encodeInToBase64(hashed));

		Password password = createPassword(originalValue.toCharArray());
		System.out.println("Password hash: " + password.getHash());
		System.out.println("Password salt: " + password.getSalt());
//		System.out.println(encode("3"));

	}
1140789
private static String buildRegisteredServiceCacheKey(final RegisteredService registeredService) {
        val key = registeredService.getId() + '@' + registeredService.getName();
        return DigestUtils.sha512(key);
    }
1249271
function RSASHA512() {

  /**
  * Sign the given string using the given key
  *
  */
  this.getSignature = function(signedInfo, signingKey) {
    var signer = crypto.createSign("RSA-SHA512")
    signer.update(signedInfo)
    var res = signer.sign(signingKey, 'base64')
    return res
  }

  /**
  * Verify the given signature of the given string using key
  *
  */
  this.verifySignature = function(str, key, signatureValue) {
    var verifier = crypto.createVerify("RSA-SHA512")
    verifier.update(str)
    var res = verifier.verify(key, signatureValue, 'base64')
    return res
  }

  this.getAlgorithmName = function() {
    return "http://www.w3.org/2001/04/xmldsig-more#rsa-sha512"
  }
}
236456
public static int crypto_sign_open(
  Sha512 sha512provider,
  byte[] m, long mlen,
  byte[] sm, long smlen,
  byte[] pk
)
{
  byte[] pkcopy = new byte[32];
  byte[] rcopy = new byte[32];
  byte[] scopy = new byte[32];
  byte[] h = new byte[64];
  byte[] rcheck = new byte[32];
  ge_p3 A = new ge_p3();
  ge_p2 R = new ge_p2();

  if (smlen < 64) return -1;
  if ((sm[63] & 224) != 0) return -1;
  if (ge_frombytes.ge_frombytes_negate_vartime(A,pk) != 0) return -1;

  byte[] pubkeyhash = new byte[64];
  sha512provider.calculateDigest(pubkeyhash,pk,32);

  System.arraycopy(pk, 0, pkcopy, 0, 32);
  System.arraycopy(sm, 0, rcopy, 0, 32);
  System.arraycopy(sm, 32, scopy, 0, 32);

  System.arraycopy(sm, 0, m, 0, (int)smlen);
  System.arraycopy(pkcopy, 0, m, 32, 32);
  sha512provider.calculateDigest(h,m,smlen);
  sc_reduce.sc_reduce(h);

  ge_double_scalarmult.ge_double_scalarmult_vartime(R,h,A,scopy);
  ge_tobytes.ge_tobytes(rcheck,R);
  if (crypto_verify_32.crypto_verify_32(rcheck,rcopy) == 0) {
    System.arraycopy(m, 64, m, 0, (int)(smlen - 64));
    //memset(m + smlen - 64,0,64);
    return 0;
  }

//badsig:
  //memset(m,0,smlen);
  return -1;
}
434114
public static String sha512(final String data) {
        return digest(MessageDigestAlgorithms.SHA_512, data.getBytes(StandardCharsets.UTF_8));
    }
699325
private String sha512hash(String str) {
        return Hashing.sha512().hashBytes(str.getBytes(getEncoding())).toString();
    }
1247506
function getHmacKey(key, blockIndex) {
    var shaSrc = new Uint8Array(8 + key.byteLength);
    shaSrc.set(new Uint8Array(key), 8);
    var view = new DataView(shaSrc.buffer);
    view.setUint32(0, blockIndex.lo, true);
    view.setUint32(4, blockIndex.hi, true);
    return CryptoEngine.sha512(ByteUtils.arrayToBuffer(shaSrc)).then(function(sha) {
        ByteUtils.zeroBuffer(shaSrc);
        return sha;
    });
}
936460
def derivesha512address(self):
        
        pkbin = unhexlify(repr(self._pubkey))
        addressbin = ripemd160(hexlify(hashlib.sha512(pkbin).digest()))
        return Base58(hexlify(addressbin).decode('ascii'))
72897
private static String sha1hash(Collection<String> nquads) {
        try {
            // create SHA-1 digest
            final MessageDigest md = MessageDigest.getInstance("SHA-1");
            for (final String nquad : nquads) {
                md.update(nquad.getBytes("UTF-8"));
            }
            return encodeHex(md.digest());
        } catch (final NoSuchAlgorithmException e) {
            throw new RuntimeException(e);
        } catch (final UnsupportedEncodingException e) {
            throw new RuntimeException(e);
        }
    }
1180830
public /*@ pure @*/ int cmpPow52(int p5, int p2) {
        if (p5 == 0) {
            int wordcount = p2 >> 5;
            int bitcount = p2 & 0x1f;
            int size = this.nWords + this.offset;
            if (size > wordcount + 1) {
                return 1;
            } else if (size < wordcount + 1) {
                return -1;
            }
            int a = this.data[this.nWords -1];
            int b = 1 << bitcount;
            if (a != b) {
                return ( (a & LONG_MASK) < (b & LONG_MASK)) ? -1 : 1;
            }
            return checkZeroTail(this.data, this.nWords - 1);
        }
        return this.cmp(big5pow(p5).leftShift(p2));
    }
167198
public static byte[] calcNewAddr(byte[] addr, byte[] nonce) {

        byte[] encSender = RLP.encodeElement(addr);
        byte[] encNonce = RLP.encodeBigInteger(new BigInteger(1, nonce));

        return sha3omit12(RLP.encodeList(encSender, encNonce));
    }
152458
private static byte[] oneBlock(byte[] buffer, InputStream in, int len) throws IOException {
        MessageDigest sha1 = null;
        try {
            sha1 = MessageDigest.getInstance("sha-1");
        } catch (NoSuchAlgorithmException e) {
            e.printStackTrace();
            //never reach
            return null;
        }
        int buffSize = buffer.length;
        while (len != 0) {
            int next = buffSize > len ? len : buffSize;
            //noinspection ResultOfMethodCallIgnored
            in.read(buffer, 0, next);
            sha1.update(buffer, 0, next);
            len -= next;
        }

        return sha1.digest();
    }
1195038
function initModule(forge) {

var sha512 = forge.sha512 = forge.sha512 || {};
forge.md = forge.md || {};
forge.md.algorithms = forge.md.algorithms || {};

// SHA-512
forge.md.sha512 = forge.md.algorithms.sha512 = sha512;

// SHA-384
var sha384 = forge.sha384 = forge.sha512.sha384 = forge.sha512.sha384 || {};
sha384.create = function() {
  return sha512.create('SHA-384');
};
forge.md.sha384 = forge.md.algorithms.sha384 = sha384;

// SHA-512/256
forge.sha512.sha256 = forge.sha512.sha256 || {
  create: function() {
    return sha512.create('SHA-512/256');
  }
};
forge.md['sha512/256'] = forge.md.algorithms['sha512/256'] =
  forge.sha512.sha256;

// SHA-512/224
forge.sha512.sha224 = forge.sha512.sha224 || {
  create: function() {
    return sha512.create('SHA-512/224');
  }
};
forge.md['sha512/224'] = forge.md.algorithms['sha512/224'] =
  forge.sha512.sha224;

/**
 * Creates a SHA-2 message digest object.
 *
 * @param algorithm the algorithm to use (SHA-512, SHA-384, SHA-512/224,
 *          SHA-512/256).
 *
 * @return a message digest object.
 */
sha512.create = function(algorithm) {
  // do initialization as necessary
  if(!_initialized) {
    _init();
  }

  if(typeof algorithm === 'undefined') {
    algorithm = 'SHA-512';
  }

  if(!(algorithm in _states)) {
    throw new Error('Invalid SHA-512 algorithm: ' + algorithm);
  }

  // SHA-512 state contains eight 64-bit integers (each as two 32-bit ints)
  var _state = _states[algorithm];
  var _h = null;

  // input buffer
  var _input = forge.util.createBuffer();

  // used for 64-bit word storage
  var _w = new Array(80);
  for(var wi = 0; wi < 80; ++wi) {
    _w[wi] = new Array(2);
  }

  // message digest object
  var md = {
    // SHA-512 => sha512
    algorithm: algorithm.replace('-', '').toLowerCase(),
    blockLength: 128,
    digestLength: 64,
    // 56-bit length of message so far (does not including padding)
    messageLength: 0,
    // true message length
    fullMessageLength: null,
    // size of message length in bytes
    messageLengthSize: 16
  };

  /**
   * Starts the digest.
   *
   * @return this digest object.
   */
  md.start = function() {
    // up to 56-bit message length for convenience
    md.messageLength = 0;

    // full message length (set md.messageLength128 for backwards-compatibility)
    md.fullMessageLength = md.messageLength128 = [];
    var int32s = md.messageLengthSize / 4;
    for(var i = 0; i < int32s; ++i) {
      md.fullMessageLength.push(0);
    }
    _input = forge.util.createBuffer();
    _h = new Array(_state.length);
    for(var i = 0; i < _state.length; ++i) {
      _h[i] = _state[i].slice(0);
    }
    return md;
  };
  // start digest automatically for first time
  md.start();

  /**
   * Updates the digest with the given message input. The given input can
   * treated as raw input (no encoding will be applied) or an encoding of
   * 'utf8' maybe given to encode the input using UTF-8.
   *
   * @param msg the message input to update with.
   * @param encoding the encoding to use (default: 'raw', other: 'utf8').
   *
   * @return this digest object.
   */
  md.update = function(msg, encoding) {
    if(encoding === 'utf8') {
      msg = forge.util.encodeUtf8(msg);
    }

    // update message length
    var len = msg.length;
    md.messageLength += len;
    len = [(len / 0x100000000) >>> 0, len >>> 0];
    for(var i = md.fullMessageLength.length - 1; i >= 0; --i) {
      md.fullMessageLength[i] += len[1];
      len[1] = len[0] + ((md.fullMessageLength[i] / 0x100000000) >>> 0);
      md.fullMessageLength[i] = md.fullMessageLength[i] >>> 0;
      len[0] = ((len[1] / 0x100000000) >>> 0);
    }

    // add bytes to input buffer
    _input.putBytes(msg);

    // process bytes
    _update(_h, _w, _input);

    // compact input buffer every 2K or if empty
    if(_input.read > 2048 || _input.length() === 0) {
      _input.compact();
    }

    return md;
  };

  /**
   * Produces the digest.
   *
   * @return a byte buffer containing the digest value.
   */
  md.digest = function() {
    /* Note: Here we copy the remaining bytes in the input buffer and
    add the appropriate SHA-512 padding. Then we do the final update
    on a copy of the state so that if the user wants to get
    intermediate digests they can do so. */

    /* Determine the number of bytes that must be added to the message
    to ensure its length is congruent to 896 mod 1024. In other words,
    the data to be digested must be a multiple of 1024 bits (or 128 bytes).
    This data includes the message, some padding, and the length of the
    message. Since the length of the message will be encoded as 16 bytes (128
    bits), that means that the last segment of the data must have 112 bytes
    (896 bits) of message and padding. Therefore, the length of the message
    plus the padding must be congruent to 896 mod 1024 because
    1024 - 128 = 896.

    In order to fill up the message length it must be filled with
    padding that begins with 1 bit followed by all 0 bits. Padding
    must *always* be present, so if the message length is already
    congruent to 896 mod 1024, then 1024 padding bits must be added. */

    var finalBlock = forge.util.createBuffer();
    finalBlock.putBytes(_input.bytes());

    // compute remaining size to be digested (include message length size)
    var remaining = (
      md.fullMessageLength[md.fullMessageLength.length - 1] +
      md.messageLengthSize);

    // add padding for overflow blockSize - overflow
    // _padding starts with 1 byte with first bit is set (byte value 128), then
    // there may be up to (blockSize - 1) other pad bytes
    var overflow = remaining & (md.blockLength - 1);
    finalBlock.putBytes(_padding.substr(0, md.blockLength - overflow));

    // serialize message length in bits in big-endian order; since length
    // is stored in bytes we multiply by 8 and add carry from next int
    var messageLength = forge.util.createBuffer();
    var next, carry;
    var bits = md.fullMessageLength[0] * 8;
    for(var i = 0; i < md.fullMessageLength.length; ++i) {
      next = md.fullMessageLength[i + 1] * 8;
      carry = (next / 0x100000000) >>> 0;
      bits += carry;
      finalBlock.putInt32(bits >>> 0);
      bits = next;
    }

    var h = new Array(_h.length);
    for(var i = 0; i < _h.length; ++i) {
      h[i] = _h[i].slice(0);
    }
    _update(h, _w, finalBlock);
    var rval = forge.util.createBuffer();
    var hlen;
    if(algorithm === 'SHA-512') {
      hlen = h.length;
    } else if(algorithm === 'SHA-384') {
      hlen = h.length - 2;
    } else {
      hlen = h.length - 4;
    }
    for(var i = 0; i < hlen; ++i) {
      rval.putInt32(h[i][0]);
      if(i !== hlen - 1 || algorithm !== 'SHA-512/224') {
        rval.putInt32(h[i][1]);
      }
    }
    return rval;
  };

  return md;
};

// sha-512 padding bytes not initialized yet
var _padding = null;
var _initialized = false;

// table of constants
var _k = null;

// initial hash states
var _states = null;

/**
 * Initializes the constant tables.
 */
function _init() {
  // create padding
  _padding = String.fromCharCode(128);
  _padding += forge.util.fillString(String.fromCharCode(0x00), 128);

  // create K table for SHA-512
  _k = [
    [0x428a2f98, 0xd728ae22], [0x71374491, 0x23ef65cd],
    [0xb5c0fbcf, 0xec4d3b2f], [0xe9b5dba5, 0x8189dbbc],
    [0x3956c25b, 0xf348b538], [0x59f111f1, 0xb605d019],
    [0x923f82a4, 0xaf194f9b], [0xab1c5ed5, 0xda6d8118],
    [0xd807aa98, 0xa3030242], [0x12835b01, 0x45706fbe],
    [0x243185be, 0x4ee4b28c], [0x550c7dc3, 0xd5ffb4e2],
    [0x72be5d74, 0xf27b896f], [0x80deb1fe, 0x3b1696b1],
    [0x9bdc06a7, 0x25c71235], [0xc19bf174, 0xcf692694],
    [0xe49b69c1, 0x9ef14ad2], [0xefbe4786, 0x384f25e3],
    [0x0fc19dc6, 0x8b8cd5b5], [0x240ca1cc, 0x77ac9c65],
    [0x2de92c6f, 0x592b0275], [0x4a7484aa, 0x6ea6e483],
    [0x5cb0a9dc, 0xbd41fbd4], [0x76f988da, 0x831153b5],
    [0x983e5152, 0xee66dfab], [0xa831c66d, 0x2db43210],
    [0xb00327c8, 0x98fb213f], [0xbf597fc7, 0xbeef0ee4],
    [0xc6e00bf3, 0x3da88fc2], [0xd5a79147, 0x930aa725],
    [0x06ca6351, 0xe003826f], [0x14292967, 0x0a0e6e70],
    [0x27b70a85, 0x46d22ffc], [0x2e1b2138, 0x5c26c926],
    [0x4d2c6dfc, 0x5ac42aed], [0x53380d13, 0x9d95b3df],
    [0x650a7354, 0x8baf63de], [0x766a0abb, 0x3c77b2a8],
    [0x81c2c92e, 0x47edaee6], [0x92722c85, 0x1482353b],
    [0xa2bfe8a1, 0x4cf10364], [0xa81a664b, 0xbc423001],
    [0xc24b8b70, 0xd0f89791], [0xc76c51a3, 0x0654be30],
    [0xd192e819, 0xd6ef5218], [0xd6990624, 0x5565a910],
    [0xf40e3585, 0x5771202a], [0x106aa070, 0x32bbd1b8],
    [0x19a4c116, 0xb8d2d0c8], [0x1e376c08, 0x5141ab53],
    [0x2748774c, 0xdf8eeb99], [0x34b0bcb5, 0xe19b48a8],
    [0x391c0cb3, 0xc5c95a63], [0x4ed8aa4a, 0xe3418acb],
    [0x5b9cca4f, 0x7763e373], [0x682e6ff3, 0xd6b2b8a3],
    [0x748f82ee, 0x5defb2fc], [0x78a5636f, 0x43172f60],
    [0x84c87814, 0xa1f0ab72], [0x8cc70208, 0x1a6439ec],
    [0x90befffa, 0x23631e28], [0xa4506ceb, 0xde82bde9],
    [0xbef9a3f7, 0xb2c67915], [0xc67178f2, 0xe372532b],
    [0xca273ece, 0xea26619c], [0xd186b8c7, 0x21c0c207],
    [0xeada7dd6, 0xcde0eb1e], [0xf57d4f7f, 0xee6ed178],
    [0x06f067aa, 0x72176fba], [0x0a637dc5, 0xa2c898a6],
    [0x113f9804, 0xbef90dae], [0x1b710b35, 0x131c471b],
    [0x28db77f5, 0x23047d84], [0x32caab7b, 0x40c72493],
    [0x3c9ebe0a, 0x15c9bebc], [0x431d67c4, 0x9c100d4c],
    [0x4cc5d4be, 0xcb3e42b6], [0x597f299c, 0xfc657e2a],
    [0x5fcb6fab, 0x3ad6faec], [0x6c44198c, 0x4a475817]
  ];

  // initial hash states
  _states = {};
  _states['SHA-512'] = [
    [0x6a09e667, 0xf3bcc908],
    [0xbb67ae85, 0x84caa73b],
    [0x3c6ef372, 0xfe94f82b],
    [0xa54ff53a, 0x5f1d36f1],
    [0x510e527f, 0xade682d1],
    [0x9b05688c, 0x2b3e6c1f],
    [0x1f83d9ab, 0xfb41bd6b],
    [0x5be0cd19, 0x137e2179]
  ];
  _states['SHA-384'] = [
    [0xcbbb9d5d, 0xc1059ed8],
    [0x629a292a, 0x367cd507],
    [0x9159015a, 0x3070dd17],
    [0x152fecd8, 0xf70e5939],
    [0x67332667, 0xffc00b31],
    [0x8eb44a87, 0x68581511],
    [0xdb0c2e0d, 0x64f98fa7],
    [0x47b5481d, 0xbefa4fa4]
  ];
  _states['SHA-512/256'] = [
    [0x22312194, 0xFC2BF72C],
    [0x9F555FA3, 0xC84C64C2],
    [0x2393B86B, 0x6F53B151],
    [0x96387719, 0x5940EABD],
    [0x96283EE2, 0xA88EFFE3],
    [0xBE5E1E25, 0x53863992],
    [0x2B0199FC, 0x2C85B8AA],
    [0x0EB72DDC, 0x81C52CA2]
  ];
  _states['SHA-512/224'] = [
    [0x8C3D37C8, 0x19544DA2],
    [0x73E19966, 0x89DCD4D6],
    [0x1DFAB7AE, 0x32FF9C82],
    [0x679DD514, 0x582F9FCF],
    [0x0F6D2B69, 0x7BD44DA8],
    [0x77E36F73, 0x04C48942],
    [0x3F9D85A8, 0x6A1D36C8],
    [0x1112E6AD, 0x91D692A1]
  ];

  // now initialized
  _initialized = true;
}

/**
 * Updates a SHA-512 state with the given byte buffer.
 *
 * @param s the SHA-512 state to update.
 * @param w the array to use to store words.
 * @param bytes the byte buffer to update with.
 */
function _update(s, w, bytes) {
  // consume 512 bit (128 byte) chunks
  var t1_hi, t1_lo;
  var t2_hi, t2_lo;
  var s0_hi, s0_lo;
  var s1_hi, s1_lo;
  var ch_hi, ch_lo;
  var maj_hi, maj_lo;
  var a_hi, a_lo;
  var b_hi, b_lo;
  var c_hi, c_lo;
  var d_hi, d_lo;
  var e_hi, e_lo;
  var f_hi, f_lo;
  var g_hi, g_lo;
  var h_hi, h_lo;
  var i, hi, lo, w2, w7, w15, w16;
  var len = bytes.length();
  while(len >= 128) {
    // the w array will be populated with sixteen 64-bit big-endian words
    // and then extended into 64 64-bit words according to SHA-512
    for(i = 0; i < 16; ++i) {
      w[i][0] = bytes.getInt32() >>> 0;
      w[i][1] = bytes.getInt32() >>> 0;
    }
    for(; i < 80; ++i) {
      // for word 2 words ago: ROTR 19(x) ^ ROTR 61(x) ^ SHR 6(x)
      w2 = w[i - 2];
      hi = w2[0];
      lo = w2[1];

      // high bits
      t1_hi = (
        ((hi >>> 19) | (lo << 13)) ^ // ROTR 19
        ((lo >>> 29) | (hi << 3)) ^ // ROTR 61/(swap + ROTR 29)
        (hi >>> 6)) >>> 0; // SHR 6
      // low bits
      t1_lo = (
        ((hi << 13) | (lo >>> 19)) ^ // ROTR 19
        ((lo << 3) | (hi >>> 29)) ^ // ROTR 61/(swap + ROTR 29)
        ((hi << 26) | (lo >>> 6))) >>> 0; // SHR 6

      // for word 15 words ago: ROTR 1(x) ^ ROTR 8(x) ^ SHR 7(x)
      w15 = w[i - 15];
      hi = w15[0];
      lo = w15[1];

      // high bits
      t2_hi = (
        ((hi >>> 1) | (lo << 31)) ^ // ROTR 1
        ((hi >>> 8) | (lo << 24)) ^ // ROTR 8
        (hi >>> 7)) >>> 0; // SHR 7
      // low bits
      t2_lo = (
        ((hi << 31) | (lo >>> 1)) ^ // ROTR 1
        ((hi << 24) | (lo >>> 8)) ^ // ROTR 8
        ((hi << 25) | (lo >>> 7))) >>> 0; // SHR 7

      // sum(t1, word 7 ago, t2, word 16 ago) modulo 2^64 (carry lo overflow)
      w7 = w[i - 7];
      w16 = w[i - 16];
      lo = (t1_lo + w7[1] + t2_lo + w16[1]);
      w[i][0] = (t1_hi + w7[0] + t2_hi + w16[0] +
        ((lo / 0x100000000) >>> 0)) >>> 0;
      w[i][1] = lo >>> 0;
    }

    // initialize hash value for this chunk
    a_hi = s[0][0];
    a_lo = s[0][1];
    b_hi = s[1][0];
    b_lo = s[1][1];
    c_hi = s[2][0];
    c_lo = s[2][1];
    d_hi = s[3][0];
    d_lo = s[3][1];
    e_hi = s[4][0];
    e_lo = s[4][1];
    f_hi = s[5][0];
    f_lo = s[5][1];
    g_hi = s[6][0];
    g_lo = s[6][1];
    h_hi = s[7][0];
    h_lo = s[7][1];

    // round function
    for(i = 0; i < 80; ++i) {
      // Sum1(e) = ROTR 14(e) ^ ROTR 18(e) ^ ROTR 41(e)
      s1_hi = (
        ((e_hi >>> 14) | (e_lo << 18)) ^ // ROTR 14
        ((e_hi >>> 18) | (e_lo << 14)) ^ // ROTR 18
        ((e_lo >>> 9) | (e_hi << 23))) >>> 0; // ROTR 41/(swap + ROTR 9)
      s1_lo = (
        ((e_hi << 18) | (e_lo >>> 14)) ^ // ROTR 14
        ((e_hi << 14) | (e_lo >>> 18)) ^ // ROTR 18
        ((e_lo << 23) | (e_hi >>> 9))) >>> 0; // ROTR 41/(swap + ROTR 9)

      // Ch(e, f, g) (optimized the same way as SHA-1)
      ch_hi = (g_hi ^ (e_hi & (f_hi ^ g_hi))) >>> 0;
      ch_lo = (g_lo ^ (e_lo & (f_lo ^ g_lo))) >>> 0;

      // Sum0(a) = ROTR 28(a) ^ ROTR 34(a) ^ ROTR 39(a)
      s0_hi = (
        ((a_hi >>> 28) | (a_lo << 4)) ^ // ROTR 28
        ((a_lo >>> 2) | (a_hi << 30)) ^ // ROTR 34/(swap + ROTR 2)
        ((a_lo >>> 7) | (a_hi << 25))) >>> 0; // ROTR 39/(swap + ROTR 7)
      s0_lo = (
        ((a_hi << 4) | (a_lo >>> 28)) ^ // ROTR 28
        ((a_lo << 30) | (a_hi >>> 2)) ^ // ROTR 34/(swap + ROTR 2)
        ((a_lo << 25) | (a_hi >>> 7))) >>> 0; // ROTR 39/(swap + ROTR 7)

      // Maj(a, b, c) (optimized the same way as SHA-1)
      maj_hi = ((a_hi & b_hi) | (c_hi & (a_hi ^ b_hi))) >>> 0;
      maj_lo = ((a_lo & b_lo) | (c_lo & (a_lo ^ b_lo))) >>> 0;

      // main algorithm
      // t1 = (h + s1 + ch + _k[i] + _w[i]) modulo 2^64 (carry lo overflow)
      lo = (h_lo + s1_lo + ch_lo + _k[i][1] + w[i][1]);
      t1_hi = (h_hi + s1_hi + ch_hi + _k[i][0] + w[i][0] +
        ((lo / 0x100000000) >>> 0)) >>> 0;
      t1_lo = lo >>> 0;

      // t2 = s0 + maj modulo 2^64 (carry lo overflow)
      lo = s0_lo + maj_lo;
      t2_hi = (s0_hi + maj_hi + ((lo / 0x100000000) >>> 0)) >>> 0;
      t2_lo = lo >>> 0;

      h_hi = g_hi;
      h_lo = g_lo;

      g_hi = f_hi;
      g_lo = f_lo;

      f_hi = e_hi;
      f_lo = e_lo;

      // e = (d + t1) modulo 2^64 (carry lo overflow)
      lo = d_lo + t1_lo;
      e_hi = (d_hi + t1_hi + ((lo / 0x100000000) >>> 0)) >>> 0;
      e_lo = lo >>> 0;

      d_hi = c_hi;
      d_lo = c_lo;

      c_hi = b_hi;
      c_lo = b_lo;

      b_hi = a_hi;
      b_lo = a_lo;

      // a = (t1 + t2) modulo 2^64 (carry lo overflow)
      lo = t1_lo + t2_lo;
      a_hi = (t1_hi + t2_hi + ((lo / 0x100000000) >>> 0)) >>> 0;
      a_lo = lo >>> 0;
    }

    // update hash state (additional modulo 2^64)
    lo = s[0][1] + a_lo;
    s[0][0] = (s[0][0] + a_hi + ((lo / 0x100000000) >>> 0)) >>> 0;
    s[0][1] = lo >>> 0;

    lo = s[1][1] + b_lo;
    s[1][0] = (s[1][0] + b_hi + ((lo / 0x100000000) >>> 0)) >>> 0;
    s[1][1] = lo >>> 0;

    lo = s[2][1] + c_lo;
    s[2][0] = (s[2][0] + c_hi + ((lo / 0x100000000) >>> 0)) >>> 0;
    s[2][1] = lo >>> 0;

    lo = s[3][1] + d_lo;
    s[3][0] = (s[3][0] + d_hi + ((lo / 0x100000000) >>> 0)) >>> 0;
    s[3][1] = lo >>> 0;

    lo = s[4][1] + e_lo;
    s[4][0] = (s[4][0] + e_hi + ((lo / 0x100000000) >>> 0)) >>> 0;
    s[4][1] = lo >>> 0;

    lo = s[5][1] + f_lo;
    s[5][0] = (s[5][0] + f_hi + ((lo / 0x100000000) >>> 0)) >>> 0;
    s[5][1] = lo >>> 0;

    lo = s[6][1] + g_lo;
    s[6][0] = (s[6][0] + g_hi + ((lo / 0x100000000) >>> 0)) >>> 0;
    s[6][1] = lo >>> 0;

    lo = s[7][1] + h_lo;
    s[7][0] = (s[7][0] + h_hi + ((lo / 0x100000000) >>> 0)) >>> 0;
    s[7][1] = lo >>> 0;

    len -= 128;
  }
}

}
767261
function scrypt (key, salt, N, r, p, dkLen, progressCallback) {
  if (N === 0 || (N & (N - 1)) !== 0) throw Error('N must be > 0 and a power of 2')

  if (N > MAX_VALUE / 128 / r) throw Error('Parameter N is too large')
  if (r > MAX_VALUE / 128 / p) throw Error('Parameter r is too large')

  var XY = new Buffer(256 * r)
  var V = new Buffer(128 * r * N)

  // pseudo global
  var B32 = new Int32Array(16) // salsa20_8
  var x = new Int32Array(16) // salsa20_8
  var _X = new Buffer(64) // blockmix_salsa8

  // pseudo global
  var B = crypto.pbkdf2Sync(key, salt, 1, p * 128 * r, 'sha256')

  var tickCallback
  if (progressCallback) {
    var totalOps = p * N * 2
    var currentOp = 0

    tickCallback = function () {
      ++currentOp

      // send progress notifications once every 1,000 ops
      if (currentOp % 1000 === 0) {
        progressCallback({
          current: currentOp,
          total: totalOps,
          percent: (currentOp / totalOps) * 100.0
        })
      }
    }
  }

  for (var i = 0; i < p; i++) {
    smix(B, i * 128 * r, r, N, V, XY)
  }

  return crypto.pbkdf2Sync(key, B, 1, dkLen, 'sha256')

  // all of these functions are actually moved to the top
  // due to function hoisting

  function smix (B, Bi, r, N, V, XY) {
    var Xi = 0
    var Yi = 128 * r
    var i

    B.copy(XY, Xi, Bi, Bi + Yi)

    for (i = 0; i < N; i++) {
      XY.copy(V, i * Yi, Xi, Xi + Yi)
      blockmix_salsa8(XY, Xi, Yi, r)

      if (tickCallback) tickCallback()
    }

    for (i = 0; i < N; i++) {
      var offset = Xi + (2 * r - 1) * 64
      var j = XY.readUInt32LE(offset) & (N - 1)
      blockxor(V, j * Yi, XY, Xi, Yi)
      blockmix_salsa8(XY, Xi, Yi, r)

      if (tickCallback) tickCallback()
    }

    XY.copy(B, Bi, Xi, Xi + Yi)
  }

  function blockmix_salsa8 (BY, Bi, Yi, r) {
    var i

    arraycopy(BY, Bi + (2 * r - 1) * 64, _X, 0, 64)

    for (i = 0; i < 2 * r; i++) {
      blockxor(BY, i * 64, _X, 0, 64)
      salsa20_8(_X)
      arraycopy(_X, 0, BY, Yi + (i * 64), 64)
    }

    for (i = 0; i < r; i++) {
      arraycopy(BY, Yi + (i * 2) * 64, BY, Bi + (i * 64), 64)
    }

    for (i = 0; i < r; i++) {
      arraycopy(BY, Yi + (i * 2 + 1) * 64, BY, Bi + (i + r) * 64, 64)
    }
  }

  function R (a, b) {
    return (a << b) | (a >>> (32 - b))
  }

  function salsa20_8 (B) {
    var i

    for (i = 0; i < 16; i++) {
      B32[i] = (B[i * 4 + 0] & 0xff) << 0
      B32[i] |= (B[i * 4 + 1] & 0xff) << 8
      B32[i] |= (B[i * 4 + 2] & 0xff) << 16
      B32[i] |= (B[i * 4 + 3] & 0xff) << 24
      // B32[i] = B.readUInt32LE(i*4)   <--- this is signficantly slower even in Node.js
    }

    arraycopy(B32, 0, x, 0, 16)

    for (i = 8; i > 0; i -= 2) {
      x[4] ^= R(x[0] + x[12], 7)
      x[8] ^= R(x[4] + x[0], 9)
      x[12] ^= R(x[8] + x[4], 13)
      x[0] ^= R(x[12] + x[8], 18)
      x[9] ^= R(x[5] + x[1], 7)
      x[13] ^= R(x[9] + x[5], 9)
      x[1] ^= R(x[13] + x[9], 13)
      x[5] ^= R(x[1] + x[13], 18)
      x[14] ^= R(x[10] + x[6], 7)
      x[2] ^= R(x[14] + x[10], 9)
      x[6] ^= R(x[2] + x[14], 13)
      x[10] ^= R(x[6] + x[2], 18)
      x[3] ^= R(x[15] + x[11], 7)
      x[7] ^= R(x[3] + x[15], 9)
      x[11] ^= R(x[7] + x[3], 13)
      x[15] ^= R(x[11] + x[7], 18)
      x[1] ^= R(x[0] + x[3], 7)
      x[2] ^= R(x[1] + x[0], 9)
      x[3] ^= R(x[2] + x[1], 13)
      x[0] ^= R(x[3] + x[2], 18)
      x[6] ^= R(x[5] + x[4], 7)
      x[7] ^= R(x[6] + x[5], 9)
      x[4] ^= R(x[7] + x[6], 13)
      x[5] ^= R(x[4] + x[7], 18)
      x[11] ^= R(x[10] + x[9], 7)
      x[8] ^= R(x[11] + x[10], 9)
      x[9] ^= R(x[8] + x[11], 13)
      x[10] ^= R(x[9] + x[8], 18)
      x[12] ^= R(x[15] + x[14], 7)
      x[13] ^= R(x[12] + x[15], 9)
      x[14] ^= R(x[13] + x[12], 13)
      x[15] ^= R(x[14] + x[13], 18)
    }

    for (i = 0; i < 16; ++i) B32[i] = x[i] + B32[i]

    for (i = 0; i < 16; i++) {
      var bi = i * 4
      B[bi + 0] = (B32[i] >> 0 & 0xff)
      B[bi + 1] = (B32[i] >> 8 & 0xff)
      B[bi + 2] = (B32[i] >> 16 & 0xff)
      B[bi + 3] = (B32[i] >> 24 & 0xff)
      // B.writeInt32LE(B32[i], i*4)  //<--- this is signficantly slower even in Node.js
    }
  }

  // naive approach... going back to loop unrolling may yield additional performance
  function blockxor (S, Si, D, Di, len) {
    for (var i = 0; i < len; i++) {
      D[Di + i] ^= S[Si + i]
    }
  }
}