mirror of
https://github.com/pezkuwichain/pezkuwi-common.git
synced 2026-07-29 02:05:44 +00:00
82 lines
3.5 KiB
JavaScript
82 lines
3.5 KiB
JavaScript
"use strict";
|
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
exports.signatureVerify = signatureVerify;
|
|
const util_1 = require("@pezkuwi/util");
|
|
const decode_js_1 = require("../address/decode.js");
|
|
const verify_js_1 = require("../ed25519/verify.js");
|
|
const verify_js_2 = require("../secp256k1/verify.js");
|
|
const verify_js_3 = require("../sr25519/verify.js");
|
|
const secp256k1VerifyHasher = (hashType) => (message, signature, publicKey) => (0, verify_js_2.secp256k1Verify)(message, signature, publicKey, hashType, true);
|
|
const VERIFIERS_ECDSA = [
|
|
['ecdsa', secp256k1VerifyHasher('blake2')],
|
|
['ethereum', secp256k1VerifyHasher('keccak')]
|
|
];
|
|
const VERIFIERS = [
|
|
['ed25519', verify_js_1.ed25519Verify],
|
|
['sr25519', verify_js_3.sr25519Verify]
|
|
];
|
|
function verifyDetect(result, { message, publicKey, signature }, verifiers = [...VERIFIERS, ...VERIFIERS_ECDSA]) {
|
|
result.isValid = verifiers.some(([crypto, verify]) => {
|
|
try {
|
|
if (verify(message, signature, publicKey)) {
|
|
result.crypto = crypto;
|
|
return true;
|
|
}
|
|
}
|
|
catch {
|
|
// do nothing, result.isValid still set to false
|
|
}
|
|
return false;
|
|
});
|
|
return result;
|
|
}
|
|
function verifyMultisig(result, { message, publicKey, signature }) {
|
|
if (![0, 1, 2].includes(signature[0]) || ![65, 66].includes(signature.length)) {
|
|
throw new Error(`Unknown crypto type, expected signature prefix [0..2], found ${signature[0]}`);
|
|
}
|
|
// If the signature is 66 bytes it must be an ecdsa signature
|
|
// containing: prefix [1 byte] + signature [65] bytes.
|
|
// Remove the and then verify
|
|
if (signature.length === 66) {
|
|
result = verifyDetect(result, { message, publicKey, signature: signature.subarray(1) }, VERIFIERS_ECDSA);
|
|
}
|
|
else {
|
|
// The signature contains 65 bytes which is either
|
|
// - A ed25519 or sr25519 signature [1 byte prefix + 64 bytes]
|
|
// - An ecdsa signature [65 bytes]
|
|
result = verifyDetect(result, { message, publicKey, signature: signature.subarray(1) }, VERIFIERS);
|
|
if (!result.isValid) {
|
|
result = verifyDetect(result, { message, publicKey, signature }, VERIFIERS_ECDSA);
|
|
}
|
|
// If both failed, explicitly set crypto to 'none'
|
|
if (!result.isValid) {
|
|
result.crypto = 'none';
|
|
}
|
|
}
|
|
return result;
|
|
}
|
|
function getVerifyFn(signature) {
|
|
return [0, 1, 2].includes(signature[0]) && [65, 66].includes(signature.length)
|
|
? verifyMultisig
|
|
: verifyDetect;
|
|
}
|
|
function signatureVerify(message, signature, addressOrPublicKey) {
|
|
const signatureU8a = (0, util_1.u8aToU8a)(signature);
|
|
if (![64, 65, 66].includes(signatureU8a.length)) {
|
|
throw new Error(`Invalid signature length, expected [64..66] bytes, found ${signatureU8a.length}`);
|
|
}
|
|
const publicKey = (0, decode_js_1.decodeAddress)(addressOrPublicKey);
|
|
const input = { message: (0, util_1.u8aToU8a)(message), publicKey, signature: signatureU8a };
|
|
const result = { crypto: 'none', isValid: false, isWrapped: (0, util_1.u8aIsWrapped)(input.message, true), publicKey };
|
|
const isWrappedBytes = (0, util_1.u8aIsWrapped)(input.message, false);
|
|
const verifyFn = getVerifyFn(signatureU8a);
|
|
verifyFn(result, input);
|
|
if (result.crypto !== 'none' || (result.isWrapped && !isWrappedBytes)) {
|
|
return result;
|
|
}
|
|
input.message = isWrappedBytes
|
|
? (0, util_1.u8aUnwrapBytes)(input.message)
|
|
: (0, util_1.u8aWrapBytes)(input.message);
|
|
return verifyFn(result, input);
|
|
}
|