Move Brainpool curves implementation from noble-curves fork

The main repo doesn't implement them
This commit is contained in:
larabr 2024-05-02 19:12:31 +02:00 committed by larabr
parent ec52bdea83
commit 5bfff907b4
6 changed files with 157 additions and 3 deletions

View File

@ -0,0 +1,23 @@
import { createCurve } from '@noble/curves/_shortw_utils';
import { sha256 } from '@noble/hashes/sha256';
import { Field } from '@noble/curves/abstract/modular';
// brainpoolP256r1: https://datatracker.ietf.org/doc/html/rfc5639#section-3.4
const Fp = Field(BigInt('0xa9fb57dba1eea9bc3e660a909d838d726e3bf623d52620282013481d1f6e5377'));
const CURVE_A = Fp.create(BigInt('0x7d5a0975fc2c3057eef67530417affe7fb8055c126dc5c6ce94a4b44f330b5d9'));
const CURVE_B = BigInt('0x26dc5c6ce94a4b44f330b5d9bbd77cbf958416295cf7e1ce6bccdc18ff8c07b6');
// prettier-ignore
export const brainpoolP256r1 = createCurve({
a: CURVE_A, // Equation params: a, b
b: CURVE_B,
Fp,
// Curve order (q), total count of valid points in the field
n: BigInt('0xa9fb57dba1eea9bc3e660a909d838d718c397aa3b561a6f7901e0e82974856a7'),
// Base (generator) point (x, y)
Gx: BigInt('0x8bd2aeb9cb7e57cb2c4b482ffc81b7afb9de27e1e3bd23c23a4453bd9ace3262'),
Gy: BigInt('0x547ef835c3dac4fd97f8461a14611dc9c27745132ded8e545c1d54c72f046997'),
h: BigInt(1),
lowS: false,
} as const, sha256);

View File

@ -0,0 +1,23 @@
import { createCurve } from '@noble/curves/_shortw_utils';
import { sha384 } from '@noble/hashes/sha512';
import { Field } from '@noble/curves/abstract/modular';
// brainpoolP384 r1: https://datatracker.ietf.org/doc/html/rfc5639#section-3.6
const Fp = Field(BigInt('0x8cb91e82a3386d280f5d6f7e50e641df152f7109ed5456b412b1da197fb71123acd3a729901d1a71874700133107ec53'));
const CURVE_A = Fp.create(BigInt('0x7bc382c63d8c150c3c72080ace05afa0c2bea28e4fb22787139165efba91f90f8aa5814a503ad4eb04a8c7dd22ce2826'));
const CURVE_B = BigInt('0x04a8c7dd22ce28268b39b55416f0447c2fb77de107dcd2a62e880ea53eeb62d57cb4390295dbc9943ab78696fa504c11');
// prettier-ignore
export const brainpoolP384r1 = createCurve({
a: CURVE_A, // Equation params: a, b
b: CURVE_B,
Fp,
// Curve order (q), total count of valid points in the field
n: BigInt('0x8cb91e82a3386d280f5d6f7e50e641df152f7109ed5456b31f166e6cac0425a7cf3ab6af6b7fc3103b883202e9046565'),
// Base (generator) point (x, y)
Gx: BigInt('0x1d1c64f068cf45ffa2a63a81b7c13f6b8847a3e77ef14fe3db7fcafe0cbd10e8e826e03436d646aaef87b2e247d4af1e'),
Gy: BigInt('0x8abe1d7520f9c2a45cb1eb8e95cfd55262b70b29feec5864e19c054ff99129280e4646217791811142820341263c5315'),
h: BigInt(1),
lowS: false,
} as const, sha384);

View File

@ -0,0 +1,23 @@
import { createCurve } from '@noble/curves/_shortw_utils';
import { sha512 } from '@noble/hashes/sha512';
import { Field } from '@noble/curves/abstract/modular';
// brainpoolP512r1: https://datatracker.ietf.org/doc/html/rfc5639#section-3.7
const Fp = Field(BigInt('0xaadd9db8dbe9c48b3fd4e6ae33c9fc07cb308db3b3c9d20ed6639cca703308717d4d9b009bc66842aecda12ae6a380e62881ff2f2d82c68528aa6056583a48f3'));
const CURVE_A = Fp.create(BigInt('0x7830a3318b603b89e2327145ac234cc594cbdd8d3df91610a83441caea9863bc2ded5d5aa8253aa10a2ef1c98b9ac8b57f1117a72bf2c7b9e7c1ac4d77fc94ca'));
const CURVE_B = BigInt('0x3df91610a83441caea9863bc2ded5d5aa8253aa10a2ef1c98b9ac8b57f1117a72bf2c7b9e7c1ac4d77fc94cadc083e67984050b75ebae5dd2809bd638016f723');
// prettier-ignore
export const brainpoolP512r1 = createCurve({
a: CURVE_A, // Equation params: a, b
b: CURVE_B,
Fp,
// Curve order (q), total count of valid points in the field
n: BigInt('0xaadd9db8dbe9c48b3fd4e6ae33c9fc07cb308db3b3c9d20ed6639cca70330870553e5c414ca92619418661197fac10471db1d381085ddaddb58796829ca90069'),
// Base (generator) point (x, y)
Gx: BigInt('0x81aee4bdd82ed9645a21322e9c4c6a9385ed9f70b5d916c1b43b62eef4d0098eff3b1f78e2d0d48d50d1687b93b97d5f7c6d5047406a5e688b352209bcb9f822'),
Gy: BigInt('0x7dde385d566332ecc0eabfa9cf7822fdf209f70024a57b1aa000c55b881f8111b2dcde494a5f485e5bca4bd88a2763aed1ca2b2fa8f0540678cd1e0f3ad80892'),
h: BigInt(1),
lowS: false,
} as const, sha512);

View File

@ -4,12 +4,12 @@
* which share a lot of code anyway.
*/
import { brainpoolP256r1 } from '@openpgp/noble-curves/brainpoolP256r1';
import { brainpoolP384r1 } from '@openpgp/noble-curves/brainpoolP384r1';
import { brainpoolP512r1 } from '@openpgp/noble-curves/brainpoolP512r1';
import { p256 as nistP256 } from '@noble/curves/p256';
import { p384 as nistP384 } from '@noble/curves/p384';
import { p521 as nistP521 } from '@noble/curves/p521';
import { brainpoolP256r1 } from './brainpool/brainpoolP256r1';
import { brainpoolP384r1 } from './brainpool/brainpoolP384r1';
import { brainpoolP512r1 } from './brainpool/brainpoolP512r1';
import { x448, ed448 } from '@noble/curves/ed448';
import { secp256k1 } from '@noble/curves/secp256k1';

View File

@ -0,0 +1,83 @@
import { expect } from 'chai';
import { brainpoolP256r1 } from '../../src/crypto/public_key/elliptic/brainpool/brainpoolP256r1';
import { brainpoolP384r1 } from '../../src/crypto/public_key/elliptic/brainpool/brainpoolP384r1';
import { brainpoolP512r1 } from '../../src/crypto/public_key/elliptic/brainpool/brainpoolP512r1';
import util from '../../src/util';
const rfc7027 = [
{
'curve': 'brainpoolP256r1',
'dA': '81DB1EE100150FF2EA338D708271BE38300CB54241D79950F77B063039804F1D',
'QAx': '44106E913F92BC02A1705D9953A8414DB95E1AAA49E81D9E85F929A8E3100BE5',
'QAy': '8AB4846F11CACCB73CE49CBDD120F5A900A69FD32C272223F789EF10EB089BDC',
'dB': '55E40BC41E37E3E2AD25C3C6654511FFA8474A91A0032087593852D3E7D76BD3',
'QBx': '8D2D688C6CF93E1160AD04CC4429117DC2C41825E1E9FCA0ADDD34E6F1B39F7B',
'QBy': '990C57520812BE512641E47034832106BC7D3E8DD0E4C7F1136D7006547CEC6A',
'Zx': '89AFC39D41D3B327814B80940B042590F96556EC91E6AE7939BCE31F3A18BF2B',
'Zy': '49C27868F4ECA2179BFD7D59B1E3BF34C1DBDE61AE12931648F43E59632504DE'
},
{
'curve': 'brainpoolP384r1',
'dA': '1E20F5E048A5886F1F157C74E91BDE2B98C8B52D58E5003D57053FC4B0BD65D6F15EB5D1EE1610DF870795143627D042',
'QAx': '68B665DD91C195800650CDD363C625F4E742E8134667B767B1B476793588F885AB698C852D4A6E77A252D6380FCAF068',
'QAy': '55BC91A39C9EC01DEE36017B7D673A931236D2F1F5C83942D049E3FA20607493E0D038FF2FD30C2AB67D15C85F7FAA59',
'dB': '032640BC6003C59260F7250C3DB58CE647F98E1260ACCE4ACDA3DD869F74E01F8BA5E0324309DB6A9831497ABAC96670',
'QBx': '4D44326F269A597A5B58BBA565DA5556ED7FD9A8A9EB76C25F46DB69D19DC8CE6AD18E404B15738B2086DF37E71D1EB4',
'QBy': '62D692136DE56CBE93BF5FA3188EF58BC8A3A0EC6C1E151A21038A42E9185329B5B275903D192F8D4E1F32FE9CC78C48',
'Zx': '0BD9D3A7EA0B3D519D09D8E48D0785FB744A6B355E6304BC51C229FBBCE239BBADF6403715C35D4FB2A5444F575D4F42',
'Zy': '0DF213417EBE4D8E40A5F76F66C56470C489A3478D146DECF6DF0D94BAE9E598157290F8756066975F1DB34B2324B7BD'
},
{
'curve': 'brainpoolP512r1',
'dA': '16302FF0DBBB5A8D733DAB7141C1B45ACBC8715939677F6A56850A38BD87BD59B09E80279609FF333EB9D4C061231FB26F92EEB04982A5F1D1764CAD57665422',
'QAx': '0A420517E406AAC0ACDCE90FCD71487718D3B953EFD7FBEC5F7F27E28C6149999397E91E029E06457DB2D3E640668B392C2A7E737A7F0BF04436D11640FD09FD',
'QAy': '72E6882E8DB28AAD36237CD25D580DB23783961C8DC52DFA2EC138AD472A0FCEF3887CF62B623B2A87DE5C588301EA3E5FC269B373B60724F5E82A6AD147FDE7',
'dB': '230E18E1BCC88A362FA54E4EA3902009292F7F8033624FD471B5D8ACE49D12CFABBC19963DAB8E2F1EBA00BFFB29E4D72D13F2224562F405CB80503666B25429',
'QBx': '9D45F66DE5D67E2E6DB6E93A59CE0BB48106097FF78A081DE781CDB31FCE8CCBAAEA8DD4320C4119F1E9CD437A2EAB3731FA9668AB268D871DEDA55A5473199F',
'QBy': '2FDC313095BCDD5FB3A91636F07A959C8E86B5636A1E930E8396049CB481961D365CC11453A06C719835475B12CB52FC3C383BCE35E27EF194512B71876285FA',
'Zx': 'A7927098655F1F9976FA50A9D566865DC530331846381C87256BAF3226244B76D36403C024D7BBF0AA0803EAFF405D3D24F11A9B5C0BEF679FE1454B21C4CD1F',
'Zy': '7DB71C3DEF63212841C463E881BDCF055523BD368240E6C3143BD8DEF8B3B3223B95E0F53082FF5E412F4222537A43DF1C6D25729DDB51620A832BE6A26680A2'
}
];
const hexToBigint = hex => BigInt(`0x${hex}`);
// prettier-ignore
const BRAINPOOL = {
brainpoolP256r1,
brainpoolP384r1,
brainpoolP512r1
};
export default () => describe('Brainpool curves (RFC7027)', () => {
it('Field orders', () => {
const vectors = {
brainpoolP256r1: BigInt('0xa9fb57dba1eea9bc3e660a909d838d726e3bf623d52620282013481d1f6e5377'),
brainpoolP384r1: BigInt('0x8cb91e82a3386d280f5d6f7e50e641df152f7109ed5456b412b1da197fb71123acd3a729901d1a71874700133107ec53'),
brainpoolP512r1: BigInt('0xaadd9db8dbe9c48b3fd4e6ae33c9fc07cb308db3b3c9d20ed6639cca703308717d4d9b009bc66842aecda12ae6a380e62881ff2f2d82c68528aa6056583a48f3')
};
for (const n of Object.keys(vectors)) { expect(BRAINPOOL[n].CURVE.Fp.ORDER).to.deep.equal(vectors[n]); }
});
for (const v of rfc7027) {
it(v.curve, () => {
const curve = BRAINPOOL[v.curve];
const secKeyA = util.hexToUint8Array(v.dA);
const pubKeyA = curve.getPublicKey(secKeyA);
const pubPointA = curve.ProjectivePoint.fromHex(pubKeyA);
expect(pubPointA.x).to.equal(hexToBigint(v.QAx));
expect(pubPointA.y).to.equal(hexToBigint(v.QAy));
const secKeyB = hexToBigint(v.dB);
const pubKeyB = curve.getPublicKey(secKeyB);
const pubPointB = curve.ProjectivePoint.fromHex(pubKeyB);
expect(pubPointB.x).to.equal(hexToBigint(v.QBx));
expect(pubPointB.y).to.equal(hexToBigint(v.QBy));
const shared = curve.getSharedSecret(secKeyA, pubKeyB);
const sharedPoint = curve.ProjectivePoint.fromHex(shared);
expect(sharedPoint.x).to.equal(hexToBigint(v.Zx));
expect(sharedPoint.y).to.equal(hexToBigint(v.Zy));
expect(shared).to.deep.equal(curve.getSharedSecret(secKeyB, pubKeyA));
});
}
});

View File

@ -2,6 +2,7 @@ import testCipher from './cipher';
import testHash from './hash';
import testCrypto from './crypto';
import testElliptic from './elliptic';
import testBrainpoolRFC7027 from './brainpool_rfc7027';
import testECDH from './ecdh';
import testPKCS5 from './pkcs5';
import testAESKW from './aes_kw';
@ -17,6 +18,7 @@ export default () => describe('Crypto', function () {
testHash();
testCrypto();
testElliptic();
testBrainpoolRFC7027();
testECDH();
testPKCS5();
testAESKW();