public static unsafe bool Ecdh(byte[] agreement, byte[] publicKey, byte[] privateKey) { int outputLength = agreement.Length; // TODO: should probably do that only once secp256k1_ecdh_hash_function hashFunctionPtr = (void *output, void *x, void *y, IntPtr d) => { Span <byte> outputSpan = new Span <byte>(output, outputLength); Span <byte> xSpan = new Span <byte>(x, 32); if (xSpan.Length < 32) { return(0); } xSpan.CopyTo(outputSpan); return(1); }; GCHandle gch = GCHandle.Alloc(hashFunctionPtr); try { IntPtr fp = Marshal.GetFunctionPointerForDelegate(hashFunctionPtr); { return(secp256k1_ecdh(Context, agreement, publicKey, privateKey, fp, IntPtr.Zero)); } } finally { gch.Free(); } }
public static unsafe bool Ecdh(byte[] agreement, byte[] publicKey, byte[] privateKey) { int outputLength = agreement.Length; secp256k1_ecdh_hash_function hashFunctionPtr = (void *output, void *x, void *y, IntPtr d) => { var outputSpan = new Span <byte>(output, outputLength); var xSpan = new Span <byte>(x, 32); if (xSpan.Length < 32) { return(0); } xSpan.CopyTo(outputSpan); return(1); }; GCHandle gch = GCHandle.Alloc(hashFunctionPtr); try { IntPtr fp = Marshal.GetFunctionPointerForDelegate(hashFunctionPtr); { return(Platform == OsPlatform.Windows ? Win64Lib.secp256k1_ecdh(Context, agreement, publicKey, privateKey, fp, IntPtr.Zero) : Platform == OsPlatform.Linux ? PosixLib.secp256k1_ecdh(Context, agreement, publicKey, privateKey, fp, IntPtr.Zero) : MacLib.secp256k1_ecdh(Context, agreement, publicKey, privateKey, fp, IntPtr.Zero)); } } finally { gch.Free(); } }
/// <summary> /// Compute an EC Diffie-Hellman secret in constant time. /// </summary> /// <param name="resultOutput">A 32-byte array which will be populated by an ECDH secret computed from the point and scalar.</param> /// <param name="publicKey">A secp256k1_pubkey containing an initialized public key.</param> /// <param name="privateKey">A 32-byte scalar with which to multiply the point.</param> /// <param name="hashFunction">Pointer to a hash function. If null, sha256 is used.</param> /// <param name="data">Arbitrary data that is passed through.</param> /// <returns>True if exponentiation was successful, false if scalar was invalid (zero or overflow).</returns> public bool Ecdh(Span <byte> resultOutput, Span <byte> publicKey, Span <byte> privateKey, EcdhHashFunction hashFunction, IntPtr data) { if (resultOutput.Length < SECRET_LENGTH) { throw new ArgumentException($"{nameof(resultOutput)} must be {SECRET_LENGTH} bytes"); } if (publicKey.Length < PUBKEY_LENGTH) { throw new ArgumentException($"{nameof(publicKey)} must be {PUBKEY_LENGTH} bytes"); } if (privateKey.Length < PRIVKEY_LENGTH) { throw new ArgumentException($"{nameof(privateKey)} must be {PRIVKEY_LENGTH} bytes"); } int outputLength = resultOutput.Length; secp256k1_ecdh_hash_function hashFunctionPtr = (void *output, void *x, void *y, IntPtr d) => { var outputSpan = new Span <byte>(output, outputLength); var xSpan = new Span <byte>(x, 32); var ySpan = new Span <byte>(y, 32); return(hashFunction(outputSpan, xSpan, ySpan, d)); }; GCHandle gch = GCHandle.Alloc(hashFunctionPtr); try { var fp = Marshal.GetFunctionPointerForDelegate(hashFunctionPtr); fixed(byte *resPtr = &MemoryMarshal.GetReference(resultOutput), pubPtr = &MemoryMarshal.GetReference(publicKey), privPtr = &MemoryMarshal.GetReference(privateKey)) { return(secp256k1_ecdh.Value(_ctx, resPtr, pubPtr, privPtr, fp, data) == 1); } } finally { gch.Free(); } }