UNPKG

pooja-docucomb-tink-crypto

Version:

A multi-language, cross-platform library that provides cryptographic APIs that are secure, easy to use correctly, and hard(er) to misuse.

860 lines (805 loc) 39.4 kB
/** * @license * Copyright 2020 Google LLC * SPDX-License-Identifier: Apache-2.0 */ import {assertExists} from '../testing/internal/test_utils'; import * as Bytes from './bytes'; import * as EllipticCurves from './elliptic_curves'; import * as Random from './random'; import {WYCHEPROOF_ECDH_TEST_VECTORS} from './wycheproof_ecdh_test_vectors'; describe('elliptic curves test', function() { beforeEach(function() { // Use a generous promise timeout for running continuously. jasmine.DEFAULT_TIMEOUT_INTERVAL = 1000 * 1000; // 1000s }); afterEach(function() { // Reset the promise timeout to default value. jasmine.DEFAULT_TIMEOUT_INTERVAL = 1000; // 1s }); it('compute ecdh shared secret', async function() { const aliceKeyPair = await EllipticCurves.generateKeyPair('ECDH', 'P-256'); const bobKeyPair = await EllipticCurves.generateKeyPair('ECDH', 'P-256'); const sharedSecret1 = await EllipticCurves.computeEcdhSharedSecret( aliceKeyPair.privateKey!, bobKeyPair.publicKey!); const sharedSecret2 = await EllipticCurves.computeEcdhSharedSecret( bobKeyPair.privateKey!, aliceKeyPair.publicKey!); expect(Bytes.toHex(sharedSecret2)).toBe(Bytes.toHex(sharedSecret1)); }); it('wycheproof, wycheproof webcrypto', async function() { for (const testGroup of WYCHEPROOF_ECDH_TEST_VECTORS['testGroups']) { let errors = ''; for (const test of testGroup['tests']) { errors += await runWycheproofTest(test); } if (errors !== '') { fail(errors); } } }); // Test that both ECDH public and private key are defined in the result. it('generate key pair e c d h', async function() { const curveTypes = [ EllipticCurves.CurveType.P256, EllipticCurves.CurveType.P384, EllipticCurves.CurveType.P521 ]; for (const curve of curveTypes) { const curveTypeString = EllipticCurves.curveToString(curve); const keyPair = await EllipticCurves.generateKeyPair('ECDH', curveTypeString); expect(keyPair.privateKey! != null).toBe(true); expect(keyPair.publicKey! != null).toBe(true); } }); // Test that both ECDSA public and private key are defined in the result. it('generate key pair e c d s a', async function() { const curveTypes = [ EllipticCurves.CurveType.P256, EllipticCurves.CurveType.P384, EllipticCurves.CurveType.P521 ]; for (const curve of curveTypes) { const curveTypeString = EllipticCurves.curveToString(curve); const keyPair = await EllipticCurves.generateKeyPair('ECDSA', curveTypeString); expect(keyPair.privateKey! != null).toBe(true); expect(keyPair.publicKey! != null).toBe(true); } }); // Test that when ECDH crypto key is exported and imported it gives the same // key as the original one. it('import export crypto key e c d h', async function() { const curveTypes = [ EllipticCurves.CurveType.P256, EllipticCurves.CurveType.P384, EllipticCurves.CurveType.P521 ]; for (const curve of curveTypes) { const curveTypeString = EllipticCurves.curveToString(curve); const keyPair = await EllipticCurves.generateKeyPair('ECDH', curveTypeString); const publicKey = keyPair.publicKey!; const publicCryptoKey = await EllipticCurves.exportCryptoKey(publicKey); const importedPublicKey = await EllipticCurves.importPublicKey('ECDH', publicCryptoKey); expect(importedPublicKey).toEqual(publicKey); const privateKey = keyPair.privateKey!; const privateCryptoKey = await EllipticCurves.exportCryptoKey(privateKey); const importedPrivateKey = await EllipticCurves.importPrivateKey('ECDH', privateCryptoKey); expect(importedPrivateKey).toEqual(privateKey); } }); // Test that when ECDSA crypto key is exported and imported it gives the same // key as the original one. it('import export crypto key e c d s a', async function() { const curveTypes = [ EllipticCurves.CurveType.P256, EllipticCurves.CurveType.P384, EllipticCurves.CurveType.P521 ]; for (const curve of curveTypes) { const curveTypeString = EllipticCurves.curveToString(curve); const keyPair = await EllipticCurves.generateKeyPair('ECDSA', curveTypeString); const publicKey = keyPair.publicKey!; const publicCryptoKey = await EllipticCurves.exportCryptoKey(publicKey); const importedPublicKey = await EllipticCurves.importPublicKey('ECDSA', publicCryptoKey); expect(importedPublicKey).toEqual(publicKey); const privateKey = keyPair.privateKey!; const privateCryptoKey = await EllipticCurves.exportCryptoKey(privateKey); const importedPrivateKey = await EllipticCurves.importPrivateKey('ECDSA', privateCryptoKey); expect(importedPrivateKey).toEqual(privateKey); } }); // Test that when JSON ECDH web key is imported and exported it gives the same // key as the original one. it('import export json key e c d h', async function() { for (const testKey of TEST_KEYS) { const jwk: JsonWebKey = ({ 'kty': 'EC', 'crv': testKey.curve, 'x': Bytes.toBase64(Bytes.fromHex(testKey.x), true), 'y': Bytes.toBase64(Bytes.fromHex(testKey.y), true), 'ext': true, }); let importedKey; if (!testKey.d) { jwk['key_ops'] = []; importedKey = await EllipticCurves.importPublicKey('ECDH', jwk); } else { jwk['key_ops'] = ['deriveKey', 'deriveBits']; jwk['d'] = Bytes.toBase64(Bytes.fromHex(testKey.d), true); importedKey = await EllipticCurves.importPrivateKey('ECDH', jwk); } const exportedKey = await EllipticCurves.exportCryptoKey(importedKey); expect(exportedKey).toEqual(jwk); } }); // Test that when JSON ECDSA web key is imported and exported it gives the // same key as the original one. it('import export json key e c d s a', async function() { for (const testKey of TEST_KEYS) { const jwk: JsonWebKey = ({ 'kty': 'EC', 'crv': testKey.curve, 'x': Bytes.toBase64(Bytes.fromHex(testKey.x), true), 'y': Bytes.toBase64(Bytes.fromHex(testKey.y), true), 'ext': true, }); let importedKey; if (!testKey.d) { jwk['key_ops'] = ['verify']; importedKey = await EllipticCurves.importPublicKey('ECDSA', jwk); } else { jwk['key_ops'] = ['sign']; jwk['d'] = Bytes.toBase64(Bytes.fromHex(testKey.d), true); importedKey = await EllipticCurves.importPrivateKey('ECDSA', jwk); } const exportedKey = await EllipticCurves.exportCryptoKey(importedKey); expect(exportedKey).toEqual(jwk); } }); it('curve to string', function() { expect(EllipticCurves.curveToString(EllipticCurves.CurveType.P256)) .toBe('P-256'); expect(EllipticCurves.curveToString(EllipticCurves.CurveType.P384)) .toBe('P-384'); expect(EllipticCurves.curveToString(EllipticCurves.CurveType.P521)) .toBe('P-521'); }); it('curve from string', function() { expect(EllipticCurves.curveFromString('P-256')) .toBe(EllipticCurves.CurveType.P256); expect(EllipticCurves.curveFromString('P-384')) .toBe(EllipticCurves.CurveType.P384); expect(EllipticCurves.curveFromString('P-521')) .toBe(EllipticCurves.CurveType.P521); }); it('field size in bytes', function() { expect(EllipticCurves.fieldSizeInBytes(EllipticCurves.CurveType.P256)) .toBe(256 / 8); expect(EllipticCurves.fieldSizeInBytes(EllipticCurves.CurveType.P384)) .toBe(384 / 8); expect(EllipticCurves.fieldSizeInBytes(EllipticCurves.CurveType.P521)) .toBe((521 + 7) / 8); }); it('encoding size in bytes, uncompressed point format type', function() { expect(EllipticCurves.encodingSizeInBytes( EllipticCurves.CurveType.P256, EllipticCurves.PointFormatType.UNCOMPRESSED)) .toBe(2 * (256 / 8) + 1); expect(EllipticCurves.encodingSizeInBytes( EllipticCurves.CurveType.P384, EllipticCurves.PointFormatType.UNCOMPRESSED)) .toBe(2 * (384 / 8) + 1); expect(EllipticCurves.encodingSizeInBytes( EllipticCurves.CurveType.P521, EllipticCurves.PointFormatType.UNCOMPRESSED)) .toBe(2 * ((521 + 7) / 8) + 1); }); it('encoding size in bytes, compressed point format type', function() { expect(EllipticCurves.encodingSizeInBytes( EllipticCurves.CurveType.P256, EllipticCurves.PointFormatType.COMPRESSED)) .toBe((256 / 8) + 1); expect(EllipticCurves.encodingSizeInBytes( EllipticCurves.CurveType.P384, EllipticCurves.PointFormatType.COMPRESSED)) .toBe((384 / 8) + 1); expect(EllipticCurves.encodingSizeInBytes( EllipticCurves.CurveType.P521, EllipticCurves.PointFormatType.COMPRESSED)) .toBe(((521 + 7) / 8) + 1); }); it('encoding size in bytes, crunchy uncompressed point format type', function() { expect( EllipticCurves.encodingSizeInBytes( EllipticCurves.CurveType.P256, EllipticCurves.PointFormatType.DO_NOT_USE_CRUNCHY_UNCOMPRESSED)) .toBe(2 * (256 / 8)); expect( EllipticCurves.encodingSizeInBytes( EllipticCurves.CurveType.P384, EllipticCurves.PointFormatType.DO_NOT_USE_CRUNCHY_UNCOMPRESSED)) .toBe(2 * (384 / 8)); expect( EllipticCurves.encodingSizeInBytes( EllipticCurves.CurveType.P521, EllipticCurves.PointFormatType.DO_NOT_USE_CRUNCHY_UNCOMPRESSED)) .toBe(2 * ((521 + 7) / 8)); }); it('point decode, wrong point size', function() { const point = new Uint8Array(10); const format = EllipticCurves.PointFormatType.UNCOMPRESSED; for (const curve of [EllipticCurves.CurveType.P256, EllipticCurves.CurveType.P384, EllipticCurves.CurveType.P521]) { const curveTypeString = EllipticCurves.curveToString(curve); // It should throw an exception as the point array is too short. try { EllipticCurves.pointDecode(curveTypeString, format, point); fail('Should throw an exception.'); // Preserving old behavior when moving to // https://www.typescriptlang.org/tsconfig#useUnknownInCatchVariables // tslint:disable-next-line:no-any } catch (e: any) { expect(e.toString()).toBe('InvalidArgumentsException: invalid point'); } } }); it('point decode, unknown curve', function() { const point = new Uint8Array(10); const format = EllipticCurves.PointFormatType.UNCOMPRESSED; const curve = 'some-unknown-curve'; try { EllipticCurves.pointDecode(curve, format, point); fail('Should throw an exception.'); // Preserving old behavior when moving to // https://www.typescriptlang.org/tsconfig#useUnknownInCatchVariables // tslint:disable-next-line:no-any } catch (e: any) { expect(e.toString().includes('unknown curve')).toBe(true); } }); it('point encode, compressed', () => { for (const test of TEST_VECTORS) { const format = EllipticCurves.formatFromString(test.format); if (format !== EllipticCurves.PointFormatType.COMPRESSED) { // TODO(b/214598739): Investigate compatibility of other formats with // Java test vectors. continue; } const point: JsonWebKey = { kty: 'EC', crv: test.curve, x: Bytes.toBase64( EllipticCurves.integerToByteArray(BigInt('0x' + test.x)), /* websafe = */ true), y: Bytes.toBase64( EllipticCurves.integerToByteArray(BigInt('0x' + test.y)), /* websafe = */ true), ext: true, }; const encodedPoint = EllipticCurves.pointEncode(assertExists(point.crv), format, point); expect(Bytes.toHex(encodedPoint)).toEqual(test.encoded); } }); it('point decode, compressed', () => { for (const test of TEST_VECTORS) { const format = EllipticCurves.formatFromString(test.format); if (format !== EllipticCurves.PointFormatType.COMPRESSED) { // TODO(b/214598739): Investigate compatibility of other formats with // Java test vectors. continue; } const decodedPoint = EllipticCurves.pointDecode( test.curve, format, Bytes.fromHex(test.encoded)); // NOTE: Any leading zero inserted by Bytes.toHex() must be removed. const decodedX = Bytes.toHex(Bytes.fromBase64(assertExists(decodedPoint.x), true)) .replace(/^0?/, ''); const decodedY = Bytes.toHex(Bytes.fromBase64(assertExists(decodedPoint.y), true)) .replace(/^0?/, ''); expect(decodedX).toEqual(test.x); expect(decodedY).toEqual(test.y); } }); it('point encode decode', () => { for (const test of TEST_VECTORS) { const format = EllipticCurves.formatFromString(test.format); if (format !== EllipticCurves.PointFormatType.COMPRESSED) { // TODO(b/214598739): Investigate compatibility of other formats with // Java test vectors. continue; } const point: JsonWebKey = { kty: 'EC', crv: test.curve, x: Bytes.toBase64( EllipticCurves.integerToByteArray(BigInt('0x' + test.x)), /* websafe = */ true), y: Bytes.toBase64( EllipticCurves.integerToByteArray(BigInt('0x' + test.y)), /* websafe = */ true), ext: true, }; const encodedPoint = EllipticCurves.pointEncode(assertExists(point.crv), format, point); const decodedPoint = EllipticCurves.pointDecode( assertExists(point.crv), format, encodedPoint); expect(decodedPoint).toEqual(point); } }); it('point encode decode, random points', () => { for (const format of [EllipticCurves.PointFormatType.UNCOMPRESSED, EllipticCurves.PointFormatType.DO_NOT_USE_CRUNCHY_UNCOMPRESSED]) { for (const curveType of [EllipticCurves.CurveType.P256, EllipticCurves.CurveType.P384, EllipticCurves.CurveType.P521]) { const curveTypeString = EllipticCurves.curveToString(curveType); const x = Random.randBytes(EllipticCurves.fieldSizeInBytes(curveType)); const y = Random.randBytes(EllipticCurves.fieldSizeInBytes(curveType)); const point: JsonWebKey = { kty: 'EC', crv: curveTypeString, x: Bytes.toBase64(x, /* websafe = */ true), y: Bytes.toBase64(y, /* websafe = */ true), ext: true, }; const encodedPoint = EllipticCurves.pointEncode(assertExists(point.crv), format, point); const decodedPoint = EllipticCurves.pointDecode(curveTypeString, format, encodedPoint); expect(decodedPoint).toEqual(point); } } }); it('ecdsa der2 ieee', function() { for (const test of ECDSA_IEEE_DER_TEST_VECTORS) { expect(EllipticCurves.ecdsaDer2Ieee(test.der, test.ieee.length)) .toEqual(test.ieee); } }); it('ecdsa der2 ieee with invalid signatures', function() { for (const test of INVALID_DER_ECDSA_SIGNATURES) { try { EllipticCurves.ecdsaDer2Ieee( Bytes.fromHex(test), 1 /* ieeeLength, ignored */); // Preserving old behavior when moving to // https://www.typescriptlang.org/tsconfig#useUnknownInCatchVariables // tslint:disable-next-line:no-any } catch (e: any) { expect(e.toString()) .toBe('InvalidArgumentsException: invalid DER signature'); } } }); it('ecdsa ieee2 der', function() { for (const test of ECDSA_IEEE_DER_TEST_VECTORS) { expect(EllipticCurves.ecdsaIeee2Der(test.ieee)).toEqual(test.der); } }); it('is valid der ecdsa signature', function() { for (const test of INVALID_DER_ECDSA_SIGNATURES) { expect(EllipticCurves.isValidDerEcdsaSignature(Bytes.fromHex(test))) .toBe(false); } }); }); /** * Runs the test with test vector given as an input and returns either empty * string or a text describing the failure. */ async function runWycheproofTest(test: { 'tcId': number, 'public': JsonWebKey, 'private': JsonWebKey, 'shared': string, 'result': string, }): Promise<string> { try { const privateKey = await EllipticCurves.importPrivateKey('ECDH', test['private']); try { const publicKey = await EllipticCurves.importPublicKey('ECDH', test['public']); const sharedSecret = await EllipticCurves.computeEcdhSharedSecret(privateKey, publicKey); if (test['result'] === 'invalid') { return 'Fail on test ' + test['tcId'] + ': No exception thrown.\n'; } const sharedSecretHex = Bytes.toHex(sharedSecret); if (sharedSecretHex !== test['shared']) { return 'Fail on test ' + test['tcId'] + ': unexpected result was "' + sharedSecretHex + '".\n'; } // Preserving old behavior when moving to // https://www.typescriptlang.org/tsconfig#useUnknownInCatchVariables // tslint:disable-next-line:no-any } catch (e: any) { if (test['result'] === 'valid') { return 'Fail on test ' + test['tcId'] + ': unexpected exception "' + e.toString() + '".\n'; } } // Preserving old behavior when moving to // https://www.typescriptlang.org/tsconfig#useUnknownInCatchVariables // tslint:disable-next-line:no-any } catch (e: any) { if (test['result'] === 'valid') { if (test['private']['crv'] == "P-256K") { // P-256K doesn't have to be supported. Hence failing to import the // key is OK. return ''; } return 'Fail on test ' + test['tcId'] + ': unexpected exception trying to import private key "' + e.toString() + '".\n'; } } // If the test passes return an empty string. return ''; } class TestKey { constructor( readonly curve: string, readonly x: string, readonly y: string, readonly d?: string) {} } // This set of keys was generated by Java version of Tink. // It contains one private and one public key for each curve type supported by // Tink. const TEST_KEYS: TestKey[] = [ new TestKey( /* curve = */ 'P-256', /* x = */ '2eab800e5d8e9b15d0f87c55324b477ffc9382d7137599e0203113a4e41b50d0', /* y = */ '50bb2c11cfb72f3c380c2f93ea088d6938b91bcf581cd94a73ed0a3f623a6b8b'), new TestKey( /* curve = */ 'P-256', /* x = */ '844c085cc4450297b681126356e10da074dea817f69bc2b1f3d6b1fc82593c7d', /* y = */ '3cdb41fc89867d2066cc9c4f9ad7e890152bad24de20621abfe608234cbe40f1', /* opt_d = */ 'f96796cc28b36038817cc5d7db01c52ee0411dd848dc0833e9e26e989e4a64db'), new TestKey( /* curve = */ 'P-384', /* x = */ 'f3290cc80faa65e8821b0bf835f51e3431a4d78dcebd81b74c53b9b704bd995df93b648d51057a9a96a654fb8332391e', /* y = */ '7e52bb9f654781a6894ef5ae77869207fa32ddbcec4a02d27ba1ead5472b3b9f39b09e9bca7d936809c143e99c655401'), new TestKey( /* curve = */ 'P-384', /* x = */ 'be9df79abedb82fc0e527630955f63f2f74b4984f0a4ac063a089565393ed20ac7a784f4efa434f5b1fa1837c76c8472', /* y = */ 'cf34ad0d4f3f2cbd546780509ec7073bb26fa0547d09ed10b83bf9b90903037ac956dbd661d02ce3e397e0547356b331', /* opt_d = */ '34d86595280a8bdca23ccd60eeac9581016e895c2bc867c26dc2f99f6d0f627ce586ad36d1d2981968d8852dc9276d12'), new TestKey( /* curve = */ 'P-521', /* x = */ '012f2211ec7e634919857be3066becf20c438b84ff24501712c91c98f527b44c7b001f8611935cb1179541c2b3cc3a1fc9259d50cd4842a847ea0cafe22cd75fe788', /* y = */ '016b5d3f5480122643a26ef9e7c7e36875f53c28167d6afc35777d32ea76127d34287325bf14779f2e4cf3864fcc951ba601cec92b03291e34db2e815d4bd6fc2045'), new TestKey( /* curve = */ 'P-521', /* x = */ '01ee3aabecef323cb4581e044be21914b567c426eae18d71720a71a0b236f5324ef9666fe855f5d7986d3e33a9250396f63c780572b3ad9417d69c2a87773ce39194', /* y = */ '0036bea90db019304719d269e5335f9790e730e241a1b02cfdab8bdcfd0bcff8bdcb3ddeb9c3a94ecff1ab6abb80b0c1655f871c6089d3a4bf8625cf6bd182897f1b', /* opt_d = */ '00b9f9f5d91cbfa9b7f92b041b137ac9822ca4a38f71ce227f624cac6178ca8351fab24bc2cc3f85d7ab72f54a0f9d1bb11a888a79a9c7b1ca267ddc82043585e437') ]; class EcdsaIeeeDerTestVector { ieee: Uint8Array; der: Uint8Array; constructor(ieee: string, der: string) { this.ieee = Bytes.fromHex(ieee); this.der = Bytes.fromHex(der); } } const ECDSA_IEEE_DER_TEST_VECTORS: EcdsaIeeeDerTestVector[] = [ new EcdsaIeeeDerTestVector( // normal case, short-form length '0102030405060708090a0b0c0d0e0f100102030405060708090a0b0c0d0e0f10', '302402100102030405060708090a0b0c0d0e0f1002100102030405060708090a0b0c0d0e0f10'), new EcdsaIeeeDerTestVector( // normal case, long-form length '010000000100000001000000010000000100000001000000010000000100000001000000010000000100000001000000010000000100000001000000010000000203010000000100000001000000010000000100000001000000010000000100000001000000010000000100000001000000010000000100000001000000010000000203', '30818802420100000001000000010000000100000001000000010000000100000001000000010000000100000001000000010000000100000001000000010000000100000002030242010000000100000001000000010000000100000001000000010000000100000001000000010000000100000001000000010000000100000001000000010000000203'), new EcdsaIeeeDerTestVector( // zero prefix. '0002030405060708090a0b0c0d0e0f100002030405060708090a0b0c0d0e0f10', '3022020f02030405060708090a0b0c0d0e0f10020f02030405060708090a0b0c0d0e0f10'), new EcdsaIeeeDerTestVector( // highest bit is set. '00ff030405060708090a0b0c0d0e0f1000ff030405060708090a0b0c0d0e0f10', '3024021000ff030405060708090a0b0c0d0e0f10021000ff030405060708090a0b0c0d0e0f10'), new EcdsaIeeeDerTestVector( // highest bit is set, full length. 'ff02030405060708090a0b0c0d0e0f10ff02030405060708090a0b0c0d0e0f10', '3026021100ff02030405060708090a0b0c0d0e0f10021100ff02030405060708090a0b0c0d0e0f10'), new EcdsaIeeeDerTestVector( // all zeros. '0000000000000000000000000000000000000000000000000000000000000000', '3006020100020100'), ]; const INVALID_DER_ECDSA_SIGNATURES: string[] = [ '2006020101020101', // 1st byte is not 0x30 (SEQUENCE tag) '3006050101020101', // 3rd byte is not 0x02 (INTEGER tag) '3006020101050101', // 6th byte is not 0x02 (INTEGER tag) '308206020101020101', // long form length is not 0x81 '30ff020101020101', // invalid total length '3006020201020101', // invalid rLength '3006020101020201', // invalid sLength '30060201ff020101', // no extra zero when highest bit of r is set '30060201010201ff', // no extra zero when highest bit of s is set ]; // Following test vectors copied from 'testVectors2' variable in // /src/test/java/com/google/crypto/tink/subtle/EllipticCurvesTest.java. class TestVector { constructor( readonly curve: string, readonly format: string, readonly x: string, readonly y: string, readonly encoded: string) {} } const TEST_VECTORS: TestVector[] = [ new TestVector( /* curve = */ 'P-256', /* format = */ 'UNCOMPRESSED', /* x = */ 'b0cfc7bc02fc980d858077552947ffb449b10df8949dee4e56fe21e016dcb25a', /* y = */ '1886ccdca5487a6772f9401888203f90587cc00a730e2b83d5c6f89b3b568df7', /* encoded = */ '04b0cfc7bc02fc980d858077552947ffb449b10df8949dee4e56fe21e016dcb25a1886ccdca5487a6772f9401888203f90587cc00a730e2b83d5c6f89b3b568df7', ), new TestVector( /* curve = */ 'P-256', /* format = */ 'DO_NOT_USE_CRUNCHY_UNCOMPRESSED', /* x = */ 'b0cfc7bc02fc980d858077552947ffb449b10df8949dee4e56fe21e016dcb25a', /* y = */ '1886ccdca5487a6772f9401888203f90587cc00a730e2b83d5c6f89b3b568df7', /* encoded = */ 'b0cfc7bc02fc980d858077552947ffb449b10df8949dee4e56fe21e016dcb25a1886ccdca5487a6772f9401888203f90587cc00a730e2b83d5c6f89b3b568df7', ), new TestVector( /* curve = */ 'P-256', /* format = */ 'COMPRESSED', /* x = */ 'b0cfc7bc02fc980d858077552947ffb449b10df8949dee4e56fe21e016dcb25a', /* y = */ '1886ccdca5487a6772f9401888203f90587cc00a730e2b83d5c6f89b3b568df7', /* encoded = */ '03b0cfc7bc02fc980d858077552947ffb449b10df8949dee4e56fe21e016dcb25a', ), new TestVector( /* curve = */ 'P-256', /* format = */ 'UNCOMPRESSED', /* x = */ '0', /* y = */ '66485c780e2f83d72433bd5d84a06bb6541c2af31dae871728bf856a174f93f4', /* encoded = */ '04000000000000000000000000000000000000000000000000000000000000000066485c780e2f83d72433bd5d84a06bb6541c2af31dae871728bf856a174f93f4', ), new TestVector( /* curve = */ 'P-256', /* format = */ 'DO_NOT_USE_CRUNCHY_UNCOMPRESSED', /* x = */ '0', /* y = */ '66485c780e2f83d72433bd5d84a06bb6541c2af31dae871728bf856a174f93f4', /* encoded = */ '000000000000000000000000000000000000000000000000000000000000000066485c780e2f83d72433bd5d84a06bb6541c2af31dae871728bf856a174f93f4', ), new TestVector( /* curve = */ 'P-256', /* format = */ 'COMPRESSED', /* x = */ '0', /* y = */ '66485c780e2f83d72433bd5d84a06bb6541c2af31dae871728bf856a174f93f4', /* encoded = */ '020000000000000000000000000000000000000000000000000000000000000000', ), new TestVector( /* curve = */ 'P-256', /* format = */ 'UNCOMPRESSED', /* x = */ 'ffffffff00000001000000000000000000000000fffffffffffffffffffffffc', /* y = */ '19719bebf6aea13f25c96dfd7c71f5225d4c8fc09eb5a0ab9f39e9178e55c121', /* encoded = */ '04ffffffff00000001000000000000000000000000fffffffffffffffffffffffc19719bebf6aea13f25c96dfd7c71f5225d4c8fc09eb5a0ab9f39e9178e55c121', ), new TestVector( /* curve = */ 'P-256', /* format = */ 'DO_NOT_USE_CRUNCHY_UNCOMPRESSED', /* x = */ 'ffffffff00000001000000000000000000000000fffffffffffffffffffffffc', /* y = */ '19719bebf6aea13f25c96dfd7c71f5225d4c8fc09eb5a0ab9f39e9178e55c121', /* encoded = */ 'ffffffff00000001000000000000000000000000fffffffffffffffffffffffc19719bebf6aea13f25c96dfd7c71f5225d4c8fc09eb5a0ab9f39e9178e55c121', ), new TestVector( /* curve = */ 'P-256', /* format = */ 'COMPRESSED', /* x = */ 'ffffffff00000001000000000000000000000000fffffffffffffffffffffffc', /* y = */ '19719bebf6aea13f25c96dfd7c71f5225d4c8fc09eb5a0ab9f39e9178e55c121', /* encoded = */ '03ffffffff00000001000000000000000000000000fffffffffffffffffffffffc', ), new TestVector( /* curve = */ 'P-384', /* format = */ 'UNCOMPRESSED', /* x = */ 'aa87ca22be8b05378eb1c71ef320ad746e1d3b628ba79b9859f741e082542a385502f25dbf55296c3a545e3872760ab7', /* y = */ '3617de4a96262c6f5d9e98bf9292dc29f8f41dbd289a147ce9da3113b5f0b8c00a60b1ce1d7e819d7a431d7c90ea0e5f', /* encoded = */ '04aa87ca22be8b05378eb1c71ef320ad746e1d3b628ba79b9859f741e082542a385502f25dbf55296c3a545e3872760ab73617de4a96262c6f5d9e98bf9292dc29f8f41dbd289a147ce9da3113b5f0b8c00a60b1ce1d7e819d7a431d7c90ea0e5f', ), new TestVector( /* curve = */ 'P-384', /* format = */ 'COMPRESSED', /* x = */ 'aa87ca22be8b05378eb1c71ef320ad746e1d3b628ba79b9859f741e082542a385502f25dbf55296c3a545e3872760ab7', /* y = */ '3617de4a96262c6f5d9e98bf9292dc29f8f41dbd289a147ce9da3113b5f0b8c00a60b1ce1d7e819d7a431d7c90ea0e5f', /* encoded = */ '03aa87ca22be8b05378eb1c71ef320ad746e1d3b628ba79b9859f741e082542a385502f25dbf55296c3a545e3872760ab7', ), new TestVector( /* curve = */ 'P-384', /* format = */ 'UNCOMPRESSED', /* x = */ '0', /* y = */ '3cf99ef04f51a5ea630ba3f9f960dd593a14c9be39fd2bd215d3b4b08aaaf86bbf927f2c46e52ab06fb742b8850e521e', /* encoded = */ '040000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000003cf99ef04f51a5ea630ba3f9f960dd593a14c9be39fd2bd215d3b4b08aaaf86bbf927f2c46e52ab06fb742b8850e521e', ), new TestVector( /* curve = */ 'P-384', /* format = */ 'COMPRESSED', /* x = */ '0', /* y = */ '3cf99ef04f51a5ea630ba3f9f960dd593a14c9be39fd2bd215d3b4b08aaaf86bbf927f2c46e52ab06fb742b8850e521e', /* encoded = */ '02000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000', ), new TestVector( /* curve = */ 'P-384', /* format = */ 'UNCOMPRESSED', /* x = */ '2', /* y = */ '732152442fb6ee5c3e6ce1d920c059bc623563814d79042b903ce60f1d4487fccd450a86da03f3e6ed525d02017bfdb3', /* encoded = */ '04000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002732152442fb6ee5c3e6ce1d920c059bc623563814d79042b903ce60f1d4487fccd450a86da03f3e6ed525d02017bfdb3', ), new TestVector( /* curve = */ 'P-384', /* format = */ 'COMPRESSED', /* x = */ '2', /* y = */ '732152442fb6ee5c3e6ce1d920c059bc623563814d79042b903ce60f1d4487fccd450a86da03f3e6ed525d02017bfdb3', /* encoded = */ '03000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002', ), new TestVector( /* curve = */ 'P-384', /* format = */ 'UNCOMPRESSED', /* x = */ 'fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffeffffffff0000000000000000fffffffc', /* y = */ '2de9de09a95b74e6b2c430363e1afb8dff7164987a8cfe0a0d5139250ac02f797f81092a9bdc0e09b574a8f43bf80c17', /* encoded = */ '04fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffeffffffff0000000000000000fffffffc2de9de09a95b74e6b2c430363e1afb8dff7164987a8cfe0a0d5139250ac02f797f81092a9bdc0e09b574a8f43bf80c17', ), new TestVector( /* curve = */ 'P-384', /* format = */ 'COMPRESSED', /* x = */ 'fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffeffffffff0000000000000000fffffffc', /* y = */ '2de9de09a95b74e6b2c430363e1afb8dff7164987a8cfe0a0d5139250ac02f797f81092a9bdc0e09b574a8f43bf80c17', /* encoded = */ '03fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffeffffffff0000000000000000fffffffc', ), new TestVector( /* curve = */ 'P-521', /* format = */ 'UNCOMPRESSED', /* x = */ 'c6858e06b70404e9cd9e3ecb662395b4429c648139053fb521f828af606b4d3dbaa14b5e77efe75928fe1dc127a2ffa8de3348b3c1856a429bf97e7e31c2e5bd66', /* y = */ '11839296a789a3bc0045c8a5fb42c7d1bd998f54449579b446817afbd17273e662c97ee72995ef42640c550b9013fad0761353c7086a272c24088be94769fd16650', /* encoded = */ '0400c6858e06b70404e9cd9e3ecb662395b4429c648139053fb521f828af606b4d3dbaa14b5e77efe75928fe1dc127a2ffa8de3348b3c1856a429bf97e7e31c2e5bd66011839296a789a3bc0045c8a5fb42c7d1bd998f54449579b446817afbd17273e662c97ee72995ef42640c550b9013fad0761353c7086a272c24088be94769fd16650', ), new TestVector( /* curve = */ 'P-521', /* format = */ 'COMPRESSED', /* x = */ 'c6858e06b70404e9cd9e3ecb662395b4429c648139053fb521f828af606b4d3dbaa14b5e77efe75928fe1dc127a2ffa8de3348b3c1856a429bf97e7e31c2e5bd66', /* y = */ '11839296a789a3bc0045c8a5fb42c7d1bd998f54449579b446817afbd17273e662c97ee72995ef42640c550b9013fad0761353c7086a272c24088be94769fd16650', /* encoded = */ '0200c6858e06b70404e9cd9e3ecb662395b4429c648139053fb521f828af606b4d3dbaa14b5e77efe75928fe1dc127a2ffa8de3348b3c1856a429bf97e7e31c2e5bd66', ), new TestVector( /* curve = */ 'P-521', /* format = */ 'UNCOMPRESSED', /* x = */ '0', /* y = */ 'd20ec9fea6b577c10d26ca1bb446f40b299e648b1ad508aad068896fee3f8e614bc63054d5772bf01a65d412e0bcaa8e965d2f5d332d7f39f846d440ae001f4f87', /* encoded = */ '0400000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000d20ec9fea6b577c10d26ca1bb446f40b299e648b1ad508aad068896fee3f8e614bc63054d5772bf01a65d412e0bcaa8e965d2f5d332d7f39f846d440ae001f4f87', ), new TestVector( /* curve = */ 'P-521', /* format = */ 'COMPRESSED', /* x = */ '0', /* y = */ 'd20ec9fea6b577c10d26ca1bb446f40b299e648b1ad508aad068896fee3f8e614bc63054d5772bf01a65d412e0bcaa8e965d2f5d332d7f39f846d440ae001f4f87', /* encoded = */ '03000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000', ), new TestVector( /* curve = */ 'P-521', /* format = */ 'UNCOMPRESSED', /* x = */ '1', /* y = */ '10e59be93c4f269c0269c79e2afd65d6aeaa9b701eacc194fb3ee03df47849bf550ec636ebee0ddd4a16f1cd9406605af38f584567770e3f272d688c832e843564', /* encoded = */ '040000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000010010e59be93c4f269c0269c79e2afd65d6aeaa9b701eacc194fb3ee03df47849bf550ec636ebee0ddd4a16f1cd9406605af38f584567770e3f272d688c832e843564', ), new TestVector( /* curve = */ 'P-521', /* format = */ 'COMPRESSED', /* x = */ '1', /* y = */ '10e59be93c4f269c0269c79e2afd65d6aeaa9b701eacc194fb3ee03df47849bf550ec636ebee0ddd4a16f1cd9406605af38f584567770e3f272d688c832e843564', /* encoded = */ '02000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001', ), new TestVector( /* curve = */ 'P-521', /* format = */ 'UNCOMPRESSED', /* x = */ '2', /* y = */ 'd9254fdf800496acb33790b103c5ee9fac12832fe546c632225b0f7fce3da4574b1a879b623d722fa8fc34d5fc2a8731aad691a9a8bb8b554c95a051d6aa505acf', /* encoded = */ '0400000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000200d9254fdf800496acb33790b103c5ee9fac12832fe546c632225b0f7fce3da4574b1a879b623d722fa8fc34d5fc2a8731aad691a9a8bb8b554c95a051d6aa505acf', ), new TestVector( /* curve = */ 'P-521', /* format = */ 'COMPRESSED', /* x = */ '2', /* y = */ 'd9254fdf800496acb33790b103c5ee9fac12832fe546c632225b0f7fce3da4574b1a879b623d722fa8fc34d5fc2a8731aad691a9a8bb8b554c95a051d6aa505acf', /* encoded = */ '03000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002', ), new TestVector( /* curve = */ 'P-521', /* format = */ 'UNCOMPRESSED', /* x = */ '1fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffd', /* y = */ '10e59be93c4f269c0269c79e2afd65d6aeaa9b701eacc194fb3ee03df47849bf550ec636ebee0ddd4a16f1cd9406605af38f584567770e3f272d688c832e843564', /* encoded = */ '0401fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffd0010e59be93c4f269c0269c79e2afd65d6aeaa9b701eacc194fb3ee03df47849bf550ec636ebee0ddd4a16f1cd9406605af38f584567770e3f272d688c832e843564', ), new TestVector( /* curve = */ 'P-521', /* format = */ 'COMPRESSED', /* x = */ '1fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffd', /* y = */ '10e59be93c4f269c0269c79e2afd65d6aeaa9b701eacc194fb3ee03df47849bf550ec636ebee0ddd4a16f1cd9406605af38f584567770e3f272d688c832e843564', /* encoded = */ '0201fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffd', ) ];