Example #1
0
        /// <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();
            }
        }
Example #2
0
 /// <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(ReadOnlySpan <byte> publicKey, ReadOnlySpan <byte> privateKey, EcdhHashFunction hashFunction, IntPtr data, out byte[] resultOutput)
 {
     resultOutput = new byte[SECRET_LENGTH];
     return(Ecdh(publicKey, privateKey, hashFunction, data, resultOutput));
 }