Pre-checks on verify input lengths (#608)

* Pre-checks on verify input lengths

* Small cleanup

* Update error signatures
This commit is contained in:
Jaco Greeff
2020-06-01 10:27:08 +02:00
committed by GitHub
parent cc5b7ed0ad
commit bdb14f91a8
12 changed files with 67 additions and 21 deletions
+1 -2
View File
@@ -19,8 +19,7 @@ export default function decode (encoded: string | Uint8Array, ignoreChecksum?: b
}
const decoded = bufferToU8a(bs58.decode(encoded));
const error = (message: string): string =>
`Decoding ${encoded as string}: ${message}`;
const error = (message: string) => `Decoding ${encoded as string}: ${message}`;
// assert(defaults.allowedPrefix.includes(decoded[0] as Prefix), error('Invalid decoded address prefix'));
assert(defaults.allowedEncodedLengths.includes(decoded.length), error('Invalid decoded address length'));
@@ -20,7 +20,6 @@ export default function encode (_key: Uint8Array | string, ss58Format: Prefix =
assert(defaults.allowedDecodedLengths.includes(key.length), `Expected a valid key to convert, with length ${defaults.allowedDecodedLengths.join(', ')}`);
const isPublicKey = key.length === 32;
const input = u8aConcat(new Uint8Array([ss58Format]), key);
const hash = sshash(input);
+1 -1
View File
@@ -13,7 +13,7 @@ export interface ExtractResult {
}
/**
* @description Extract derivation juntions from the supplied path
* @description Extract derivation junctions from the supplied path
*/
export default function keyExtractPath (derivePath: string): ExtractResult {
const parts = derivePath.match(RE_JUNCTION);
+7 -5
View File
@@ -9,12 +9,14 @@ import keyHdkdEd15519 from './hdkdEd25519';
import keyHdkdSr15519 from './hdkdSr25519';
import keyHdkdEcdsa from './hdkdEcdsa';
const generators = {
ecdsa: keyHdkdEcdsa,
ed25519: keyHdkdEd15519,
sr25519: keyHdkdSr15519
};
export default function keyFromPath (pair: Keypair, path: DeriveJunction[], type: KeypairType): Keypair {
const keyHdkd = {
ecdsa: keyHdkdEcdsa,
ed25519: keyHdkdEd15519,
sr25519: keyHdkdSr15519
}[type];
const keyHdkd = generators[type];
return path.reduce((pair, junction): Keypair => {
return keyHdkd(pair, junction);
+1 -1
View File
@@ -23,7 +23,7 @@ import { isReady, ed25519Sign } from '@polkadot/wasm-crypto';
* ```
*/
export default function naclSign (message: Uint8Array | string, { publicKey, secretKey }: Partial<Keypair>): Uint8Array {
assert(secretKey, 'Expected valid secretKey');
assert(secretKey, 'Expected a valid secretKey');
const messageU8a = u8aToU8a(message);
+21 -1
View File
@@ -7,7 +7,7 @@ import { waitReady } from '@polkadot/wasm-crypto';
import { naclVerify, naclKeypairFromSeed } from '.';
describe('naclSign', (): void => {
describe('naclVerify', (): void => {
let publicKey: Uint8Array;
let signature: Uint8Array;
@@ -51,4 +51,24 @@ describe('naclSign', (): void => {
)
).toEqual(false);
});
it('throws error when publicKey lengths do not match', (): void => {
expect(
() => naclVerify(
new Uint8Array([0x61, 0x62, 0x63, 0x64]),
signature,
new Uint8Array([1, 2])
)
).toThrow(/Invalid publicKey/);
});
it('throws error when signature lengths do not match', (): void => {
expect(
() => naclVerify(
new Uint8Array([0x61, 0x62, 0x63, 0x64]),
new Uint8Array([1, 2]),
publicKey
)
).toThrow(/Invalid signature/);
});
});
+6 -3
View File
@@ -3,14 +3,14 @@
// of the Apache-2.0 license. See the LICENSE file for details.
import nacl from 'tweetnacl';
import { u8aToU8a } from '@polkadot/util';
import { assert, u8aToU8a } from '@polkadot/util';
import { isReady, ed25519Verify } from '@polkadot/wasm-crypto';
/**
* @name naclSign
* @summary Verifies the signature on the supplied message.
* @description
* Verifies the `signature` on `message` with the supplied `plublicKey`. Returns `true` on sucess, `false` otherwise.
* Verifies the `signature` on `message` with the supplied `publicKey`. Returns `true` on sucess, `false` otherwise.
* @example
* <BR>
*
@@ -22,8 +22,11 @@ import { isReady, ed25519Verify } from '@polkadot/wasm-crypto';
*/
export default function naclVerify (message: Uint8Array | string, signature: Uint8Array | string, publicKey: Uint8Array | string): boolean {
const messageU8a = u8aToU8a(message);
const signatureU8a = u8aToU8a(signature);
const publicKeyU8a = u8aToU8a(publicKey);
const signatureU8a = u8aToU8a(signature);
assert(publicKeyU8a.length === 32, `Invalid publicKey, received ${publicKeyU8a.length}, expected 32`);
assert(signatureU8a.length === 64, `Invalid signature, received ${signatureU8a.length} bytes, expected 64`);
return isReady()
? ed25519Verify(signatureU8a, messageU8a, publicKeyU8a)
+2 -2
View File
@@ -14,8 +14,8 @@ import { sr25519Sign } from '@polkadot/wasm-crypto';
* @description Returns message signature of `message`, using the supplied pair
*/
export default function schnorrkelSign (message: Uint8Array | string, { publicKey, secretKey }: Partial<Keypair>): Uint8Array {
assert(publicKey?.length === 32, 'Expected valid publicKey, 32-bytes');
assert(secretKey?.length === 64, 'Expected valid secretKey, 64-bytes');
assert(publicKey?.length === 32, 'Expected a valid publicKey, 32-bytes');
assert(secretKey?.length === 64, 'Expected a valid secretKey, 64-bytes');
const messageU8a = u8aToU8a(message);
@@ -29,4 +29,24 @@ describe('sign and verify', (): void => {
expect(verify(MESSAGE, signature, pair.publicKey)).toBe(true);
});
it('throws error when publicKey lengths do not match', (): void => {
expect(
() => verify(
new Uint8Array([0x61, 0x62, 0x63, 0x64]),
new Uint8Array(64),
new Uint8Array(31)
)
).toThrow(/Invalid publicKey/);
});
it('throws error when signature lengths do not match', (): void => {
expect(
() => verify(
new Uint8Array([0x61, 0x62, 0x63, 0x64]),
new Uint8Array(65),
new Uint8Array(32)
)
).toThrow(/Invalid signature/);
});
});
@@ -4,7 +4,7 @@
import '../polyfill';
import { u8aToU8a } from '@polkadot/util';
import { assert, u8aToU8a } from '@polkadot/util';
import { sr25519Verify } from '@polkadot/wasm-crypto';
/**
@@ -13,8 +13,11 @@ import { sr25519Verify } from '@polkadot/wasm-crypto';
*/
export default function schnorrkelVerify (message: Uint8Array | string, signature: Uint8Array | string, publicKey: Uint8Array | string): boolean {
const messageU8a = u8aToU8a(message);
const signatureU8a = u8aToU8a(signature);
const publicKeyU8a = u8aToU8a(publicKey);
const signatureU8a = u8aToU8a(signature);
assert(publicKeyU8a.length === 32, `Invalid publicKey, received ${publicKeyU8a.length} bytes, expected 32`);
assert(signatureU8a.length === 64, `Invalid signature, received ${signatureU8a.length} bytes, expected 64`);
return sr25519Verify(signatureU8a, messageU8a, publicKeyU8a);
}
+2 -3
View File
@@ -67,10 +67,9 @@ export default function signatureVerify (message: Uint8Array | string, signature
const result: VerifyResult = { crypto: 'none', isValid: false };
const publicKey = addressDecode(addressOrPublicKey);
const isMultisig = [0, 1, 2].includes(signatureU8a[0]) && [65, 66].includes(signatureU8a.length);
const multisig = [0, 1, 2].includes(signatureU8a[0]) && [65, 66].includes(signatureU8a.length);
if (multisig) {
if (isMultisig) {
return verifyMultisig(result, message, signatureU8a, publicKey);
} else {
return verifyDetect(result, message, signatureU8a, publicKey);