Skip to content

Commit

Permalink
Add new ethereum backwards compatible message hash and verify methods
Browse files Browse the repository at this point in the history
  • Loading branch information
rileystephens28 committed Jun 26, 2024
1 parent 3abcc46 commit 755bfc2
Show file tree
Hide file tree
Showing 4 changed files with 56 additions and 6 deletions.
12 changes: 11 additions & 1 deletion src/constants/strings.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,11 +9,21 @@
*/
export const quaisymbol: string = '\u039e'; // "\uD835\uDF63";

/**
* A constant for the Quai Network equivalent of the [EIP-191](https://eips.ethereum.org/EIPS/eip-191) personal message
* prefix.
*
* (**i.e.** `"\\x19Quai Signed Message:\\n"`)
*
* @category Constants
*/
export const MessagePrefix: string = '\x19Quai Signed Message:\n';

/**
* A constant for the [EIP-191](https://eips.ethereum.org/EIPS/eip-191) personal message prefix.
*
* (**i.e.** `"\\x19Ethereum Signed Message:\\n"`)
*
* @category Constants
*/
export const MessagePrefix: string = '\x19Quai Signed Message:\n';
export const EthMessagePrefix: string = '\x19Ethereum Signed Message:\n';
2 changes: 1 addition & 1 deletion src/hash/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
*/

export { id } from './id.js';
export { hashMessage, verifyMessage } from './message.js';
export { hashMessage, verifyMessage, ethHashMessage, ethVerifyMessage } from './message.js';
export { solidityPacked, solidityPackedKeccak256, solidityPackedSha256 } from './solidity.js';
export { TypedDataEncoder, verifyTypedData } from './typed-data.js';

Expand Down
46 changes: 42 additions & 4 deletions src/hash/message.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,10 +4,11 @@ import { recoverAddress } from '../address/index.js';
import { concat } from '../utils/index.js';
import { toUtf8Bytes } from '../encoding/index.js';


import type { SignatureLike } from '../crypto/index.js';
import { EthMessagePrefix } from '../constants/strings.js';
/**
* Computes the [EIP-191](https://eips.ethereum.org/EIPS/eip-191) personal-sign message digest to sign.
* Computes the Quai Network equivalent of the [EIP-191](https://eips.ethereum.org/EIPS/eip-191) personal-sign message
* digest to sign.
*
* This prefixes the message with {@link MessagePrefix | **MessagePrefix**} and the decimal length of `message` and
* computes the {@link keccak256 | **keccak256**} digest.
Expand Down Expand Up @@ -37,7 +38,6 @@ import type { SignatureLike } from '../crypto/index.js';
* ```
*
* @param {Uint8Array | string} message - The message to hash.
*
* @returns {string} The message digest.
*/
export function hashMessage(message: Uint8Array | string): string {
Expand All @@ -53,10 +53,48 @@ export function hashMessage(message: Uint8Array | string): string {
* @category Hash
* @param {Uint8Array | string} message - The message that was signed.
* @param {SignatureLike} sig - The signature to verify.
*
* @returns {string} The address of the signer.
*/
export function verifyMessage(message: Uint8Array | string, sig: SignatureLike): string {
const digest = hashMessage(message);
return recoverAddress(digest, sig);
}

/**
* Computes the [EIP-191](https://eips.ethereum.org/EIPS/eip-191) personal-sign message digest to sign.
*
* This prefixes the message with {@link EthMessagePrefix | **EthMessagePrefix**} and the decimal length of `message` and
* computes the {@link keccak256 | **keccak256**} digest.
*
* If `message` is a string, it is converted to its UTF-8 bytes first. To compute the digest of a
* [**DataHexString**](../types-aliases/DataHex), it must be converted to [**bytes**](../functions/getBytes).
*
* This is the same as `hashMessage` except it uses `EthMessagePrefix` instead of `MessagePrefix` and is available for
* broader compatibility with EVM signing practices.
*
* @category Hash
* @param message
* @returns
*/
export function ethHashMessage(message: Uint8Array | string): string {
if (typeof message === 'string') {
message = toUtf8Bytes(message);
}
return keccak256(concat([toUtf8Bytes(EthMessagePrefix), toUtf8Bytes(String(message.length)), message]));
}

/**
* Return the address of the private key that produced the signature `sig` during signing for `message`.
*
* This is the same as `verifyMessage` except it uses `EthMessagePrefix` instead of `MessagePrefix` and is available for
* broader compatibility with EVM signing practices.
*
* @category Hash
* @param message - The message that was signed.
* @param sig - The signature to verify.
* @returns {string} The address of the signer.
*/
export function ethVerifyMessage(message: Uint8Array | string, sig: SignatureLike): string {
const digest = ethHashMessage(message);
return recoverAddress(digest, sig);
}
2 changes: 2 additions & 0 deletions src/quais.ts
Original file line number Diff line number Diff line change
Expand Up @@ -89,6 +89,8 @@ export {
id,
hashMessage,
verifyMessage,
ethHashMessage,
ethVerifyMessage,
solidityPacked,
solidityPackedKeccak256,
solidityPackedSha256,
Expand Down

0 comments on commit 755bfc2

Please sign in to comment.