_section: Hashing Algorithms @ There are many hashing algorithms used throughout the blockchain space as well as some more complex usages which require utilities to facilitate these common operations. _subsection: Cryptographic Hash Functions @ The [Cryptographic Hash Functions](link-wiki-cryptographichash) are a specific family of hash functions. _property: ethers.utils.id(text) => string<[[DataHexString]]<32>> @ @SRC The Ethereum Identity function computes the [KECCAK256](link-wiki-sha3) hash of the //text// bytes. _property: ethers.utils.keccak256(aBytesLike) => string<[[DataHexString]]<32>> @ @SRC Returns the [KECCAK256](link-wiki-sha3) digest //aBytesLike//. _property: ethers.utils.ripemd160(aBytesLike) => string<[[DataHexString]]<20>> @ @SRC Returns the [RIPEMD-160](link-wiki-ripemd) digest of //aBytesLike//. _property: ethers.utils.sha256(aBytesLike) => string<[[DataHexString]]<32>> @ @SRC Returns the [SHA2-256](link-wiki-sha2) digest of //aBytesLike//. _property: ethers.utils.sha512(aBytesLike) => string<[[DataHexString]]<64>> @ @SRC Returns the [SHA2-512](link-wiki-sha2) digest of //aBytesLike//. _code: KECCAK256 @lang utils.keccak256([ 0x12, 0x34 ]) //! utils.keccak256("0x") //! utils.keccak256("0x1234") //! // The value MUST be data, such as: // - an Array of numbers // - a data hex string (e.g. "0x1234") // - a Uint8Array // Do NOT use UTF-8 strings that are not a DataHexstring utils.keccak256("hello world") //! error // If needed, convert strings to bytes first: utils.keccak256(utils.toUtf8Bytes("hello world")) //! // Or equivalently use the identity function: utils.id("hello world") //! // Keep in mind that the string "0x1234" represents TWO // bytes (i.e. [ 0x12, 0x34 ]. If you wish to compute the // hash of the 6 characters "0x1234", convert it to UTF-8 // bytes first using utils.toUtf8Bytes. // Consider the following examples: // Hash of TWO (2) bytes: utils.keccak256("0x1234") //! // Hash of TWO (2) bytes: (same result) utils.keccak256([ 0x12, 0x34 ]) //! const bytes = utils.toUtf8Bytes("0x1234") // bytes // //! // Hash of SIX (6) characters (different than above) utils.keccak256(bytes) //! // Hash of SIX (6) characters (same result) utils.id("0x1234") //! _code: RIPEMD160 @lang utils.ripemd160("0x") //! utils.ripemd160("0x1234") //! _code: SHA-2 @lang utils.sha256("0x") //! utils.sha256("0x1234") //! utils.sha512("0x") //! utils.sha512("0x1234") //! _subsection: HMAC @ _property: ethers.utils.computeHmac(algorithm, key, data) => string<[[DataHexString]]> @ @SRC Returns the [HMAC](link-wiki-hmac) of //data// with //key// using the [Algorithm](utils--hmac-supported-algorithm) //algorithm//. _heading: **HMAC Supported Algorithms** @ @SRC _property: ethers.utils.SupportedAlgorithm.sha256 => string Use the [SHA2-256](link-wiki-sha2) hash algorithm. _property: ethers.utils.SupportedAlgorithm.sha512 => string Use the [SHA2-512](link-wiki-sha2) hash algorithm. _code: HMAC @lang const key = "0x0102" const data = "0x1234" utils.computeHmac("sha256", key, data) //! _subsection: Hashing Helpers @ _property: ethers.utils.hashMessage(message) => string<[[DataHexString]]<32>> @ @SRC Computes the [[link-eip-191]] personal message digest of //message//. Personal messages are converted to UTF-8 bytes and prefixed with ``\\x19Ethereum Signed Message:`` and the length of //message//. _code: Hashing Messages @lang // Hashing a string message utils.hashMessage("Hello World") //! // Hashing binary data (also "Hello World", but as bytes) utils.hashMessage( [ 72, 101, 108, 108, 111, 32, 87, 111, 114, 108, 100 ]) //! // NOTE: It is important to understand how strings and binary // data is handled differently. A string is ALWAYS processed // as the bytes of the string, so a hexstring MUST be // converted to an ArrayLike object first. // Hashing a hex string is the same as hashing a STRING // Note: this is the hash of the 4 characters [ '0', 'x', '4', '2' ] utils.hashMessage("0x42") //! // Hashing the binary data // Note: this is the hash of the 1 byte [ 0x42 ] utils.hashMessage([ 0x42 ]) //! // Hashing the binary data // Note: similarly, this is the hash of the 1 byte [ 0x42 ] utils.hashMessage(utils.arrayify("0x42")) //! _property: ethers.utils.namehash(name) => string<[[DataHexString]]<32>> @ @SRC Returns the [ENS Namehash](link-namehash) of //name//. _code: Namehash @lang utils.namehash("") //! utils.namehash("eth") //! utils.namehash("ricmoo.firefly.eth") //! utils.namehash("ricmoo.xyz") //! _heading: Typed Data Encoder @ @SRC The **TypedDataEncoder** is used to compute the various encoded data required for [[link-eip-712]] signed data. Signed data requires a domain, list of structures and their members and the data itself. The **domain** is an object with values for any of the standard domain properties. The **types** is an object with each property being the name of a structure, mapping to an array of field descriptions. It should **not** include the ``EIP712Domain`` property unless it is required as a child structure of another. _note: Experimental Feature (this exported class name will change) This is still an experimental feature. If using it, please specify the **exact** version of ethers you are using (e.g. spcify ``"5.0.18"``, **not** ``"^5.0.18"``) as the exported class name will be renamed from ``_TypedDataEncoder`` to ``TypedDataEncoder`` once it has been used in the field a bit. _property: ethers.utils._TypedDataEncoder.from(types) => [TypedDataEncoder] @ @SRC Creates a new **TypedDataEncoder** for //types//. This object is a fairly low-level object that most developers should not require using instances directly. Most developers will find the static class methods below the most useful. _property: TypedDataEncoder.encode(domain, types, values) => string @ @SRC Encodes the Returns the hashed [[link-eip-712]] domain. _property: TypedDataEncoder.getPayload(domain, types, value) => any @ @SRC Returns the standard payload used by various JSON-RPC ``eth_signTypedData*`` calls. All domain values and entries in value are normalized and the types are verified. _property: TypedDataEncoder.getPrimaryType(types) => string @ @SRC Constructs a directed acyclic graph of the types and returns the root type, which can be used as the **primaryType** for [[link-eip-712]] payloads. _property: TypedDataEncoder.hash(domain, types, values) => string<[[DataHexString]]<32>> @ @SRC Returns the computed [[link-eip-712]] hash. _property: TypedDataEncoder.hashDomain(domain) => string<[[DataHexString]]<32>> @ @SRC Returns the hashed [[link-eip-712]] domain. _property: TypedDataEncoder.resolveNames(domain, types, value, resolveName) => Promise @ @SRC Returns a copy of value, where any leaf value with a type of ``address`` will have been recursively replacedwith the value of calling //resolveName// with that value. _code: Typed Data Example @lang // TypedDataEncoder = ethers.utils._TypedDataEncoder // const domain = { name: 'Ether Mail', version: '1', chainId: 1, verifyingContract: '0xCcCCccccCCCCcCCCCCCcCcCccCcCCCcCcccccccC' } // The named list of all type definitions const types = { Person: [ { name: 'name', type: 'string' }, { name: 'wallet', type: 'address' } ], Mail: [ { name: 'from', type: 'Person' }, { name: 'to', type: 'Person' }, { name: 'contents', type: 'string' } ] } // The data to sign const value = { from: { name: 'Cow', wallet: '0xCD2a3d9F938E13CD947Ec05AbC7FE734Df8DD826' }, to: { name: 'Bob', wallet: '0xbBbBBBBbbBBBbbbBbbBbbbbBBbBbbbbBbBbbBBbB' }, contents: 'Hello, Bob!' } TypedDataEncoder.encode(domain, types, value) //! TypedDataEncoder.getPayload(domain, types, value) //! TypedDataEncoder.getPrimaryType(types) //! TypedDataEncoder.hash(domain, types, value) //! TypedDataEncoder.hashDomain(domain) //! _subsection: Solidity Hashing Algorithms @ When using the Solidity ``abi.packEncoded(...)`` function, a non-standard //tightly packed// version of encoding is used. These functions implement the tightly packing algorithm. _property: ethers.utils.solidityPack(types, values) => string<[[DataHexString]]> @ @SRC Returns the non-standard encoded //values// packed according to their respective type in //types//. _property: ethers.utils.solidityKeccak256(types, values) => string<[[DataHexString]]<32>> @ @SRC Returns the [KECCAK256](link-wiki-sha3) of the non-standard encoded //values// packed according to their respective type in //types//. _property: ethers.utils.soliditySha256(types, values) => string<[[DataHexString]]<32>> @ @SRC Returns the [SHA2-256](link-wiki-sha2) of the non-standard encoded //values// packed according to their respective type in //types//. _code: Solidity Hashing @lang utils.solidityPack([ "int16", "uint48" ], [ -1, 12 ]) //! utils.solidityPack([ "string", "uint8" ], [ "Hello", 3 ]) //! utils.solidityKeccak256([ "int16", "uint48" ], [ -1, 12 ]) //! utils.soliditySha256([ "int16", "uint48" ], [ -1, 12 ]) //! // As a short example of the non-distinguished nature of // Solidity tight-packing (which is why it is inappropriate // for many things from a security point of view), consider // the following examples are all equal, despite representing // very different values and layouts. utils.solidityPack([ "string", "string" ], [ "hello", "world01" ]) //! utils.solidityPack([ "string", "string" ], [ "helloworld", "01" ]) //! utils.solidityPack([ "string", "string", "uint16" ], [ "hell", "oworld", 0x3031 ]) //! utils.solidityPack([ "uint96" ], [ "32309054545061485574011236401" ]) //!