diff options
author | Peter Dettman <peter.dettman@bouncycastle.org> | 2023-05-01 17:50:05 +0700 |
---|---|---|
committer | Peter Dettman <peter.dettman@bouncycastle.org> | 2023-05-01 17:50:05 +0700 |
commit | d5116b38e5b8a0425d31e5fe711866515bc91af6 (patch) | |
tree | 19d43d38824512db369b739dcab78f71304c221a /crypto/src/pqc | |
parent | PQC test cleanup (diff) | |
download | BouncyCastle.NET-ed25519-d5116b38e5b8a0425d31e5fe711866515bc91af6.tar.xz |
Update Pqc.Crypto.Crystals from bc-java
- add PqcOtherInfoGenerator and supporting code
Diffstat (limited to 'crypto/src/pqc')
14 files changed, 441 insertions, 134 deletions
diff --git a/crypto/src/pqc/asn1/CmcePrivateKey.cs b/crypto/src/pqc/asn1/CmcePrivateKey.cs index 042325d1d..44b52ca56 100644 --- a/crypto/src/pqc/asn1/CmcePrivateKey.cs +++ b/crypto/src/pqc/asn1/CmcePrivateKey.cs @@ -42,11 +42,10 @@ namespace Org.BouncyCastle.Pqc.Asn1 public CmcePrivateKey(int version, byte[] delta, byte[] c, byte[] g, byte[] alpha, byte[] s, CmcePublicKey pubKey = null) { - this.version = version; if (version != 0) - { - throw new Exception("unrecognized version"); - } + throw new Exception("unrecognized version"); + + this.version = version; this.delta = Arrays.Clone(delta); this.c = Arrays.Clone(c); this.g = Arrays.Clone(g); @@ -57,11 +56,10 @@ namespace Org.BouncyCastle.Pqc.Asn1 private CmcePrivateKey(Asn1Sequence seq) { - version = DerInteger.GetInstance(seq[0]).Value.IntValue; + version = DerInteger.GetInstance(seq[0]).IntValueExact; if (version != 0) - { throw new Exception("unrecognized version"); - } + delta = Arrays.Clone(Asn1OctetString.GetInstance(seq[1]).GetOctets()); c = Arrays.Clone(Asn1OctetString.GetInstance(seq[2]).GetOctets()); @@ -72,8 +70,7 @@ namespace Org.BouncyCastle.Pqc.Asn1 s = Arrays.Clone(Asn1OctetString.GetInstance(seq[5]).GetOctets()); - // todo optional publickey - if(seq.Count == 7) + if (seq.Count == 7) { publicKey = CmcePublicKey.GetInstance(seq[6]); } diff --git a/crypto/src/pqc/asn1/KyberPrivateKey.cs b/crypto/src/pqc/asn1/KyberPrivateKey.cs new file mode 100644 index 000000000..ee71e4f97 --- /dev/null +++ b/crypto/src/pqc/asn1/KyberPrivateKey.cs @@ -0,0 +1,115 @@ +using System; + +using Org.BouncyCastle.Asn1; +using Org.BouncyCastle.Utilities; + +namespace Org.BouncyCastle.Pqc.Asn1 +{ + /** + * Crystal Kyber Private Key Format. + * See https://www.ietf.org/archive/id/draft-uni-qsckeys-kyber-00.html for details. + * <pre> + * KyberPrivateKey ::= SEQUENCE { + * version INTEGER {v0(0)} -- version (round 3) + * s OCTET STRING, -- EMPTY + * hpk OCTET STRING -- EMPTY + * nonce OCTET STRING, -- d + * publicKey [0] IMPLICIT KyberPublicKey OPTIONAL, + * -- see next section + * } + * </pre> + */ + public sealed class KyberPrivateKey + : Asn1Encodable + { + public static KyberPrivateKey GetInstance(object obj) + { + if (obj == null) + return null; + if (obj is KyberPrivateKey kyberPublicKey) + return kyberPublicKey; + return new KyberPrivateKey(Asn1Sequence.GetInstance(obj)); + } + + public static KyberPrivateKey GetInstance(Asn1TaggedObject taggedObject, bool declaredExplicit) + { + return GetInstance(Asn1Sequence.GetInstance(taggedObject, declaredExplicit)); + } + + private int version; + private byte[] s; +#pragma warning disable CS0618 // Type or member is obsolete + private KyberPublicKey publicKey; +#pragma warning restore CS0618 // Type or member is obsolete + private byte[] hpk; + private byte[] nonce; + +#pragma warning disable CS0618 // Type or member is obsolete + public KyberPrivateKey(int version, byte[] s, byte[] hpk, byte[] nonce, KyberPublicKey publicKey) + { + this.version = version; + this.s = s; + this.publicKey = publicKey; + this.hpk = hpk; + this.nonce = nonce; + } +#pragma warning restore CS0618 // Type or member is obsolete + + public KyberPrivateKey(int version, byte[] s, byte[] hpk, byte[] nonce) + : this(version, s, hpk, nonce, null) + { + } + + private KyberPrivateKey(Asn1Sequence seq) + { + version = DerInteger.GetInstance(seq[0]).IntValueExact; + if (version != 0) + throw new ArgumentException("unrecognized version"); + + s = Arrays.Clone(Asn1OctetString.GetInstance(seq[1]).GetOctets()); + + int skipPubKey = 1; + if (seq.Count == 5) + { + skipPubKey = 0; +#pragma warning disable CS0618 // Type or member is obsolete + publicKey = KyberPublicKey.GetInstance(seq[2]); +#pragma warning restore CS0618 // Type or member is obsolete + } + + hpk = Arrays.Clone(Asn1OctetString.GetInstance(seq[3 - skipPubKey]).GetOctets()); + + nonce = Arrays.Clone(Asn1OctetString.GetInstance(seq[4 - skipPubKey]).GetOctets()); + } + + public int Version => version; + + public byte[] GetS() => Arrays.Clone(s); + +#pragma warning disable CS0618 // Type or member is obsolete + public KyberPublicKey PublicKey => publicKey; +#pragma warning restore CS0618 // Type or member is obsolete + + public byte[] GetHpk() => Arrays.Clone(hpk); + + public byte[] GetNonce() => Arrays.Clone(nonce); + + public override Asn1Object ToAsn1Object() + { + Asn1EncodableVector v = new Asn1EncodableVector(5); + + v.Add(new DerInteger(version)); + v.Add(new DerOctetString(s)); + if (publicKey != null) + { +#pragma warning disable CS0618 // Type or member is obsolete + v.Add(new KyberPublicKey(publicKey.T, publicKey.Rho)); +#pragma warning restore CS0618 // Type or member is obsolete + } + v.Add(new DerOctetString(hpk)); + v.Add(new DerOctetString(nonce)); + + return new DerSequence(v); + } + } +} diff --git a/crypto/src/pqc/crypto/IKemParameters.cs b/crypto/src/pqc/crypto/IKemParameters.cs new file mode 100644 index 000000000..9852946ba --- /dev/null +++ b/crypto/src/pqc/crypto/IKemParameters.cs @@ -0,0 +1,9 @@ +using Org.BouncyCastle.Crypto; + +namespace Org.BouncyCastle.Pqc.Crypto +{ + public interface IKemParameters + : ICipherParameters + { + } +} diff --git a/crypto/src/pqc/crypto/crystals/dilithium/DilithiumPrivateKeyParameters.cs b/crypto/src/pqc/crypto/crystals/dilithium/DilithiumPrivateKeyParameters.cs index b5f3c2a32..66a518c93 100644 --- a/crypto/src/pqc/crypto/crystals/dilithium/DilithiumPrivateKeyParameters.cs +++ b/crypto/src/pqc/crypto/crystals/dilithium/DilithiumPrivateKeyParameters.cs @@ -5,45 +5,47 @@ namespace Org.BouncyCastle.Pqc.Crypto.Crystals.Dilithium public sealed class DilithiumPrivateKeyParameters : DilithiumKeyParameters { - internal byte[] rho; - internal byte[] k; - internal byte[] tr; - internal byte[] s1; - internal byte[] s2; - internal byte[] t0; - - private byte[] t1; - - public DilithiumPrivateKeyParameters(DilithiumParameters parameters, byte[] rho, byte[] K, byte[] tr, byte[] s1, byte[] s2, byte[] t0, byte[] t1) + internal byte[] m_rho; + internal byte[] m_k; + internal byte[] m_tr; + internal byte[] m_s1; + internal byte[] m_s2; + internal byte[] m_t0; + + private byte[] m_t1; + + public DilithiumPrivateKeyParameters(DilithiumParameters parameters, byte[] rho, byte[] K, byte[] tr, + byte[] s1, byte[] s2, byte[] t0, byte[] t1) : base(true, parameters) { - this.rho = Arrays.Clone(rho); - this.k = Arrays.Clone(K); - this.tr = Arrays.Clone(tr); - this.s1 = Arrays.Clone(s1); - this.s2 = Arrays.Clone(s2); - this.t0 = Arrays.Clone(t0); - this.t1 = Arrays.Clone(t1); + m_rho = Arrays.Clone(rho); + m_k = Arrays.Clone(K); + m_tr = Arrays.Clone(tr); + m_s1 = Arrays.Clone(s1); + m_s2 = Arrays.Clone(s2); + m_t0 = Arrays.Clone(t0); + m_t1 = Arrays.Clone(t1); } - - public byte[] Rho => Arrays.Clone(rho); - public byte[] K => Arrays.Clone(k); + public byte[] GetEncoded() => Arrays.ConcatenateAll(m_rho, m_k, m_tr, m_s1, m_s2, m_t0); - public byte[] Tr => Arrays.Clone(tr); + public byte[] K => Arrays.Clone(m_k); - public byte[] S1 => Arrays.Clone(s1); + public byte[] GetPublicKey() => DilithiumPublicKeyParameters.GetEncoded(m_rho, m_t1); - public byte[] S2 => Arrays.Clone(s2); - + public DilithiumPublicKeyParameters GetPublicKeyParameters() => + new DilithiumPublicKeyParameters(Parameters, m_rho, m_t1); - public byte[] T0 => Arrays.Clone(t0); + public byte[] Rho => Arrays.Clone(m_rho); - public byte[] T1 => t1; + public byte[] S1 => Arrays.Clone(m_s1); - public byte[] GetEncoded() - { - return Arrays.ConcatenateAll(rho, k, tr, s1, s2, t0); - } + public byte[] S2 => Arrays.Clone(m_s2); + + public byte[] T0 => Arrays.Clone(m_t0); + + public byte[] T1 => Arrays.Clone(m_t1); + + public byte[] Tr => Arrays.Clone(m_tr); } -} \ No newline at end of file +} diff --git a/crypto/src/pqc/crypto/crystals/dilithium/DilithiumPublicKeyParameters.cs b/crypto/src/pqc/crypto/crystals/dilithium/DilithiumPublicKeyParameters.cs index 681435439..d47c4804e 100644 --- a/crypto/src/pqc/crypto/crystals/dilithium/DilithiumPublicKeyParameters.cs +++ b/crypto/src/pqc/crypto/crystals/dilithium/DilithiumPublicKeyParameters.cs @@ -5,31 +5,29 @@ namespace Org.BouncyCastle.Pqc.Crypto.Crystals.Dilithium public sealed class DilithiumPublicKeyParameters : DilithiumKeyParameters { - internal byte[] rho; - internal byte[] t1; + internal static byte[] GetEncoded(byte[] rho, byte[] t1) => Arrays.Concatenate(rho, t1); - public DilithiumPublicKeyParameters(DilithiumParameters parameters, byte[] pkEncoded) - : base(false, parameters) - { - this.rho = Arrays.CopyOfRange(pkEncoded, 0, DilithiumEngine.SeedBytes); - this.t1 = Arrays.CopyOfRange(pkEncoded, DilithiumEngine.SeedBytes, pkEncoded.Length); - } + internal readonly byte[] m_rho; + internal readonly byte[] m_t1; public DilithiumPublicKeyParameters(DilithiumParameters parameters, byte[] rho, byte[] t1) : base(false, parameters) { - this.rho = Arrays.Clone(rho); - this.t1 = Arrays.Clone(t1); + m_rho = Arrays.Clone(rho); + m_t1 = Arrays.Clone(t1); } - public byte[] GetEncoded() + public DilithiumPublicKeyParameters(DilithiumParameters parameters, byte[] pkEncoded) + : base(false, parameters) { - return Arrays.Concatenate(rho, t1); + m_rho = Arrays.CopyOfRange(pkEncoded, 0, DilithiumEngine.SeedBytes); + m_t1 = Arrays.CopyOfRange(pkEncoded, DilithiumEngine.SeedBytes, pkEncoded.Length); } - internal byte[] Rho => rho; + public byte[] GetEncoded() => GetEncoded(m_rho, m_t1); - internal byte[] T1 => t1; + public byte[] GetRho() => Arrays.Clone(m_rho); + public byte[] GetT1() => Arrays.Clone(m_t1); } } diff --git a/crypto/src/pqc/crypto/crystals/dilithium/DilithiumSigner.cs b/crypto/src/pqc/crypto/crystals/dilithium/DilithiumSigner.cs index d60c24222..7611f3032 100644 --- a/crypto/src/pqc/crypto/crystals/dilithium/DilithiumSigner.cs +++ b/crypto/src/pqc/crypto/crystals/dilithium/DilithiumSigner.cs @@ -42,14 +42,15 @@ namespace Org.BouncyCastle.Pqc.Crypto.Crystals.Dilithium { DilithiumEngine engine = privKey.Parameters.GetEngine(random); byte[] sig = new byte[engine.CryptoBytes]; - engine.Sign(sig, sig.Length, message, message.Length, privKey.rho, privKey.k, privKey.tr, privKey.t0, privKey.s1, privKey.s2); + engine.Sign(sig, sig.Length, message, message.Length, privKey.m_rho, privKey.m_k, privKey.m_tr, + privKey.m_t0, privKey.m_s1, privKey.m_s2); return sig; } public bool VerifySignature(byte[] message, byte[] signature) { DilithiumEngine engine = pubKey.Parameters.GetEngine(random); - return engine.SignOpen(message,signature, signature.Length, pubKey.rho, pubKey.t1 ); + return engine.SignOpen(message,signature, signature.Length, pubKey.m_rho, pubKey.m_t1); } } -} \ No newline at end of file +} diff --git a/crypto/src/pqc/crypto/crystals/kyber/KyberParameters.cs b/crypto/src/pqc/crypto/crystals/kyber/KyberParameters.cs index 5b3f71000..195831433 100644 --- a/crypto/src/pqc/crypto/crystals/kyber/KyberParameters.cs +++ b/crypto/src/pqc/crypto/crystals/kyber/KyberParameters.cs @@ -3,7 +3,7 @@ using Org.BouncyCastle.Crypto; namespace Org.BouncyCastle.Pqc.Crypto.Crystals.Kyber { public sealed class KyberParameters - : ICipherParameters + : IKemParameters { public static KyberParameters kyber512 = new KyberParameters("kyber512", 2, 128, false); public static KyberParameters kyber768 = new KyberParameters("kyber768", 3, 192, false); diff --git a/crypto/src/pqc/crypto/crystals/kyber/KyberPrivateKeyParameters.cs b/crypto/src/pqc/crypto/crystals/kyber/KyberPrivateKeyParameters.cs index 0fac30e47..08b4fbe86 100644 --- a/crypto/src/pqc/crypto/crystals/kyber/KyberPrivateKeyParameters.cs +++ b/crypto/src/pqc/crypto/crystals/kyber/KyberPrivateKeyParameters.cs @@ -11,7 +11,8 @@ namespace Org.BouncyCastle.Pqc.Crypto.Crystals.Kyber private readonly byte[] m_t; private readonly byte[] m_rho; - public KyberPrivateKeyParameters(KyberParameters parameters, byte[] s, byte[] hpk, byte[] nonce, byte[] t, byte[] rho) + public KyberPrivateKeyParameters(KyberParameters parameters, byte[] s, byte[] hpk, byte[] nonce, byte[] t, + byte[] rho) : base(true, parameters) { m_s = Arrays.Clone(s); @@ -21,16 +22,21 @@ namespace Org.BouncyCastle.Pqc.Crypto.Crystals.Kyber m_rho = Arrays.Clone(rho); } - public byte[] GetEncoded() - { - return Arrays.ConcatenateAll(m_s, m_t, m_rho, m_hpk, m_nonce); - } + public byte[] GetEncoded() => Arrays.ConcatenateAll(m_s, m_t, m_rho, m_hpk, m_nonce); + + public byte[] GetHpk() => Arrays.Clone(m_hpk); + + public byte[] GetNonce() => Arrays.Clone(m_nonce); + + public byte[] GetPublicKey() => KyberPublicKeyParameters.GetEncoded(m_t, m_rho); + + public KyberPublicKeyParameters GetPublicKeyParameters() => + new KyberPublicKeyParameters(Parameters, m_t, m_rho); + + public byte[] GetRho() => Arrays.Clone(m_rho); - internal byte[] S => m_s; - internal byte[] Hpk => m_hpk; - internal byte[] Nonce => m_nonce; - internal byte[] T => m_t; - internal byte[] Rho => m_rho; + public byte[] GetS() => Arrays.Clone(m_s); + public byte[] GetT() => Arrays.Clone(m_t); } -} \ No newline at end of file +} diff --git a/crypto/src/pqc/crypto/crystals/kyber/KyberPublicKeyParameters.cs b/crypto/src/pqc/crypto/crystals/kyber/KyberPublicKeyParameters.cs index efc582abc..dadfe8498 100644 --- a/crypto/src/pqc/crypto/crystals/kyber/KyberPublicKeyParameters.cs +++ b/crypto/src/pqc/crypto/crystals/kyber/KyberPublicKeyParameters.cs @@ -5,12 +5,16 @@ namespace Org.BouncyCastle.Pqc.Crypto.Crystals.Kyber public sealed class KyberPublicKeyParameters : KyberKeyParameters { + internal static byte[] GetEncoded(byte[] t, byte[] rho) => Arrays.Concatenate(t, rho); + private readonly byte[] m_t; private readonly byte[] m_rho; - public byte[] GetEncoded() + public KyberPublicKeyParameters(KyberParameters parameters, byte[] t, byte[] rho) + : base(false, parameters) { - return Arrays.Concatenate(m_t, m_rho); + m_t = Arrays.Clone(t); + m_rho = Arrays.Clone(rho); } public KyberPublicKeyParameters(KyberParameters parameters, byte[] encoding) @@ -20,15 +24,11 @@ namespace Org.BouncyCastle.Pqc.Crypto.Crystals.Kyber m_rho = Arrays.CopyOfRange(encoding, encoding.Length - KyberEngine.SymBytes, encoding.Length); } - public KyberPublicKeyParameters(KyberParameters parameters, byte[] t, byte[] rho) - : base(false, parameters) - { - m_t = Arrays.Clone(t); - m_rho = Arrays.Clone(rho); - } + public byte[] GetEncoded() => GetEncoded(m_t, m_rho); + + public byte[] GetRho() => Arrays.Clone(m_rho); - internal byte[] T => m_t; - internal byte[] Rho => m_rho; + public byte[] GetT() => Arrays.Clone(m_t); } } \ No newline at end of file diff --git a/crypto/src/pqc/crypto/ntru/NtruParameters.cs b/crypto/src/pqc/crypto/ntru/NtruParameters.cs index 934cc21cb..0c5158f5f 100644 --- a/crypto/src/pqc/crypto/ntru/NtruParameters.cs +++ b/crypto/src/pqc/crypto/ntru/NtruParameters.cs @@ -4,7 +4,7 @@ using Org.BouncyCastle.Pqc.Crypto.Ntru.ParameterSets; namespace Org.BouncyCastle.Pqc.Crypto.Ntru { public sealed class NtruParameters - : ICipherParameters + : IKemParameters { public static readonly NtruParameters NtruHps2048509 = new NtruParameters("ntruhps2048509", new NtruHps2048509()); diff --git a/crypto/src/pqc/crypto/utils/PqcOtherInfoGenerator.cs b/crypto/src/pqc/crypto/utils/PqcOtherInfoGenerator.cs new file mode 100644 index 000000000..0d3af4a51 --- /dev/null +++ b/crypto/src/pqc/crypto/utils/PqcOtherInfoGenerator.cs @@ -0,0 +1,203 @@ +using System; +using System.IO; + +using Org.BouncyCastle.Asn1.X509; +using Org.BouncyCastle.Crypto; +using Org.BouncyCastle.Crypto.Utilities; +using Org.BouncyCastle.Pqc.Crypto.Crystals.Kyber; +using Org.BouncyCastle.Pqc.Crypto.Ntru; +using Org.BouncyCastle.Security; + +namespace Org.BouncyCastle.Pqc.Crypto.Utilities +{ + /** + * OtherInfo Generator for which can be used for populating the SuppPrivInfo field used to provide shared + * secret data used with NIST SP 800-56A agreement algorithms. + */ + public abstract class PqcOtherInfoGenerator + { + protected readonly DerOtherInfo.Builder m_otherInfoBuilder; + protected readonly SecureRandom m_random; + + protected bool m_used = false; + + /** + * Create a basic builder with just the compulsory fields. + * + * @param algorithmID the algorithm associated with this invocation of the KDF. + * @param partyUInfo sender party info. + * @param partyVInfo receiver party info. + * @param random a source of randomness. + */ + internal PqcOtherInfoGenerator(AlgorithmIdentifier algorithmID, byte[] partyUInfo, byte[] partyVInfo, + SecureRandom random) + { + m_otherInfoBuilder = new DerOtherInfo.Builder(algorithmID, partyUInfo, partyVInfo); + m_random = random; + } + + /** + * Party U (initiator) generation. + */ + public sealed class PartyU + : PqcOtherInfoGenerator + { + private AsymmetricCipherKeyPair m_aKp; + private IEncapsulatedSecretExtractor m_encSE; + + /** + * Create a basic builder with just the compulsory fields for the initiator. + * + * @param kemParams the key type parameters for populating the private info field. + * @param algorithmID the algorithm associated with this invocation of the KDF. + * @param partyUInfo sender party info. + * @param partyVInfo receiver party info. + * @param random a source of randomness. + */ + public PartyU(IKemParameters kemParams, AlgorithmIdentifier algorithmID, byte[] partyUInfo, + byte[] partyVInfo, SecureRandom random) + : base(algorithmID, partyUInfo, partyVInfo, random) + { + if (kemParams is KyberParameters kyberParameters) + { + KyberKeyPairGenerator kpg = new KyberKeyPairGenerator(); + kpg.Init(new KyberKeyGenerationParameters(random, kyberParameters)); + + m_aKp = kpg.GenerateKeyPair(); + + m_encSE = new KyberKemExtractor((KyberPrivateKeyParameters)m_aKp.Private); + } + else if (kemParams is NtruParameters ntruParameters) + { + NtruKeyPairGenerator kpg = new NtruKeyPairGenerator(); + kpg.Init(new NtruKeyGenerationParameters(random, ntruParameters)); + + m_aKp = kpg.GenerateKeyPair(); + + m_encSE = new NtruKemExtractor((NtruPrivateKeyParameters)m_aKp.Private); + } + else + { + throw new ArgumentException("unknown IKemParameters"); + } + } + + /** + * Add optional supplementary public info (DER tagged, implicit, 0). + * + * @param suppPubInfo supplementary public info. + * @return the current builder instance. + */ + public PqcOtherInfoGenerator WithSuppPubInfo(byte[] suppPubInfo) + { + m_otherInfoBuilder.WithSuppPubInfo(suppPubInfo); + return this; + } + + public byte[] GetSuppPrivInfoPartA() + { + return GetEncoded(m_aKp.Public); + } + + public DerOtherInfo Generate(byte[] suppPrivInfoPartB) + { + m_otherInfoBuilder.WithSuppPrivInfo(m_encSE.ExtractSecret(suppPrivInfoPartB)); + + return m_otherInfoBuilder.Build(); + } + } + + /** + * Party V (responder) generation. + */ + public sealed class PartyV + : PqcOtherInfoGenerator + { + private IEncapsulatedSecretGenerator m_encSG; + + /** + * Create a basic builder with just the compulsory fields for the responder. + * + * @param kemParams the key type parameters for populating the private info field. + * @param algorithmID the algorithm associated with this invocation of the KDF. + * @param partyUInfo sender party info. + * @param partyVInfo receiver party info. + * @param random a source of randomness. + */ + public PartyV(IKemParameters kemParams, AlgorithmIdentifier algorithmID, byte[] partyUInfo, + byte[] partyVInfo, SecureRandom random) + : base(algorithmID, partyUInfo, partyVInfo, random) + { + if (kemParams is KyberParameters) + { + m_encSG = new KyberKemGenerator(random); + } + else if (kemParams is NtruParameters) + { + m_encSG = new NtruKemGenerator(random); + } + else + { + throw new ArgumentException("unknown IKemParameters"); + } + } + + /** + * Add optional supplementary public info (DER tagged, implicit, 0). + * + * @param suppPubInfo supplementary public info. + * @return the current builder instance. + */ + public PqcOtherInfoGenerator WithSuppPubInfo(byte[] suppPubInfo) + { + m_otherInfoBuilder.WithSuppPubInfo(suppPubInfo); + return this; + } + + public byte[] GetSuppPrivInfoPartB(byte[] suppPrivInfoPartA) + { + m_used = false; + + try + { + ISecretWithEncapsulation bEp = m_encSG.GenerateEncapsulated(GetPublicKey(suppPrivInfoPartA)); + + m_otherInfoBuilder.WithSuppPrivInfo(bEp.GetSecret()); + + return bEp.GetEncapsulation(); + } + catch (IOException e) + { + throw new ArgumentException("cannot decode public key", e); + } + } + + public DerOtherInfo Generate() + { + if (m_used) + throw new InvalidOperationException("builder already used"); + + m_used = true; + + return m_otherInfoBuilder.Build(); + } + } + + private static byte[] GetEncoded(AsymmetricKeyParameter pubKey) + { + try + { + return PqcSubjectPublicKeyInfoFactory.CreateSubjectPublicKeyInfo(pubKey).GetEncoded(); + } + catch (IOException) + { + return null; + } + } + + private static AsymmetricKeyParameter GetPublicKey(byte[] enc) + { + return PqcPublicKeyFactory.CreateKey(enc); + } + } +} diff --git a/crypto/src/pqc/crypto/utils/PqcPrivateKeyFactory.cs b/crypto/src/pqc/crypto/utils/PqcPrivateKeyFactory.cs index 01566c8b0..1deb2c8d6 100644 --- a/crypto/src/pqc/crypto/utils/PqcPrivateKeyFactory.cs +++ b/crypto/src/pqc/crypto/utils/PqcPrivateKeyFactory.cs @@ -134,55 +134,35 @@ namespace Org.BouncyCastle.Pqc.Crypto.Utilities return new HqcPrivateKeyParameters(hqcParams, keyEnc); } - if (algOID.Equals(BCObjectIdentifiers.kyber512) - || algOID.Equals(BCObjectIdentifiers.kyber512_aes) - || algOID.Equals(BCObjectIdentifiers.kyber768) - || algOID.Equals(BCObjectIdentifiers.kyber768_aes) - || algOID.Equals(BCObjectIdentifiers.kyber1024) - || algOID.Equals(BCObjectIdentifiers.kyber1024_aes)) + if (algOID.On(BCObjectIdentifiers.pqc_kem_kyber)) { - Asn1Sequence keyEnc = Asn1Sequence.GetInstance(keyInfo.ParsePrivateKey()); - - KyberParameters spParams = PqcUtilities.KyberParamsLookup(keyInfo.PrivateKeyAlgorithm.Algorithm); + KyberPrivateKey kyberKey = KyberPrivateKey.GetInstance(keyInfo.ParsePrivateKey()); + KyberParameters kyberParams = PqcUtilities.KyberParamsLookup(keyInfo.PrivateKeyAlgorithm.Algorithm); - int version = DerInteger.GetInstance(keyEnc[0]).Value.IntValue; - if (version != 0) - { - throw new IOException("unknown private key version: " + version); - } - - if (keyInfo.PublicKeyData != null) - { - Asn1Sequence pubKey = Asn1Sequence.GetInstance(keyInfo.PublicKeyData.GetOctets()); - return new KyberPrivateKeyParameters(spParams, - Asn1OctetString.GetInstance(keyEnc[1]).GetDerEncoded(), - Asn1OctetString.GetInstance(keyEnc[2]).GetOctets(), - Asn1OctetString.GetInstance(keyEnc[3]).GetOctets(), - Asn1OctetString.GetInstance(pubKey[0]).GetOctets(), // t - Asn1OctetString.GetInstance(pubKey[1]).GetOctets()); // rho - } - else +#pragma warning disable CS0618 // Type or member is obsolete + KyberPublicKey pubKey = kyberKey.PublicKey; +#pragma warning restore CS0618 // Type or member is obsolete + if (pubKey != null) { - return new KyberPrivateKeyParameters(spParams, - Asn1OctetString.GetInstance(keyEnc[1]).GetOctets(), - Asn1OctetString.GetInstance(keyEnc[2]).GetOctets(), - Asn1OctetString.GetInstance(keyEnc[3]).GetOctets(), - null, - null); + return new KyberPrivateKeyParameters(kyberParams, kyberKey.GetS(), kyberKey.GetHpk(), + kyberKey.GetNonce(), pubKey.T, pubKey.Rho); } + return new KyberPrivateKeyParameters(kyberParams, kyberKey.GetS(), kyberKey.GetHpk(), + kyberKey.GetNonce(), null, null); } - if (algOID.Equals(BCObjectIdentifiers.dilithium2) - || algOID.Equals(BCObjectIdentifiers.dilithium3) - || algOID.Equals(BCObjectIdentifiers.dilithium5) - || algOID.Equals(BCObjectIdentifiers.dilithium2_aes) - || algOID.Equals(BCObjectIdentifiers.dilithium3_aes) - || algOID.Equals(BCObjectIdentifiers.dilithium5_aes)) + if (algOID.Equals(BCObjectIdentifiers.dilithium2) || + algOID.Equals(BCObjectIdentifiers.dilithium3) || + algOID.Equals(BCObjectIdentifiers.dilithium5) || + algOID.Equals(BCObjectIdentifiers.dilithium2_aes) || + algOID.Equals(BCObjectIdentifiers.dilithium3_aes) || + algOID.Equals(BCObjectIdentifiers.dilithium5_aes)) { Asn1Sequence keyEnc = Asn1Sequence.GetInstance(keyInfo.ParsePrivateKey()); - DilithiumParameters spParams = PqcUtilities.DilithiumParamsLookup(keyInfo.PrivateKeyAlgorithm.Algorithm); + DilithiumParameters spParams = PqcUtilities.DilithiumParamsLookup( + keyInfo.PrivateKeyAlgorithm.Algorithm); - int version = DerInteger.GetInstance(keyEnc[0]).Value.IntValue; + int version = DerInteger.GetInstance(keyEnc[0]).IntValueExact; if (version != 0) throw new IOException("unknown private key version: " + version); @@ -216,7 +196,7 @@ namespace Org.BouncyCastle.Pqc.Crypto.Utilities FalconParameters spParams = PqcUtilities.FalconParamsLookup(keyInfo.PrivateKeyAlgorithm.Algorithm); DerBitString publicKeyData = keyInfo.PublicKeyData; - int version = DerInteger.GetInstance(keyEnc[0]).Value.IntValue; + int version = DerInteger.GetInstance(keyEnc[0]).IntValueExact; if (version != 1) throw new IOException("unknown private key version: " + version); diff --git a/crypto/src/pqc/crypto/utils/PqcPrivateKeyInfoFactory.cs b/crypto/src/pqc/crypto/utils/PqcPrivateKeyInfoFactory.cs index 6f7bed2ca..3e2832713 100644 --- a/crypto/src/pqc/crypto/utils/PqcPrivateKeyInfoFactory.cs +++ b/crypto/src/pqc/crypto/utils/PqcPrivateKeyInfoFactory.cs @@ -129,21 +129,17 @@ namespace Org.BouncyCastle.Pqc.Crypto.Utilities } if (privateKey is KyberPrivateKeyParameters kyberPrivateKeyParameters) { - Asn1EncodableVector v = new Asn1EncodableVector(4); - v.Add(new DerInteger(0)); - v.Add(new DerOctetString(kyberPrivateKeyParameters.S)); - v.Add(new DerOctetString(kyberPrivateKeyParameters.Hpk)); - v.Add(new DerOctetString(kyberPrivateKeyParameters.Nonce)); - AlgorithmIdentifier algorithmIdentifier = new AlgorithmIdentifier( PqcUtilities.KyberOidLookup(kyberPrivateKeyParameters.Parameters)); - Asn1EncodableVector vPub = new Asn1EncodableVector(2); - vPub.Add(new DerOctetString(kyberPrivateKeyParameters.T)); - vPub.Add(new DerOctetString(kyberPrivateKeyParameters.Rho)); +#pragma warning disable CS0618 // Type or member is obsolete + KyberPublicKey kyberPub = new KyberPublicKey(kyberPrivateKeyParameters.GetT(), + kyberPrivateKeyParameters.GetRho()); +#pragma warning restore CS0618 // Type or member is obsolete + KyberPrivateKey kyberPriv = new KyberPrivateKey(0, kyberPrivateKeyParameters.GetS(), + kyberPrivateKeyParameters.GetHpk(), kyberPrivateKeyParameters.GetNonce(), kyberPub); - return new PrivateKeyInfo(algorithmIdentifier, new DerSequence(v), attributes, - new DerSequence(vPub).GetEncoded()); + return new PrivateKeyInfo(algorithmIdentifier, kyberPriv, attributes); } if (privateKey is DilithiumPrivateKeyParameters dilithiumPrivateKeyParameters) { diff --git a/crypto/src/pqc/crypto/utils/PqcSubjectPublicKeyInfoFactory.cs b/crypto/src/pqc/crypto/utils/PqcSubjectPublicKeyInfoFactory.cs index 1bdf031f6..946aca963 100644 --- a/crypto/src/pqc/crypto/utils/PqcSubjectPublicKeyInfoFactory.cs +++ b/crypto/src/pqc/crypto/utils/PqcSubjectPublicKeyInfoFactory.cs @@ -132,8 +132,8 @@ namespace Org.BouncyCastle.Pqc.Crypto.Utilities { AlgorithmIdentifier algorithmIdentifier = new AlgorithmIdentifier( PqcUtilities.DilithiumOidLookup(dilithiumPublicKeyParameters.Parameters)); - - return new SubjectPublicKeyInfo(algorithmIdentifier, Arrays.Concatenate(dilithiumPublicKeyParameters.Rho, dilithiumPublicKeyParameters.T1)); + + return new SubjectPublicKeyInfo(algorithmIdentifier, dilithiumPublicKeyParameters.GetEncoded()); } if (publicKey is BikePublicKeyParameters bikePublicKeyParameters) { |