Skip to content

Commit

Permalink
fix: ensure eth_sign signature
Browse files Browse the repository at this point in the history
  • Loading branch information
JGiter committed Dec 22, 2021
1 parent 6a920de commit 5b4dec3
Show file tree
Hide file tree
Showing 4 changed files with 30 additions and 19 deletions.
2 changes: 1 addition & 1 deletion src/errors/ErrorMessages.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ export enum ERROR_MESSAGES {
UNKNOWN_PROVIDER = "Unknown provider type",
ENS_TYPE_NOT_SUPPORTED = "ENS type not supported",
WALLET_PROVIDER_NOT_SUPPORTED = "Wallet provider must be a supported value",
PUBLIC_KEY_NOT_RECOVERED = "Public key not recovered",
NON_ETH_SIGN_SIGNATURE = "Signature is not eth_sign verifiable",
ORG_WITH_APPS = "You are not able to remove organization with registered apps",
ORG_WITH_ROLES = "You are not able to remove organization with registered roles",
APP_WITH_ROLES = "You are not able to remove application with registered roles",
Expand Down
2 changes: 1 addition & 1 deletion src/modules/claims/claims.service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -494,7 +494,7 @@ export class ClaimsService {
);
const agreement_type_hash = id("Agreement(address subject,bytes32 role,uint256 version)");

const chainId = await this._signerService.chainId;
const chainId = this._signerService.chainId;
const domainSeparator = keccak256(
defaultAbiCoder.encode(
["bytes32", "bytes32", "bytes32", "uint256", "address"],
Expand Down
44 changes: 27 additions & 17 deletions src/modules/signer/signer.service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,11 +7,13 @@ import { chainConfigs } from "../../config/chain.config";
import { ExecutionEnvironment, executionEnvironment } from "../../utils/detectEnvironment";
import { IPubKeyAndIdentityToken, ProviderType, ProviderEvent, AccountInfo, PUBLIC_KEY } from "./signer.types";
import { EkcSigner } from "./ekcSigner";
import { computeAddress } from "ethers/lib/utils";

const { arrayify, keccak256, recoverPublicKey, computeAddress, computePublicKey, getAddress, hashMessage } = utils;
const { arrayify, keccak256, recoverPublicKey, getAddress, hashMessage, verifyMessage } = utils;
export type ServiceInitializer = () => Promise<void>;
export class SignerService {
private _publicKey: string;
private _isEthSigner = true;
private _identityToken: string;
private _address: string;
private _account: string;
Expand Down Expand Up @@ -139,8 +141,19 @@ export class SignerService {
return result;
}

/**
* @description Tries to create `eth_sign` conformant signature (https://eth.wiki/json-rpc/API#eth_sign)
* Signing method is determined based on previous signing
*
* @param message Message should have binary representation to avoid confusion of text with hexadecimal binary data
*/
async signMessage(message: Uint8Array) {
return this.signer.signMessage(message);
const messageHash = this._isEthSigner ? message : arrayify(hashMessage(message));
const sig = await this.signer.signMessage(messageHash);
if (getAddress(this._address) !== getAddress(verifyMessage(message, sig))) {
throw new Error(ERROR_MESSAGES.NON_ETH_SIGN_SIGNATURE);
}
return sig;
}

async connect(signer: Required<ethers.Signer>, providerType: ProviderType) {
Expand Down Expand Up @@ -206,25 +219,22 @@ export class SignerService {
// arrayification is necessary for WalletConnect signatures to work. eth_sign expects message in bytes: https://docs.walletconnect.org/json-rpc-api-methods/ethereum#eth_sign
// keccak256 hash is applied for Metamask to display a coherent hex value when signing
const message = arrayify(keccak256(token));
const sig = await this.signMessage(message);
const recoverValidatedPublicKey = (signedMessage: Uint8Array): string | undefined => {
const publicKey = recoverPublicKey(signedMessage, sig);
if (getAddress(address) === getAddress(computeAddress(publicKey))) {
return computePublicKey(publicKey, true).slice(2);
}
return undefined;
};

// Computation of the digest in order to recover the public key under the assumption
// that signature was performed as per the eth_sign spec (https://eth.wiki/json-rpc/API#eth_sign)
// In the event that the wallet isn't prefixing & hashing message as per spec, attempt recovery without digest
const digest = arrayify(hashMessage(message));
const publicKey = recoverValidatedPublicKey(digest) ?? recoverValidatedPublicKey(message);
if (publicKey) {
this._publicKey = publicKey;
this._identityToken = `${encodedHeader}.${encodedPayload}.${base64url(sig)}`;
const sig = await this._signer.signMessage(message);
const keyFromMessage = recoverPublicKey(message, sig);
const keyFromDigest = recoverPublicKey(digest, sig);
if (getAddress(this._address) === computeAddress(keyFromMessage)) {
this._publicKey = keyFromMessage;
this._isEthSigner = false;
} else if (getAddress(this._address) === computeAddress(keyFromDigest)) {
this._publicKey = keyFromDigest;
this._isEthSigner = true;
} else {
throw new Error(ERROR_MESSAGES.PUBLIC_KEY_NOT_RECOVERED);
throw new Error(ERROR_MESSAGES.NON_ETH_SIGN_SIGNATURE);
}

this._identityToken = `${encodedHeader}.${encodedPayload}.${base64url(sig)}`;
}
}
1 change: 1 addition & 0 deletions src/modules/signer/walletConnectMetamask.ts
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ export const createWalletConnectProvider = (bridge: string, infuraId?: string) =
rpc,
connector: new Connector({ bridge, qrcodeModal: QRCodeModal }),
infuraId,
chainId: 73799,
});
return walletConnectProvider;
};
Expand Down

0 comments on commit 5b4dec3

Please sign in to comment.