bcgit / bc-csharp

BouncyCastle.NET Cryptography Library (Mirror)
https://www.bouncycastle.org/csharp
MIT License
1.68k stars 559 forks source link

SPHINCS+ key info encoding fails #521

Closed nd1012 closed 9 months ago

nd1012 commented 9 months ago

Exception:

System.ArgumentNullException: Value cannot be null. (Parameter 'element')

Stack:

Asn1EncodableVector.Add(Asn1Encodable element)
Asn1EncodableVector.ctor(Asn1Encodable element)
AlgorithmIdentifier.ToAsn1Object()
Asn1OutputStream.GetContentsEncodings(Int32 encoding, Asn1Encodable[] elements)
DerSequence.GetEncoding(Int32 encoding)
Asn1Object.InternalGetEncoded(String encoding)
Asn1Encodable.GetEncoded(String encoding)
Asn1Encodable.GetDerEncoded()

Code to reproduce:

// Create a key pair
SphincsPlusKeyPairGenerator keyGen = new();
keyGen.Init(new SphincsPlusKeyGenerationParameters(new(), SphincsPlusParameters.haraka_256f_simple));
AsymmetricCipherKeyPair keys = keyGen.GenerateKeyPair();
SphincsPlusPrivateKeyParameters privateKey = keys.Private as SphincsPlusPrivateKeyParameters ?? throw new InvalidDataException("Invalid private key");
SphincsPlusPublicKeyParameters publicKey = keys.Public as SphincsPlusPublicKeyParameters ?? throw new InvalidDataException("Invalid public key");

// Private key info serialization (FAILS!)
byte[] serialized = PqcPrivateKeyInfoFactory.CreatePrivateKeyInfo(privateKey).GetDerEncoded();
_ = PqcPrivateKeyFactory.CreateKey(serialized) as SphincsPlusPrivateKeyParameters ?? throw new InvalidDataException("Deserialization of private key failed");

// Public key info serialization (FAILS also!)
serialized = PqcSubjectPublicKeyInfoFactory.CreateSubjectPublicKeyInfo(publicKey).GetDerEncoded();
_ = PqcPublicKeyFactory.CreateKey(serialized) as SphincsPlusPublicKeyParameters ?? throw new InvalidDataException("Deserialization of public key failed");

The same exception is being thrown, when I use GetEncoded instead (similar stack).

Am I doing it wrong - is there any other recommended (working) way to un-/serialize the keys?

By the way, the serilization worked with the example code above until the NuGet package was updated to version 2.3.0.

roy-basmacier commented 9 months ago

Hello @nd1012 ,

The error only occurs when using the following parameters SphincsPlusParameters.haraka_128f_simple SphincsPlusParameters.haraka_128s_simple SphincsPlusParameters.haraka_192f_simple SphincsPlusParameters.haraka_192s_simple SphincsPlusParameters.haraka_256f_simple SphincsPlusParameters.haraka_256s_simple

This is because they weren't added to the look-up tables and the converters.

I'll add them in a patch, however, NIST stated in their FIPS 205 draft (line 306-308) that they do not approve of these parameters.

"This standard approves the use of only 12 of the 36 parameter sets defned in [4, 5]. As specifed in Section 10, only the ‘simple’ instances in which the cryptographic functions are instantiated with SHA-2 or SHAKE are approved. "

nd1012 commented 9 months ago

Thanks a lot - that wasn't clear to me! For me it's not so important to stick with with Haraka hash parameters, I'll switch to Shake instead.

Usually I try to find a way to serialize a key in a standard format, so that 3rd party apps should be able to use it, too. When I look at the PQC algorithms, there are some serializations missing (NTRU, for example), so I have to use a custom serialization format at present. I assume that the standards are in heavy development for the moment, and that's the reason why things may be missing/changed in the Bouncy castle library until the standards are finalized - is that correct?