_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 //_result: utils.keccak256([ 0x12, 0x34 ]) //_log: //_result: utils.keccak256("0x") //_log: //_result: utils.keccak256("0x1234") //_log: // 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 //_throws: utils.keccak256("hello world") //_log: // If needed, convert strings to bytes first: //_result: utils.keccak256(utils.toUtf8Bytes("hello world")) //_log: // Or equivalently use the identity function: //_result: utils.id("hello world") //_log: // 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: //_result: utils.keccak256("0x1234") //_log: // Hash of TWO (2) bytes: (same result) //_result: utils.keccak256([ 0x12, 0x34 ]) //_log: //_result: bytes = utils.toUtf8Bytes("0x1234") //_log: // Hash of SIX (6) characters (different than above) //_result: utils.keccak256(bytes) //_log: // Hash of SIX (6) characters (same result) //_result: utils.id("0x1234") //_log: _code: RIPEMD160 @lang //_result: utils.ripemd160("0x") //_log: //_result: utils.ripemd160("0x1234") //_log: _code: SHA-2 @lang //_result: utils.sha256("0x") //_log: //_result: utils.sha256("0x1234") //_log: //_result: utils.sha512("0x") //_log: //_result: utils.sha512("0x1234") //_log: _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" //_result: utils.computeHmac("sha256", key, data) //_log: _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 //_result: utils.hashMessage("Hello World") //_log: // Hashing binary data (also "Hello World", but as bytes) //_result: utils.hashMessage( [ 72, 101, 108, 108, 111, 32, 87, 111, 114, 108, 100 ]) //_log: // 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' ] //_result: utils.hashMessage("0x42") //_log: // Hashing the binary data // Note: this is the hash of the 1 byte [ 0x42 ] //_result: utils.hashMessage([ 0x42 ]) //_log: // Hashing the binary data // Note: similarly, this is the hash of the 1 byte [ 0x42 ] //_result: utils.hashMessage(utils.arrayify("0x42")) //_log: _property: ethers.utils.namehash(name) => string<[[DataHexString]]<32>> @ @SRC Returns the [ENS Namehash](link-namehash) of //name//. _code: Namehash @lang //_result: utils.namehash("") //_log: //_result: utils.namehash("eth") //_log: //_result: utils.namehash("ricmoo.firefly.eth") //_log: //_result: utils.namehash("ricmoo.xyz") //_log: _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 //_hide: TypedDataEncoder = ethers.utils._TypedDataEncoder domain = { name: 'Ether Mail', version: '1', chainId: 1, verifyingContract: '0xCcCCccccCCCCcCCCCCCcCcCccCcCCCcCcccccccC' }; // The named list of all type definitions 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 value = { from: { name: 'Cow', wallet: '0xCD2a3d9F938E13CD947Ec05AbC7FE734Df8DD826' }, to: { name: 'Bob', wallet: '0xbBbBBBBbbBBBbbbBbbBbbbbBBbBbbbbBbBbbBBbB' }, contents: 'Hello, Bob!' }; //_result: TypedDataEncoder.encode(domain, types, value) //_log: //_result: TypedDataEncoder.getPayload(domain, types, value) //_log: //_result: TypedDataEncoder.getPrimaryType(types) //_log: //_result: TypedDataEncoder.hash(domain, types, value) //_log: //_result: TypedDataEncoder.hashDomain(domain) //_log: _subsection: Solidity Hashing Algorithms @ When using the Solidity ``abi.encodePacked(...)`` 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 //_result: utils.solidityPack([ "int16", "uint48" ], [ -1, 12 ]) //_log: //_result: utils.solidityPack([ "string", "uint8" ], [ "Hello", 3 ]) //_log: //_result: utils.solidityKeccak256([ "int16", "uint48" ], [ -1, 12 ]) //_log: //_result: utils.soliditySha256([ "int16", "uint48" ], [ -1, 12 ]) //_log: // 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. //_result: utils.solidityPack([ "string", "string" ], [ "hello", "world01" ]) //_log: //_result: utils.solidityPack([ "string", "string" ], [ "helloworld", "01" ]) //_log: //_result: utils.solidityPack([ "string", "string", "uint16" ], [ "hell", "oworld", 0x3031 ]) //_log: //_result: utils.solidityPack([ "uint96" ], [ "32309054545061485574011236401" ]) //_log: