internal static void key_derive(byte[] shared, byte[] salt, byte[] secretKey, byte[] pubkey) { var longKeyHash = new byte[64]; var shortKeyHash = new byte[32]; Array.Reverse(secretKey); // compute Sha3(512) hash of secret key (as in prepareForScalarMultiply) var digestSha3 = new KeccakDigest(512); digestSha3.BlockUpdate(secretKey, 0, 32); digestSha3.DoFinal(longKeyHash, 0); longKeyHash[0] &= 248; longKeyHash[31] &= 127; longKeyHash[31] |= 64; Array.Copy(longKeyHash, 0, shortKeyHash, 0, 32); ScalarOperations.sc_clamp(shortKeyHash, 0); var p = new[] { new long[16], new long[16], new long[16], new long[16] }; var q = new[] { new long[16], new long[16], new long[16], new long[16] }; TweetNaCl.Unpackneg(q, pubkey); // returning -1 invalid signature TweetNaCl.Scalarmult(p, q, shortKeyHash, 0); TweetNaCl.Pack(shared, p); // for some reason the most significant bit of the last byte needs to be flipped. // doesnt seem to be any corrosponding action in nano/nem.core, so this may be an issue in one of the above 3 functions. i have no idea. shared[31] ^= (1 << 7); // salt for (var i = 0; i < salt.Length; i++) { shared[i] ^= salt[i]; } // hash salted shared key var digestSha3Two = new KeccakDigest(256); digestSha3Two.BlockUpdate(shared, 0, 32); digestSha3Two.DoFinal(shared, 0); }