Esempio n. 1
0
        /// <summary>
        /// Hash structured data
        /// </summary>
        /// <typeparam name="T">Structured data datatype</typeparam>
        /// <param name="structure">Structured data to hash</param>
        /// <param name="domain">EIP-712 domain</param>
        /// <returns>Keccak256 of encoded data</returns>
        /// <exception cref="ArgumentNullException"><paramref name="domain"/> or <paramref name="structure"/>
        /// is equal to <c>null</c></exception>
        public static byte[] Hash <T>(T structure, EIP712Domain domain) where T : class
        {
            if (structure == null)
            {
                throw new ArgumentNullException(nameof(structure));
            }
            if (domain == null)
            {
                throw new ArgumentNullException(nameof(domain));
            }

            return(_keccak.CalculateHash(Encode(structure, domain)));
        }
Esempio n. 2
0
        /// <summary>
        /// Encodes structured data according to EIP-712 specification
        /// </summary>
        /// <typeparam name="T">Structured data datatype</typeparam>
        /// <param name="structure">Structured data to encode</param>
        /// <param name="domain">EIP-712 domain</param>
        /// <returns>Encoded data</returns>
        /// <exception cref="ArgumentNullException"><paramref name="structure"/> or <paramref name="domain"/> is equal to <c>null</c></exception>
        public static byte[] Encode <T>(T structure, EIP712Domain domain) where T : class
        {
            if (domain == null)
            {
                throw new ArgumentNullException(nameof(structure));
            }
            if (domain == null)
            {
                throw new ArgumentNullException(nameof(domain));
            }

            byte[] domainSeparator = HashStruct(domain);
            byte[] hash            = HashStruct(structure);
            byte[] result          = ByteUtil.Merge(_eip191Header, domainSeparator, hash);
            return(result);
        }
Esempio n. 3
0
        /// <summary>
        /// Verify signature
        /// </summary>
        /// <typeparam name="T">Structured data datatype</typeparam>
        /// <param name="structure">Structured data for which to verify signature</param>
        /// <param name="domain">EIP-712 domain</param>
        /// <param name="signerAddress">Ethereum address</param>
        /// <param name="signature">Signature of the structured data</param>
        /// <returns><c>true</c> if signature is valid <c>false</c> otherwise</returns>
        /// <exception cref="ArgumentNullException">Any of the arguments is equal to <c>null</c></exception>
        /// <exception cref="ArgumentException">Invalid Ethereum address</exception>
        public static bool VerifySignature <T>(T structure, EIP712Domain domain, string signerAddress, byte[] signature) where T : class
        {
            structure     = structure ?? throw new ArgumentNullException(nameof(structure));
            domain        = domain ?? throw new ArgumentNullException(nameof(domain));
            signerAddress = signerAddress ?? throw new ArgumentNullException(nameof(signerAddress));
            signature     = signature ?? throw new ArgumentNullException(nameof(signature));

            if (!AddressUtil.Current.IsValidEthereumAddressHexFormat(signerAddress))
            {
                throw new ArgumentException("Invalid ethereum address", nameof(signerAddress));
            }

            string recoveredAddress = _signer.EcRecover(Hash(structure, domain), signature.ToHex(true));

            return(AddressUtil.Current.AreAddressesTheSame(recoveredAddress, signerAddress));
        }
Esempio n. 4
0
        /// <summary>
        /// Sign structured data
        /// </summary>
        /// <typeparam name="T">Structured data datatype</typeparam>
        /// <param name="structure">Structured data to sign</param>
        /// <param name="domain">EIP-712 domain</param>
        /// <param name="privateKey">Ethereum private key</param>
        /// <returns><see cref="EthereumSignature"/></returns>
        /// <exception cref="ArgumentNullException">Any of the arguments is equal to <c>null</c></exception>
        public static EthereumSignature Sign <T>(T structure, EIP712Domain domain, string privateKey) where T : class
        {
            if (structure == null)
            {
                throw new ArgumentNullException(nameof(structure));
            }
            if (domain == null)
            {
                throw new ArgumentNullException(nameof(domain));
            }
            if (privateKey == null)
            {
                throw new ArgumentNullException(nameof(privateKey));
            }

            EthECDSASignature sig = _signer.SignAndCalculateV(Hash(structure, domain), privateKey);

            // Returning custom type since we do not want force lib users to install additional package  (i.e. Nethereum)
            return(new EthereumSignature(Util.PadBytes(sig.R, 32), Util.PadBytes(sig.S, 32), sig.V));
        }