diff options
author | Peter Dettman <peter.dettman@bouncycastle.org> | 2023-05-01 00:24:51 +0700 |
---|---|---|
committer | Peter Dettman <peter.dettman@bouncycastle.org> | 2023-05-01 00:24:51 +0700 |
commit | f0e8e9ce4dac3fc7fdbc18ea8e27a33001974a99 (patch) | |
tree | fb5a6ed66e3dd848dc4024e2d527bd4b6e6057ef | |
parent | Use Longs.NumberOfTrailingZeros (diff) | |
download | BouncyCastle.NET-ed25519-f0e8e9ce4dac3fc7fdbc18ea8e27a33001974a99.tar.xz |
Frodo: add support to PQC factories
- refactoring
-rw-r--r-- | crypto/src/asn1/bc/BCObjectIdentifiers.cs | 14 | ||||
-rw-r--r-- | crypto/src/pqc/crypto/frodo/FrodoEngine.cs | 16 | ||||
-rw-r--r-- | crypto/src/pqc/crypto/frodo/FrodoKEMExtractor.cs | 27 | ||||
-rw-r--r-- | crypto/src/pqc/crypto/frodo/FrodoKEMGenerator.cs | 11 | ||||
-rw-r--r-- | crypto/src/pqc/crypto/frodo/FrodoKeyGenerationParameters.cs | 13 | ||||
-rw-r--r-- | crypto/src/pqc/crypto/frodo/FrodoKeyPairGenerator.cs | 48 | ||||
-rw-r--r-- | crypto/src/pqc/crypto/frodo/FrodoKeyParameters.cs | 2 | ||||
-rw-r--r-- | crypto/src/pqc/crypto/frodo/FrodoParameters.cs | 87 | ||||
-rw-r--r-- | crypto/src/pqc/crypto/frodo/FrodoPrivateKeyParameters.cs | 2 | ||||
-rw-r--r-- | crypto/src/pqc/crypto/utils/PqcPrivateKeyFactory.cs | 8 | ||||
-rw-r--r-- | crypto/src/pqc/crypto/utils/PqcPrivateKeyInfoFactory.cs | 14 | ||||
-rw-r--r-- | crypto/src/pqc/crypto/utils/PqcPublicKeyFactory.cs | 23 | ||||
-rw-r--r-- | crypto/src/pqc/crypto/utils/PqcSubjectPublicKeyInfoFactory.cs | 10 | ||||
-rw-r--r-- | crypto/src/pqc/crypto/utils/PqcUtilities.cs | 82 | ||||
-rw-r--r-- | crypto/test/src/pqc/crypto/test/FrodoVectorTest.cs | 32 |
15 files changed, 245 insertions, 144 deletions
diff --git a/crypto/src/asn1/bc/BCObjectIdentifiers.cs b/crypto/src/asn1/bc/BCObjectIdentifiers.cs index d526980e5..face6f8d3 100644 --- a/crypto/src/asn1/bc/BCObjectIdentifiers.cs +++ b/crypto/src/asn1/bc/BCObjectIdentifiers.cs @@ -178,7 +178,19 @@ namespace Org.BouncyCastle.Asn1.BC public static readonly DerObjectIdentifier mceliece6960119f_r3 = pqc_kem_mceliece.Branch("8"); public static readonly DerObjectIdentifier mceliece8192128_r3 = pqc_kem_mceliece.Branch("9"); public static readonly DerObjectIdentifier mceliece8192128f_r3 = pqc_kem_mceliece.Branch("10"); - + + /** + * Frodo + */ + public static readonly DerObjectIdentifier pqc_kem_frodo = bc_kem.Branch("2"); + + public static readonly DerObjectIdentifier frodokem640aes = pqc_kem_frodo.Branch("1"); + public static readonly DerObjectIdentifier frodokem640shake = pqc_kem_frodo.Branch("2"); + public static readonly DerObjectIdentifier frodokem976aes = pqc_kem_frodo.Branch("3"); + public static readonly DerObjectIdentifier frodokem976shake = pqc_kem_frodo.Branch("4"); + public static readonly DerObjectIdentifier frodokem1344aes = pqc_kem_frodo.Branch("5"); + public static readonly DerObjectIdentifier frodokem1344shake = pqc_kem_frodo.Branch("6"); + /** * SABER */ diff --git a/crypto/src/pqc/crypto/frodo/FrodoEngine.cs b/crypto/src/pqc/crypto/frodo/FrodoEngine.cs index 6aa3c8d89..905274cc3 100644 --- a/crypto/src/pqc/crypto/frodo/FrodoEngine.cs +++ b/crypto/src/pqc/crypto/frodo/FrodoEngine.cs @@ -59,6 +59,7 @@ namespace Org.BouncyCastle.Pqc.Crypto.Frodo public int PrivateKeySize => len_sk_bytes; public int PublicKeySize => len_pk_bytes; + // TODO[api] IDigest should be IXof? public FrodoEngine(int n, int D, int B, short[] cdf_table, IDigest digest, FrodoMatrixGenerator mGen) { this.n = n; @@ -380,18 +381,17 @@ namespace Org.BouncyCastle.Pqc.Crypto.Frodo ((IXof) digest).OutputFinal(pkh, 0, len_pkh_bytes); // 3. seedSE || k = SHAKE(pkh || mu, len_seedSE + len_k) (length in bits) - byte[] seedSE_k = new byte[len_seedSE + len_k]; + byte[] x96_seedSE_k = new byte[len_seedSE + len_k]; + x96_seedSE_k[0] = 0x96; + digest.BlockUpdate(pkh, 0, len_pkh_bytes); digest.BlockUpdate(mu, 0, len_mu_bytes); - ((IXof) digest).OutputFinal(seedSE_k, 0, len_seedSE_bytes + len_k_bytes); - - byte[] seedSE = Arrays.CopyOfRange(seedSE_k, 0, len_seedSE_bytes); - byte[] k = Arrays.CopyOfRange(seedSE_k, len_seedSE_bytes, len_seedSE_bytes + len_k_bytes); + ((IXof) digest).OutputFinal(x96_seedSE_k, 1, len_seedSE_bytes + len_k_bytes); // 4. r = SHAKE(0x96 || seedSE, 2*mbar*n + mbar*nbar*len_chi) (length in bits) byte[] rbytes = new byte[(2 * mbar * n + mbar * nbar) * len_chi_bytes]; - digest.Update((byte) 0x96); - digest.BlockUpdate(seedSE, 0, seedSE.Length); + + digest.BlockUpdate(x96_seedSE_k, 0, 1 + len_seedSE_bytes); ((IXof) digest).OutputFinal(rbytes, 0, rbytes.Length); short[] r = new short[rbytes.Length / 2]; @@ -435,7 +435,7 @@ namespace Org.BouncyCastle.Pqc.Crypto.Frodo Array.Copy(Arrays.Concatenate(c1, c2), 0, ct, 0, len_ct_bytes); digest.BlockUpdate(c1, 0, c1.Length); digest.BlockUpdate(c2, 0, c2.Length); - digest.BlockUpdate(k, 0, len_k_bytes); + digest.BlockUpdate(x96_seedSE_k, 1 + len_seedSE_bytes, len_k_bytes); ((IXof) digest).OutputFinal(ss, 0, len_s_bytes); } diff --git a/crypto/src/pqc/crypto/frodo/FrodoKEMExtractor.cs b/crypto/src/pqc/crypto/frodo/FrodoKEMExtractor.cs index 8a26e90a4..a3805e39d 100644 --- a/crypto/src/pqc/crypto/frodo/FrodoKEMExtractor.cs +++ b/crypto/src/pqc/crypto/frodo/FrodoKEMExtractor.cs @@ -1,34 +1,29 @@ - using Org.BouncyCastle.Crypto; namespace Org.BouncyCastle.Pqc.Crypto.Frodo { - + // TODO[api] FrodoKemExtractor public class FrodoKEMExtractor : IEncapsulatedSecretExtractor { - private FrodoEngine engine; - - private FrodoKeyParameters key; + private readonly FrodoKeyParameters m_key; + private readonly FrodoEngine m_engine; public FrodoKEMExtractor(FrodoKeyParameters privParams) { - this.key = privParams; - InitCipher(key.Parameters); - } - - private void InitCipher(FrodoParameters param) - { - engine = param.Engine; + m_key = privParams; +#pragma warning disable CS0618 // Type or member is obsolete + m_engine = privParams.Parameters.Engine; +#pragma warning restore CS0618 // Type or member is obsolete } public byte[] ExtractSecret(byte[] encapsulation) { - byte[] session_key = new byte[engine.SessionKeySize]; - engine.kem_dec(session_key, encapsulation, ((FrodoPrivateKeyParameters)key).privateKey); + byte[] session_key = new byte[m_engine.SessionKeySize]; + m_engine.kem_dec(session_key, encapsulation, ((FrodoPrivateKeyParameters)m_key).privateKey); return session_key; } - public int EncapsulationLength => (int)engine.CipherTextSize; + public int EncapsulationLength => m_engine.CipherTextSize; } -} \ No newline at end of file +} diff --git a/crypto/src/pqc/crypto/frodo/FrodoKEMGenerator.cs b/crypto/src/pqc/crypto/frodo/FrodoKEMGenerator.cs index 4cfde03fb..cf764ef25 100644 --- a/crypto/src/pqc/crypto/frodo/FrodoKEMGenerator.cs +++ b/crypto/src/pqc/crypto/frodo/FrodoKEMGenerator.cs @@ -4,24 +4,27 @@ using Org.BouncyCastle.Security; namespace Org.BouncyCastle.Pqc.Crypto.Frodo { + // TODO[api] FrodoKemGenerator public class FrodoKEMGenerator : IEncapsulatedSecretGenerator { // the source of randomness - private readonly SecureRandom sr; + private readonly SecureRandom m_random; public FrodoKEMGenerator(SecureRandom random) { - this.sr = random; + m_random = random; } public ISecretWithEncapsulation GenerateEncapsulated(AsymmetricKeyParameter recipientKey) { - FrodoPublicKeyParameters key = (FrodoPublicKeyParameters) recipientKey; + FrodoPublicKeyParameters key = (FrodoPublicKeyParameters)recipientKey; +#pragma warning disable CS0618 // Type or member is obsolete FrodoEngine engine = key.Parameters.Engine; +#pragma warning restore CS0618 // Type or member is obsolete byte[] cipher_text = new byte[engine.CipherTextSize]; byte[] sessionKey = new byte[engine.SessionKeySize]; - engine.kem_enc(cipher_text, sessionKey, key.m_publicKey, sr); + engine.kem_enc(cipher_text, sessionKey, key.m_publicKey, m_random); return new SecretWithEncapsulationImpl(sessionKey, cipher_text); } } diff --git a/crypto/src/pqc/crypto/frodo/FrodoKeyGenerationParameters.cs b/crypto/src/pqc/crypto/frodo/FrodoKeyGenerationParameters.cs index 062441b8f..e10ee6395 100644 --- a/crypto/src/pqc/crypto/frodo/FrodoKeyGenerationParameters.cs +++ b/crypto/src/pqc/crypto/frodo/FrodoKeyGenerationParameters.cs @@ -1,4 +1,3 @@ - using Org.BouncyCastle.Crypto; using Org.BouncyCastle.Security; @@ -7,16 +6,14 @@ namespace Org.BouncyCastle.Pqc.Crypto.Frodo public class FrodoKeyGenerationParameters : KeyGenerationParameters { - private FrodoParameters parameters; + private readonly FrodoParameters m_parameters; - public FrodoKeyGenerationParameters( - SecureRandom random, - FrodoParameters frodoParameters) + public FrodoKeyGenerationParameters(SecureRandom random, FrodoParameters frodoParameters) : base(random, 256) { - this.parameters = frodoParameters; + m_parameters = frodoParameters; } - public FrodoParameters Parameters => parameters; + public FrodoParameters Parameters => m_parameters; } -} \ No newline at end of file +} diff --git a/crypto/src/pqc/crypto/frodo/FrodoKeyPairGenerator.cs b/crypto/src/pqc/crypto/frodo/FrodoKeyPairGenerator.cs index 464161444..c10087ea2 100644 --- a/crypto/src/pqc/crypto/frodo/FrodoKeyPairGenerator.cs +++ b/crypto/src/pqc/crypto/frodo/FrodoKeyPairGenerator.cs @@ -1,4 +1,3 @@ - using Org.BouncyCastle.Crypto; using Org.BouncyCastle.Security; @@ -7,46 +6,29 @@ namespace Org.BouncyCastle.Pqc.Crypto.Frodo public class FrodoKeyPairGenerator : IAsymmetricCipherKeyPairGenerator { - private FrodoKeyGenerationParameters frodoParams; - - private int n; - private int D; - private int B; + private FrodoParameters m_parameters; + private SecureRandom m_random; - private SecureRandom random; - - private void Initialize( - KeyGenerationParameters param) + public void Init(KeyGenerationParameters param) { - frodoParams = (FrodoKeyGenerationParameters) param; - random = param.Random; + FrodoKeyGenerationParameters frodoParams = (FrodoKeyGenerationParameters)param; - n = frodoParams.Parameters.N; - D = frodoParams.Parameters.D; - B = frodoParams.Parameters.B; + m_parameters = frodoParams.Parameters; + m_random = frodoParams.Random; } - private AsymmetricCipherKeyPair GenKeyPair() + public AsymmetricCipherKeyPair GenerateKeyPair() { - FrodoEngine engine = frodoParams.Parameters.Engine; +#pragma warning disable CS0618 // Type or member is obsolete + FrodoEngine engine = m_parameters.Engine; +#pragma warning restore CS0618 // Type or member is obsolete byte[] sk = new byte[engine.PrivateKeySize]; byte[] pk = new byte[engine.PublicKeySize]; - engine.kem_keypair(pk, sk, random); - - FrodoPublicKeyParameters pubKey = new FrodoPublicKeyParameters(frodoParams.Parameters, pk); - FrodoPrivateKeyParameters privKey = new FrodoPrivateKeyParameters(frodoParams.Parameters, sk); - return new AsymmetricCipherKeyPair(pubKey, privKey); - } + engine.kem_keypair(pk, sk, m_random); - public void Init(KeyGenerationParameters param) - { - this.Initialize(param); + return new AsymmetricCipherKeyPair( + new FrodoPublicKeyParameters(m_parameters, pk), + new FrodoPrivateKeyParameters(m_parameters, sk)); } - - public AsymmetricCipherKeyPair GenerateKeyPair() - { - return GenKeyPair(); - } - } -} \ No newline at end of file +} diff --git a/crypto/src/pqc/crypto/frodo/FrodoKeyParameters.cs b/crypto/src/pqc/crypto/frodo/FrodoKeyParameters.cs index d195eba2b..4b9e4f1d9 100644 --- a/crypto/src/pqc/crypto/frodo/FrodoKeyParameters.cs +++ b/crypto/src/pqc/crypto/frodo/FrodoKeyParameters.cs @@ -10,7 +10,7 @@ namespace Org.BouncyCastle.Pqc.Crypto.Frodo internal FrodoKeyParameters(bool isPrivate, FrodoParameters parameters) : base(isPrivate) { - this.m_parameters = parameters; + m_parameters = parameters; } public FrodoParameters Parameters => m_parameters; diff --git a/crypto/src/pqc/crypto/frodo/FrodoParameters.cs b/crypto/src/pqc/crypto/frodo/FrodoParameters.cs index 3f8fe254d..6f84f1b0c 100644 --- a/crypto/src/pqc/crypto/frodo/FrodoParameters.cs +++ b/crypto/src/pqc/crypto/frodo/FrodoParameters.cs @@ -1,35 +1,53 @@ +using System; + using Org.BouncyCastle.Crypto; using Org.BouncyCastle.Crypto.Digests; +using Org.BouncyCastle.Utilities; namespace Org.BouncyCastle.Pqc.Crypto.Frodo { public sealed class FrodoParameters : ICipherParameters { - private static short[] cdf_table640 = {4643, 13363, 20579, 25843, 29227, 31145, 32103, 32525, 32689, 32745, 32762, 32766, 32767}; - private static short[] cdf_table976 = {5638, 15915, 23689, 28571, 31116, 32217, 32613, 32731, 32760, 32766, 32767}; - private static short[] cdf_table1344 = {9142, 23462, 30338, 32361, 32725, 32765, 32767}; - - public static FrodoParameters frodokem19888r3 = new FrodoParameters("frodokem19888", 640, 15, 2, cdf_table640, new ShakeDigest(128), new FrodoMatrixGenerator.Aes128MatrixGenerator(640, (1<<15))); - public static FrodoParameters frodokem19888shaker3 = new FrodoParameters("frodokem19888shake", 640, 15, 2, cdf_table640, new ShakeDigest(128), new FrodoMatrixGenerator.Shake128MatrixGenerator(640, (1<<15))); - - public static FrodoParameters frodokem31296r3 = new FrodoParameters("frodokem31296", 976, 16, 3, cdf_table976, new ShakeDigest(256), new FrodoMatrixGenerator.Aes128MatrixGenerator(976, (1<<16))); - public static FrodoParameters frodokem31296shaker3 = new FrodoParameters("frodokem31296shake", 976, 16, 3, cdf_table976, new ShakeDigest(256), new FrodoMatrixGenerator.Shake128MatrixGenerator(976, (1<<16))); - - public static FrodoParameters frodokem43088r3 = new FrodoParameters("frodokem43088", 1344, 16, 4, cdf_table1344, new ShakeDigest(256), new FrodoMatrixGenerator.Aes128MatrixGenerator(1344, (1<<16))); - public static FrodoParameters frodokem43088shaker3 = new FrodoParameters("frodokem43088shake", 1344, 16, 4, cdf_table1344, new ShakeDigest(256), new FrodoMatrixGenerator.Shake128MatrixGenerator(1344, (1<<16))); - - private string name; - private int n; - private int d; - private int b; - private short[] cdf_table; - private IDigest digest; - private FrodoMatrixGenerator mGen; - private int defaultKeySize; - private FrodoEngine engine; - - private FrodoParameters(string name, int n, int d, int b, short[] cdf_table, IDigest digest, + private static readonly short[] cdf_table640 = {4643, 13363, 20579, 25843, 29227, 31145, 32103, 32525, 32689, 32745, 32762, 32766, 32767}; + private static readonly short[] cdf_table976 = {5638, 15915, 23689, 28571, 31116, 32217, 32613, 32731, 32760, 32766, 32767}; + private static readonly short[] cdf_table1344 = {9142, 23462, 30338, 32361, 32725, 32765, 32767}; + + public static readonly FrodoParameters frodokem640aes = new FrodoParameters("frodokem19888", 640, 15, 2, cdf_table640, new ShakeDigest(128), new FrodoMatrixGenerator.Aes128MatrixGenerator(640, (1 << 15))); + public static readonly FrodoParameters frodokem640shake = new FrodoParameters("frodokem19888shake", 640, 15, 2, cdf_table640, new ShakeDigest(128), new FrodoMatrixGenerator.Shake128MatrixGenerator(640, (1 << 15))); + + public static readonly FrodoParameters frodokem976aes = new FrodoParameters("frodokem31296", 976, 16, 3, cdf_table976, new ShakeDigest(256), new FrodoMatrixGenerator.Aes128MatrixGenerator(976, (1 << 16))); + public static readonly FrodoParameters frodokem976shake = new FrodoParameters("frodokem31296shake", 976, 16, 3, cdf_table976, new ShakeDigest(256), new FrodoMatrixGenerator.Shake128MatrixGenerator(976, (1 << 16))); + + public static readonly FrodoParameters frodokem1344aes = new FrodoParameters("frodokem43088", 1344, 16, 4, cdf_table1344, new ShakeDigest(256), new FrodoMatrixGenerator.Aes128MatrixGenerator(1344, (1 << 16))); + public static readonly FrodoParameters frodokem1344shake = new FrodoParameters("frodokem43088shake", 1344, 16, 4, cdf_table1344, new ShakeDigest(256), new FrodoMatrixGenerator.Shake128MatrixGenerator(1344, (1 << 16))); + + [Obsolete("Use 'frodokem640aes' instead")] + public static FrodoParameters frodokem19888r3 = frodokem640aes; + [Obsolete("Use 'frodokem640shake' instead")] + public static FrodoParameters frodokem19888shaker3 = frodokem640shake; + + [Obsolete("Use 'frodokem976aes' instead")] + public static FrodoParameters frodokem31296r3 = frodokem976aes; + [Obsolete("Use 'frodokem976shake' instead")] + public static FrodoParameters frodokem31296shaker3 = frodokem976shake; + + [Obsolete("Use 'frodokem1344aes' instead")] + public static FrodoParameters frodokem43088r3 = frodokem1344aes; + [Obsolete("Use 'frodokem1344shake' instead")] + public static FrodoParameters frodokem43088shaker3 = frodokem1344shake; + + private readonly string name; + private readonly int n; + private readonly int d; + private readonly int b; + private readonly short[] cdf_table; + private readonly ShakeDigest digest; + private readonly FrodoMatrixGenerator mGen; + private readonly int defaultKeySize; + private readonly FrodoEngine engine; + + private FrodoParameters(string name, int n, int d, int b, short[] cdf_table, ShakeDigest digest, FrodoMatrixGenerator mGen) { this.name = name; @@ -39,26 +57,33 @@ namespace Org.BouncyCastle.Pqc.Crypto.Frodo this.cdf_table = cdf_table; this.digest = digest; this.mGen = mGen; - this.defaultKeySize = B * FrodoEngine.nbar * FrodoEngine.nbar; + this.defaultKeySize = b * FrodoEngine.nbar * FrodoEngine.nbar; this.engine = new FrodoEngine(n, d, b, cdf_table, digest, mGen); } + public string Name => name; + + public int DefaultKeySize => defaultKeySize; + + [Obsolete("Will be removed")] public FrodoEngine Engine => engine; + [Obsolete("Will be removed")] public int N => n; - public string Name => name; - + [Obsolete("Will be removed")] public int D => d; + [Obsolete("Will be removed")] public int B => b; - public short[] CdfTable => cdf_table; + [Obsolete("Will be removed")] + public short[] CdfTable => Arrays.Clone(cdf_table); - public IDigest Digest => digest; - - public int DefaultKeySize => defaultKeySize; + [Obsolete("Will be removed")] + public IDigest Digest => new ShakeDigest(digest); + [Obsolete("Will be removed")] public FrodoMatrixGenerator MGen => mGen; } } diff --git a/crypto/src/pqc/crypto/frodo/FrodoPrivateKeyParameters.cs b/crypto/src/pqc/crypto/frodo/FrodoPrivateKeyParameters.cs index cfbf1c3ea..cc3d1e182 100644 --- a/crypto/src/pqc/crypto/frodo/FrodoPrivateKeyParameters.cs +++ b/crypto/src/pqc/crypto/frodo/FrodoPrivateKeyParameters.cs @@ -5,7 +5,7 @@ namespace Org.BouncyCastle.Pqc.Crypto.Frodo public sealed class FrodoPrivateKeyParameters : FrodoKeyParameters { - internal byte[] privateKey; + internal readonly byte[] privateKey; public FrodoPrivateKeyParameters(FrodoParameters parameters, byte[] privateKey) : base(true, parameters) diff --git a/crypto/src/pqc/crypto/utils/PqcPrivateKeyFactory.cs b/crypto/src/pqc/crypto/utils/PqcPrivateKeyFactory.cs index f01988169..01566c8b0 100644 --- a/crypto/src/pqc/crypto/utils/PqcPrivateKeyFactory.cs +++ b/crypto/src/pqc/crypto/utils/PqcPrivateKeyFactory.cs @@ -14,6 +14,7 @@ using Org.BouncyCastle.Pqc.Crypto.Cmce; using Org.BouncyCastle.Pqc.Crypto.Crystals.Dilithium; using Org.BouncyCastle.Pqc.Crypto.Crystals.Kyber; using Org.BouncyCastle.Pqc.Crypto.Falcon; +using Org.BouncyCastle.Pqc.Crypto.Frodo; using Org.BouncyCastle.Pqc.Crypto.Hqc; using Org.BouncyCastle.Pqc.Crypto.Lms; using Org.BouncyCastle.Pqc.Crypto.Picnic; @@ -78,6 +79,13 @@ namespace Org.BouncyCastle.Pqc.Crypto.Utilities return new CmcePrivateKeyParameters(spParams, cmceKey.Delta, cmceKey.C, cmceKey.G, cmceKey.Alpha, cmceKey.S); } + if (algOID.On(BCObjectIdentifiers.pqc_kem_frodo)) + { + byte[] keyEnc = Asn1OctetString.GetInstance(keyInfo.ParsePrivateKey()).GetOctets(); + FrodoParameters spParams = PqcUtilities.FrodoParamsLookup(keyInfo.PrivateKeyAlgorithm.Algorithm); + + return new FrodoPrivateKeyParameters(spParams, keyEnc); + } if (algOID.On(BCObjectIdentifiers.sphincsPlus)) { byte[] keyEnc = Asn1OctetString.GetInstance(keyInfo.ParsePrivateKey()).GetOctets(); diff --git a/crypto/src/pqc/crypto/utils/PqcPrivateKeyInfoFactory.cs b/crypto/src/pqc/crypto/utils/PqcPrivateKeyInfoFactory.cs index 3d1b1b679..6f7bed2ca 100644 --- a/crypto/src/pqc/crypto/utils/PqcPrivateKeyInfoFactory.cs +++ b/crypto/src/pqc/crypto/utils/PqcPrivateKeyInfoFactory.cs @@ -10,6 +10,7 @@ using Org.BouncyCastle.Pqc.Crypto.Cmce; using Org.BouncyCastle.Pqc.Crypto.Crystals.Dilithium; using Org.BouncyCastle.Pqc.Crypto.Crystals.Kyber; using Org.BouncyCastle.Pqc.Crypto.Falcon; +using Org.BouncyCastle.Pqc.Crypto.Frodo; using Org.BouncyCastle.Pqc.Crypto.Hqc; using Org.BouncyCastle.Pqc.Crypto.Lms; using Org.BouncyCastle.Pqc.Crypto.Picnic; @@ -67,8 +68,8 @@ namespace Org.BouncyCastle.Pqc.Crypto.Utilities if (privateKey is CmcePrivateKeyParameters cmcePrivateKeyParameters) { byte[] encoding = cmcePrivateKeyParameters.GetEncoded(); - AlgorithmIdentifier algorithmIdentifier = - new AlgorithmIdentifier(PqcUtilities.McElieceOidLookup(cmcePrivateKeyParameters.Parameters)); + AlgorithmIdentifier algorithmIdentifier = new AlgorithmIdentifier( + PqcUtilities.McElieceOidLookup(cmcePrivateKeyParameters.Parameters)); CmcePublicKey CmcePub = new CmcePublicKey(cmcePrivateKeyParameters.ReconstructPublicKey()); CmcePrivateKey CmcePriv = new CmcePrivateKey(0, cmcePrivateKeyParameters.Delta, @@ -76,6 +77,15 @@ namespace Org.BouncyCastle.Pqc.Crypto.Utilities cmcePrivateKeyParameters.S, CmcePub); return new PrivateKeyInfo(algorithmIdentifier, CmcePriv, attributes); } + if (privateKey is FrodoPrivateKeyParameters frodoPrivateKeyParameters) + { + byte[] encoding = frodoPrivateKeyParameters.GetEncoded(); + + AlgorithmIdentifier algorithmIdentifier = new AlgorithmIdentifier( + PqcUtilities.FrodoOidLookup(frodoPrivateKeyParameters.Parameters)); + + return new PrivateKeyInfo(algorithmIdentifier, new DerOctetString(encoding), attributes); + } if (privateKey is SaberPrivateKeyParameters saberPrivateKeyParameters) { byte[] encoding = saberPrivateKeyParameters.GetEncoded(); diff --git a/crypto/src/pqc/crypto/utils/PqcPublicKeyFactory.cs b/crypto/src/pqc/crypto/utils/PqcPublicKeyFactory.cs index 909b93577..899ebc28e 100644 --- a/crypto/src/pqc/crypto/utils/PqcPublicKeyFactory.cs +++ b/crypto/src/pqc/crypto/utils/PqcPublicKeyFactory.cs @@ -14,6 +14,7 @@ using Org.BouncyCastle.Pqc.Crypto.Cmce; using Org.BouncyCastle.Pqc.Crypto.Crystals.Dilithium; using Org.BouncyCastle.Pqc.Crypto.Crystals.Kyber; using Org.BouncyCastle.Pqc.Crypto.Falcon; +using Org.BouncyCastle.Pqc.Crypto.Frodo; using Org.BouncyCastle.Pqc.Crypto.Hqc; using Org.BouncyCastle.Pqc.Crypto.Lms; using Org.BouncyCastle.Pqc.Crypto.Picnic; @@ -49,7 +50,14 @@ namespace Org.BouncyCastle.Pqc.Crypto.Utilities Converters[BCObjectIdentifiers.mceliece6960119f_r3] = new CmceConverter(); Converters[BCObjectIdentifiers.mceliece8192128_r3] = new CmceConverter(); Converters[BCObjectIdentifiers.mceliece8192128f_r3] = new CmceConverter(); - + + Converters[BCObjectIdentifiers.frodokem640aes] = new FrodoConverter(); + Converters[BCObjectIdentifiers.frodokem640shake] = new FrodoConverter(); + Converters[BCObjectIdentifiers.frodokem976aes] = new FrodoConverter(); + Converters[BCObjectIdentifiers.frodokem976shake] = new FrodoConverter(); + Converters[BCObjectIdentifiers.frodokem1344aes] = new FrodoConverter(); + Converters[BCObjectIdentifiers.frodokem1344shake] = new FrodoConverter(); + Converters[BCObjectIdentifiers.lightsaberkem128r3] = new SaberConverter(); Converters[BCObjectIdentifiers.saberkem128r3] = new SaberConverter(); Converters[BCObjectIdentifiers.firesaberkem128r3] = new SaberConverter(); @@ -217,6 +225,19 @@ namespace Org.BouncyCastle.Pqc.Crypto.Utilities } } + private class FrodoConverter + : SubjectPublicKeyInfoConverter + { + internal override AsymmetricKeyParameter GetPublicKeyParameters(SubjectPublicKeyInfo keyInfo, object defaultParams) + { + byte[] keyEnc = Asn1OctetString.GetInstance(keyInfo.ParsePublicKey()).GetOctets(); + + FrodoParameters fParams = PqcUtilities.FrodoParamsLookup(keyInfo.AlgorithmID.Algorithm); + + return new FrodoPublicKeyParameters(fParams, keyEnc); + } + } + private class SaberConverter : SubjectPublicKeyInfoConverter { diff --git a/crypto/src/pqc/crypto/utils/PqcSubjectPublicKeyInfoFactory.cs b/crypto/src/pqc/crypto/utils/PqcSubjectPublicKeyInfoFactory.cs index c13255c68..1bdf031f6 100644 --- a/crypto/src/pqc/crypto/utils/PqcSubjectPublicKeyInfoFactory.cs +++ b/crypto/src/pqc/crypto/utils/PqcSubjectPublicKeyInfoFactory.cs @@ -10,6 +10,7 @@ using Org.BouncyCastle.Pqc.Crypto.Cmce; using Org.BouncyCastle.Pqc.Crypto.Crystals.Dilithium; using Org.BouncyCastle.Pqc.Crypto.Crystals.Kyber; using Org.BouncyCastle.Pqc.Crypto.Falcon; +using Org.BouncyCastle.Pqc.Crypto.Frodo; using Org.BouncyCastle.Pqc.Crypto.Hqc; using Org.BouncyCastle.Pqc.Crypto.Lms; using Org.BouncyCastle.Pqc.Crypto.Picnic; @@ -71,6 +72,15 @@ namespace Org.BouncyCastle.Pqc.Crypto.Utilities // https://datatracker.ietf.org/doc/draft-uni-qsckeys/ return new SubjectPublicKeyInfo(algorithmIdentifier, new CmcePublicKey(encoding)); } + else if (publicKey is FrodoPublicKeyParameters frodoPublicKeyParameters) + { + byte[] encoding = frodoPublicKeyParameters.GetEncoded(); + + AlgorithmIdentifier algorithmIdentifier = new AlgorithmIdentifier( + PqcUtilities.FrodoOidLookup(frodoPublicKeyParameters.Parameters)); + + return new SubjectPublicKeyInfo(algorithmIdentifier, new DerOctetString(encoding)); + } if (publicKey is SaberPublicKeyParameters saberPublicKeyParameters) { byte[] encoding = saberPublicKeyParameters.GetEncoded(); diff --git a/crypto/src/pqc/crypto/utils/PqcUtilities.cs b/crypto/src/pqc/crypto/utils/PqcUtilities.cs index 67e58fd28..101e3c846 100644 --- a/crypto/src/pqc/crypto/utils/PqcUtilities.cs +++ b/crypto/src/pqc/crypto/utils/PqcUtilities.cs @@ -7,11 +7,13 @@ using Org.BouncyCastle.Pqc.Crypto.Cmce; using Org.BouncyCastle.Pqc.Crypto.Crystals.Dilithium; using Org.BouncyCastle.Pqc.Crypto.Crystals.Kyber; using Org.BouncyCastle.Pqc.Crypto.Falcon; +using Org.BouncyCastle.Pqc.Crypto.Frodo; using Org.BouncyCastle.Pqc.Crypto.Hqc; using Org.BouncyCastle.Pqc.Crypto.Picnic; using Org.BouncyCastle.Pqc.Crypto.Saber; using Org.BouncyCastle.Pqc.Crypto.Sike; using Org.BouncyCastle.Pqc.Crypto.SphincsPlus; +using Org.BouncyCastle.Utilities.Collections; namespace Org.BouncyCastle.Pqc.Crypto.Utilities { @@ -19,7 +21,10 @@ namespace Org.BouncyCastle.Pqc.Crypto.Utilities { private readonly static Dictionary<CmceParameters, DerObjectIdentifier> mcElieceOids = new Dictionary<CmceParameters, DerObjectIdentifier>(); private readonly static Dictionary<DerObjectIdentifier, CmceParameters> mcElieceParams = new Dictionary<DerObjectIdentifier, CmceParameters>(); - + + private readonly static Dictionary<FrodoParameters, DerObjectIdentifier> frodoOids = new Dictionary<FrodoParameters, DerObjectIdentifier>(); + private readonly static Dictionary<DerObjectIdentifier, FrodoParameters> frodoParams = new Dictionary<DerObjectIdentifier, FrodoParameters>(); + private readonly static Dictionary<SaberParameters, DerObjectIdentifier> saberOids = new Dictionary<SaberParameters, DerObjectIdentifier>(); private readonly static Dictionary<DerObjectIdentifier, SaberParameters> saberParams = new Dictionary<DerObjectIdentifier, SaberParameters>(); @@ -70,7 +75,21 @@ namespace Org.BouncyCastle.Pqc.Crypto.Utilities mcElieceParams[BCObjectIdentifiers.mceliece6960119f_r3] = CmceParameters.mceliece6960119fr3; mcElieceParams[BCObjectIdentifiers.mceliece8192128_r3] = CmceParameters.mceliece8192128r3; mcElieceParams[BCObjectIdentifiers.mceliece8192128f_r3] = CmceParameters.mceliece8192128fr3; - + + frodoOids[FrodoParameters.frodokem640aes] = BCObjectIdentifiers.frodokem640aes; + frodoOids[FrodoParameters.frodokem640shake] = BCObjectIdentifiers.frodokem640shake; + frodoOids[FrodoParameters.frodokem976aes] = BCObjectIdentifiers.frodokem976aes; + frodoOids[FrodoParameters.frodokem976shake] = BCObjectIdentifiers.frodokem976shake; + frodoOids[FrodoParameters.frodokem1344aes] = BCObjectIdentifiers.frodokem1344aes; + frodoOids[FrodoParameters.frodokem1344shake] = BCObjectIdentifiers.frodokem1344shake; + + frodoParams[BCObjectIdentifiers.frodokem640aes] = FrodoParameters.frodokem640aes; + frodoParams[BCObjectIdentifiers.frodokem640shake] = FrodoParameters.frodokem640shake; + frodoParams[BCObjectIdentifiers.frodokem976aes] = FrodoParameters.frodokem976aes; + frodoParams[BCObjectIdentifiers.frodokem976shake] = FrodoParameters.frodokem976shake; + frodoParams[BCObjectIdentifiers.frodokem1344aes] = FrodoParameters.frodokem1344aes; + frodoParams[BCObjectIdentifiers.frodokem1344shake] = FrodoParameters.frodokem1344shake; + saberOids[SaberParameters.lightsaberkem128r3] = BCObjectIdentifiers.lightsaberkem128r3; saberOids[SaberParameters.saberkem128r3] = BCObjectIdentifiers.saberkem128r3; saberOids[SaberParameters.firesaberkem128r3] = BCObjectIdentifiers.firesaberkem128r3; @@ -209,45 +228,62 @@ namespace Org.BouncyCastle.Pqc.Crypto.Utilities internal static DerObjectIdentifier McElieceOidLookup(CmceParameters parameters) { - return mcElieceOids[parameters]; + return CollectionUtilities.GetValueOrNull(mcElieceOids, parameters); } internal static CmceParameters McElieceParamsLookup(DerObjectIdentifier oid) { - return mcElieceParams[oid]; + return CollectionUtilities.GetValueOrNull(mcElieceParams, oid); + } + + internal static DerObjectIdentifier FrodoOidLookup(FrodoParameters parameters) + { + return CollectionUtilities.GetValueOrNull(frodoOids, parameters); + } + + internal static FrodoParameters FrodoParamsLookup(DerObjectIdentifier oid) + { + return CollectionUtilities.GetValueOrNull(frodoParams, oid); } - + internal static DerObjectIdentifier SaberOidLookup(SaberParameters parameters) { - return saberOids[parameters]; + return CollectionUtilities.GetValueOrNull(saberOids, parameters); } + internal static SaberParameters SaberParamsLookup(DerObjectIdentifier oid) { - return saberParams[oid]; + return CollectionUtilities.GetValueOrNull(saberParams, oid); } + internal static KyberParameters KyberParamsLookup(DerObjectIdentifier oid) { - return kyberParams[oid]; - } + return CollectionUtilities.GetValueOrNull(kyberParams, oid); + } + internal static DerObjectIdentifier KyberOidLookup(KyberParameters parameters) { - return kyberOids[parameters]; + return CollectionUtilities.GetValueOrNull(kyberOids, parameters); } + internal static FalconParameters FalconParamsLookup(DerObjectIdentifier oid) { - return falconParams[oid]; + return CollectionUtilities.GetValueOrNull(falconParams, oid); } + internal static DerObjectIdentifier FalconOidLookup(FalconParameters parameters) { - return falconOids[parameters]; + return CollectionUtilities.GetValueOrNull(falconOids, parameters); } + internal static DilithiumParameters DilithiumParamsLookup(DerObjectIdentifier oid) { - return dilithiumParams[oid]; - } + return CollectionUtilities.GetValueOrNull(dilithiumParams, oid); + } + internal static DerObjectIdentifier DilithiumOidLookup(DilithiumParameters parameters) { - return dilithiumOids[parameters]; + return CollectionUtilities.GetValueOrNull(dilithiumOids, parameters); } internal static DerObjectIdentifier SphincsPlusOidLookup(SphincsPlusParameters parameters) @@ -265,44 +301,44 @@ namespace Org.BouncyCastle.Pqc.Crypto.Utilities internal static DerObjectIdentifier PicnicOidLookup(PicnicParameters parameters) { - return picnicOids[parameters]; + return CollectionUtilities.GetValueOrNull(picnicOids, parameters); } internal static PicnicParameters PicnicParamsLookup(DerObjectIdentifier oid) { - return picnicParams[oid]; + return CollectionUtilities.GetValueOrNull(picnicParams, oid); } #pragma warning disable CS0618 // Type or member is obsolete internal static DerObjectIdentifier SikeOidLookup(SikeParameters parameters) { - return sikeOids[parameters]; + return CollectionUtilities.GetValueOrNull(sikeOids, parameters); } internal static SikeParameters SikeParamsLookup(DerObjectIdentifier oid) { - return sikeParams[oid]; + return CollectionUtilities.GetValueOrNull(sikeParams, oid); } #pragma warning restore CS0618 // Type or member is obsolete internal static DerObjectIdentifier BikeOidLookup(BikeParameters parameters) { - return bikeOids[parameters]; + return CollectionUtilities.GetValueOrNull(bikeOids, parameters); } internal static BikeParameters BikeParamsLookup(DerObjectIdentifier oid) { - return bikeParams[oid]; + return CollectionUtilities.GetValueOrNull(bikeParams, oid); } internal static DerObjectIdentifier HqcOidLookup(HqcParameters parameters) { - return hqcOids[parameters]; + return CollectionUtilities.GetValueOrNull(hqcOids, parameters); } internal static HqcParameters HqcParamsLookup(DerObjectIdentifier oid) { - return hqcParams[oid]; + return CollectionUtilities.GetValueOrNull(hqcParams, oid); } } } diff --git a/crypto/test/src/pqc/crypto/test/FrodoVectorTest.cs b/crypto/test/src/pqc/crypto/test/FrodoVectorTest.cs index a8133e524..a67424887 100644 --- a/crypto/test/src/pqc/crypto/test/FrodoVectorTest.cs +++ b/crypto/test/src/pqc/crypto/test/FrodoVectorTest.cs @@ -1,4 +1,3 @@ -using System; using System.Collections.Generic; using System.IO; @@ -6,6 +5,7 @@ using NUnit.Framework; using Org.BouncyCastle.Crypto; using Org.BouncyCastle.Pqc.Crypto.Frodo; +using Org.BouncyCastle.Pqc.Crypto.Utilities; using Org.BouncyCastle.Utilities; using Org.BouncyCastle.Utilities.Encoders; using Org.BouncyCastle.Utilities.Test; @@ -17,12 +17,12 @@ namespace Org.BouncyCastle.Pqc.Crypto.Tests { private static readonly Dictionary<string, FrodoParameters> Parameters = new Dictionary<string, FrodoParameters>() { - { "PQCkemKAT_19888.rsp", FrodoParameters.frodokem19888r3 }, - { "PQCkemKAT_31296.rsp", FrodoParameters.frodokem31296r3 }, - { "PQCkemKAT_43088.rsp", FrodoParameters.frodokem43088r3 }, - { "PQCkemKAT_19888_shake.rsp", FrodoParameters.frodokem19888shaker3 }, - { "PQCkemKAT_31296_shake.rsp", FrodoParameters.frodokem31296shaker3 }, - { "PQCkemKAT_43088_shake.rsp", FrodoParameters.frodokem43088shaker3 }, + { "PQCkemKAT_19888.rsp", FrodoParameters.frodokem640aes }, + { "PQCkemKAT_31296.rsp", FrodoParameters.frodokem976aes }, + { "PQCkemKAT_43088.rsp", FrodoParameters.frodokem1344aes }, + { "PQCkemKAT_19888_shake.rsp", FrodoParameters.frodokem640shake }, + { "PQCkemKAT_31296_shake.rsp", FrodoParameters.frodokem976shake }, + { "PQCkemKAT_43088_shake.rsp", FrodoParameters.frodokem1344shake }, }; private static readonly string[] TestVectorFilesAes = @@ -42,12 +42,12 @@ namespace Org.BouncyCastle.Pqc.Crypto.Tests [Test] public void TestParameters() { - Assert.AreEqual(128, FrodoParameters.frodokem19888r3.DefaultKeySize); - Assert.AreEqual(128, FrodoParameters.frodokem19888shaker3.DefaultKeySize); - Assert.AreEqual(192, FrodoParameters.frodokem31296r3.DefaultKeySize); - Assert.AreEqual(192, FrodoParameters.frodokem31296shaker3.DefaultKeySize); - Assert.AreEqual(256, FrodoParameters.frodokem43088r3.DefaultKeySize); - Assert.AreEqual(256, FrodoParameters.frodokem43088shaker3.DefaultKeySize); + Assert.AreEqual(128, FrodoParameters.frodokem640aes.DefaultKeySize); + Assert.AreEqual(128, FrodoParameters.frodokem640shake.DefaultKeySize); + Assert.AreEqual(192, FrodoParameters.frodokem976aes.DefaultKeySize); + Assert.AreEqual(192, FrodoParameters.frodokem976shake.DefaultKeySize); + Assert.AreEqual(256, FrodoParameters.frodokem1344aes.DefaultKeySize); + Assert.AreEqual(256, FrodoParameters.frodokem1344shake.DefaultKeySize); } [TestCaseSource(nameof(TestVectorFilesAes))] @@ -84,8 +84,10 @@ namespace Org.BouncyCastle.Pqc.Crypto.Tests kpGen.Init(genParams); AsymmetricCipherKeyPair kp = kpGen.GenerateKeyPair(); - FrodoPublicKeyParameters pubParams = (FrodoPublicKeyParameters)kp.Public; - FrodoPrivateKeyParameters privParams = (FrodoPrivateKeyParameters)kp.Private; + FrodoPublicKeyParameters pubParams = (FrodoPublicKeyParameters)PqcPublicKeyFactory.CreateKey( + PqcSubjectPublicKeyInfoFactory.CreateSubjectPublicKeyInfo((FrodoPublicKeyParameters)kp.Public)); + FrodoPrivateKeyParameters privParams = (FrodoPrivateKeyParameters)PqcPrivateKeyFactory.CreateKey( + PqcPrivateKeyInfoFactory.CreatePrivateKeyInfo((FrodoPrivateKeyParameters)kp.Private)); Assert.True(Arrays.AreEqual(pk, pubParams.GetPublicKey()), $"{name} {count} : public key"); Assert.True(Arrays.AreEqual(sk, privParams.GetPrivateKey()), $"{name} {count} : secret key"); |