diff --git a/.github/workflows/docfx.yml b/.github/workflows/docfx.yml
index 193d0da..4a849c9 100644
--- a/.github/workflows/docfx.yml
+++ b/.github/workflows/docfx.yml
@@ -18,6 +18,8 @@ jobs:
dotnet-version: 8.0.x
- name: Setup docfx
run: dotnet tool update -g docfx
+ - name: Copy README
+ run: cp README.md "./src/wan24-Crypto-BC Docs/index.md"
- name: Build docs
run: docfx "./src/wan24-Crypto-BC Docs/docfx.json"
- name: Commit
diff --git a/README.md b/README.md
index 5d91cef..4b73b52 100644
--- a/README.md
+++ b/README.md
@@ -12,14 +12,18 @@ the `wan24-Crypto` library with these algorithms:
| CRYSTALS-Dilithium | 3 | CRYSTALSDILITHIUM |
| FALCON | 4 | FALCON |
| SPHINCS+ | 5 | SPHINCSPLUS |
-| FrodoKEM* | 6 | FRODOKEM |
-| NTRUEncrypt* | 7 | NTRUENCRYPT |
+| FrodoKEM | 6 | FRODOKEM |
+| NTRUEncrypt | 7 | NTRUENCRYPT |
| Ed25519 | 8 | ED25519 |
| Ed448 | 9 | ED448 |
| X25519 | 10 | X25519 |
| X448 | 11 | X448 |
| XEd25519 | 12 | XED25519 |
| XEd448 | 13 | XED448 |
+| Streamlined NTRU Prime | 14 | SNTRUP |
+| BIKE | 15 | BIKE |
+| HQC | 16 | HQC |
+| Picnic | 17 | PICNIC |
| **Symmetric** | | |
| ChaCha20 | 1 | CHACHA20 |
| XSalsa20 | 2 | XSALSA20 |
@@ -29,14 +33,10 @@ the `wan24-Crypto` library with these algorithms:
| Twofish 256 CBC (ISO10126 padding) | 7 | TWOFISH256CBC |
| Twofish 256 GCM AEAD (128 bit MAC) | 8 | TWOFISH256GCM |
-NTRUSign is currently not implemented, 'cause it'd require the using code to
-be GPL licensed. This algorithm may be included in a separate package which is
-licensed using the GPL license (to avoid misunderstandings) in the future.
-
-**NOTE**: SPHINCS+ and NTRUEncrypt key serialization uses a custom serializer
-at present, which will change in the future, as soon as Bouncy Castle
-implemented a (working) serializer (again). This change will require a manual
-key conversion from the current serialization format.
+Main goals of this extension library are to make `wan24-Crypto` usable on all
+platforms and extend its algorithms by PQC algorithms and other non-PQC
+algorithms, which are not available from .NET, but implemented in the Bouncy
+Castle library.
## How to get it
@@ -54,21 +54,7 @@ wan24.Crypto.BC.Bootstrap.Boot();
This will register the algorithms to the `wan24-Crypto` library.
-To set Bouncy Castle defaults as `wan24-Crypto` defaults:
-
-```cs
-BouncyCastle.SetDefaults();
-```
-
-Per default the current `wan24-Crypto` default will be set as counter
-algorithms to `HybridAlgorithmHelper`.
-
-Current Bouncy Castle default algorithms are:
-
-- Key exchange: NTRUEncrypt
-- Signature: CRYSTALS-Dilithium
-- Encryption: Serpent 256 bit CBC
-- PAKE encryption: Serpent 256 bit GCM
+### `wan24-Crypto` algorithm replacement
Some algorithms of the `wan24-Crypto` library are not available on some
platforms, that's why they need to be replaced in order to be used:
@@ -95,7 +81,28 @@ BouncyCastle.ReplaceNetAlgorithms();
**NOTE**: The Shake128/256 replacements don't support variable output length
and use the default output length of the `wan24-Crypto` implementations
-instead.
+instead. The `NetShake128/256HashAlgorithmAdapter` can't be replaced for this
+reason.
+
+### Use as default algorithms
+
+To set Bouncy Castle defaults as `wan24-Crypto` defaults:
+
+```cs
+BouncyCastle.SetDefaults();
+```
+
+Per default the current `wan24-Crypto` default will be set as counter
+algorithms to `HybridAlgorithmHelper`.
+
+Current Bouncy Castle default algorithms are:
+
+| Usage | Algorithm |
+| ----- | --------- |
+| Key exchange | NTRUEncrypt |
+| Signature | CRYSTALS-Dilithium |
+| Encryption | Serpent 256 bit CBC |
+| PAKE encryption | Serpent 256 bit GCM |
## Post quantum safety
@@ -107,6 +114,10 @@ These asymmetric algorithms are designed for post quantum cryptography:
- SPHINCS+ (signature)
- FrodoKEM (key exchange)
- NTRUEncrypt (key exchange)
+- Streamlined NTRU Prime (key exchange)
+- BIKE (key exchange)
+- HQC (key exchange)
+- Picnic (signature)
Normally you want to use them in hybrid mode and use classical algorithms of
the `wan24-Crypto` package as counter algorithm. To do this per default:
@@ -148,11 +159,23 @@ SignatureContainer signature = dataToSign.Sign(yourNormalPrivateKey, options: op
## Algorithm parameters used
-For CRYSTALS-Kyber and CRYSTALS-Dilithium the non-AES parameters are being
-used, since the AES parameter sets have been deprecated. When using SPHINCS+,
-the Haraka simple hashing parameters will be used (since the Haraka robust
-hashing parameters have been reprecated). For FrodoKEM the AES parameters will
-be used.
+| Algorithm | Parameters |
+| --------- | ---------- |
+| CRYSTALS-Kyber, CRYSTALS-Dilithium | non-AES |
+| SPHINCS+ | Haraka simple* |
+| FrodoKEM | AES* |
+| Picnic | Full |
+
+**NOTE**: CRYSTALS-Kyber and CRYSTALS-Dilithium AES parameters and SPHINCS+
+robust parameters are deprecated! SPHINCS+ Haraka parameters are removed from
+the FIPS standard, so `wan24-Crypto-BC` will switch to Shake parameters
+instead. Also the FrodoKEM Shake parameters will be used in the next major
+release, which will require to renew existing keys, which use the AES
+parameters from the current version of this library.
+
+**WARNING** The PQC standards are in development at the moment, so future
+incompatible changes are very likely and will be handled in a new major
+release of this library.
## Random data provider
@@ -186,8 +209,10 @@ bytes of an underlaying PRNG using a random key. The result is a CSRNG. These
stream ciphers are available with `wan24-Crypto-BC`, but you could use any
other stream cipher (but not AEAD implementations!) also:
-- ChaCha20 - `ChaCha20Rng`
-- XSalsa20 - `XSalsa20Rng`
+| Stream cipher | RNG |
+| ------------- | --- |
+| ChaCha20 | `ChaCha20Rng` |
+| XSalsa20 | `XSalsa20Rng` |
If you didn't specify an underlaying PRNG, Bouncy Castle's
`VmpcRandomGenerator` will be used and seeded using 256 bytes from `RND`.
diff --git a/src/wan24-Crypto-BC Tests/wan24-Crypto-BC Tests.csproj b/src/wan24-Crypto-BC Tests/wan24-Crypto-BC Tests.csproj
index 946a44a..d1d7dd9 100644
--- a/src/wan24-Crypto-BC Tests/wan24-Crypto-BC Tests.csproj
+++ b/src/wan24-Crypto-BC Tests/wan24-Crypto-BC Tests.csproj
@@ -15,13 +15,13 @@
-
-
+
+
all
runtime; build; native; contentfiles; analyzers; buildtransitive
-
+
diff --git a/src/wan24-Crypto-BC/AsymmetricBcEcDiffieHellmanPrivateKey.cs b/src/wan24-Crypto-BC/AsymmetricBcEcDiffieHellmanPrivateKey.cs
index b30524d..7b28b53 100644
--- a/src/wan24-Crypto-BC/AsymmetricBcEcDiffieHellmanPrivateKey.cs
+++ b/src/wan24-Crypto-BC/AsymmetricBcEcDiffieHellmanPrivateKey.cs
@@ -35,6 +35,12 @@ public AsymmetricBcEcDiffieHellmanPrivateKey(byte[] keyData) : base(AsymmetricBc
/// Keys
public AsymmetricBcEcDiffieHellmanPrivateKey(AsymmetricCipherKeyPair keys) : base(AsymmetricBcEcDiffieHellmanAlgorithm.ALGORITHM_NAME, keys) { }
+ ///
+ /// Constructor
+ ///
+ /// Private key
+ public AsymmetricBcEcDiffieHellmanPrivateKey(ECPrivateKeyParameters privateKey) : base(AsymmetricBcEcDiffieHellmanAlgorithm.ALGORITHM_NAME, privateKey) { }
+
///
public override (byte[] Key, byte[] KeyExchangeData) GetKeyExchangeData(IAsymmetricPublicKey? publicKey = null, CryptoOptions? options = null)
{
diff --git a/src/wan24-Crypto-BC/AsymmetricBcEcDsaPrivateKey.cs b/src/wan24-Crypto-BC/AsymmetricBcEcDsaPrivateKey.cs
index 8a345d7..7a28709 100644
--- a/src/wan24-Crypto-BC/AsymmetricBcEcDsaPrivateKey.cs
+++ b/src/wan24-Crypto-BC/AsymmetricBcEcDsaPrivateKey.cs
@@ -35,6 +35,12 @@ public AsymmetricBcEcDsaPrivateKey(byte[] keyData) : base(AsymmetricBcEcDsaAlgor
/// Keys
public AsymmetricBcEcDsaPrivateKey(AsymmetricCipherKeyPair keys) : base(AsymmetricBcEcDsaAlgorithm.ALGORITHM_NAME, keys) { }
+ ///
+ /// Constructor
+ ///
+ /// Private key
+ public AsymmetricBcEcDsaPrivateKey(ECPrivateKeyParameters privateKey) : base(AsymmetricBcEcDsaAlgorithm.ALGORITHM_NAME, privateKey) { }
+
///
protected override ECPublicKeyParameters GetPublicKey(ECPrivateKeyParameters privateKey) => new(privateKey.Parameters.G.Multiply(privateKey.D), privateKey.Parameters);
diff --git a/src/wan24-Crypto-BC/AsymmetricBikeAlgorithm.cs b/src/wan24-Crypto-BC/AsymmetricBikeAlgorithm.cs
new file mode 100644
index 0000000..bcfc707
--- /dev/null
+++ b/src/wan24-Crypto-BC/AsymmetricBikeAlgorithm.cs
@@ -0,0 +1,70 @@
+using Org.BouncyCastle.Pqc.Crypto.Bike;
+using System.Collections.ObjectModel;
+
+namespace wan24.Crypto.BC
+{
+ ///
+ /// BIKE asymmetric algorithm
+ ///
+ public sealed record class AsymmetricBikeAlgorithm
+ : BouncyCastleAsymmetricAlgorithmBase<
+ AsymmetricBikePublicKey,
+ AsymmetricBikePrivateKey,
+ BikeKeyPairGenerator,
+ BikeKeyGenerationParameters,
+ BikeParameters,
+ BikePublicKeyParameters,
+ BikePrivateKeyParameters,
+ AsymmetricBikeAlgorithm
+ >
+ {
+ ///
+ /// Algorithm name
+ ///
+ public const string ALGORITHM_NAME = "BIKE";
+ ///
+ /// Algorithm value
+ ///
+ public const int ALGORITHM_VALUE = 15;
+ ///
+ /// Default key size in bits
+ ///
+ public const int DEFAULT_KEY_SIZE = 256;
+ ///
+ /// Algorithm usages
+ ///
+ public const AsymmetricAlgorithmUsages USAGES = AsymmetricAlgorithmUsages.KeyExchange;
+ ///
+ /// Display name
+ ///
+ public const string DISPLAY_NAME = "BIKE";
+
+ ///
+ /// Allowed key sizes in bits
+ ///
+ private static readonly ReadOnlyCollection _AllowedKeySizes;
+
+ ///
+ /// Static constructor
+ ///
+ static AsymmetricBikeAlgorithm() => _AllowedKeySizes = new List()
+ {
+ 128,// 128 bit security
+ 192,// 192 bit security
+ 256// 256 bit security
+ }.AsReadOnly();
+
+ ///
+ /// Constructor
+ ///
+ public AsymmetricBikeAlgorithm()
+ : base(ALGORITHM_NAME, ALGORITHM_VALUE, USAGES, isEllipticCurveAlgorithm: false, _AllowedKeySizes, isPostQuantum: true, DEFAULT_KEY_SIZE)
+ { }
+
+ ///
+ public override string DisplayName => DISPLAY_NAME;
+
+ ///
+ protected override BikeParameters GetEngineParameters(CryptoOptions options) => AsymmetricBikeHelper.GetParameters(options.AsymmetricKeyBits);
+ }
+}
diff --git a/src/wan24-Crypto-BC/AsymmetricBikeHelper.cs b/src/wan24-Crypto-BC/AsymmetricBikeHelper.cs
new file mode 100644
index 0000000..2d4159a
--- /dev/null
+++ b/src/wan24-Crypto-BC/AsymmetricBikeHelper.cs
@@ -0,0 +1,36 @@
+using Org.BouncyCastle.Pqc.Crypto.Bike;
+
+namespace wan24.Crypto.BC
+{
+ ///
+ /// BIKE asymmetric algorithm helper
+ ///
+ public static class AsymmetricBikeHelper
+ {
+ ///
+ /// Get the key size in bits
+ ///
+ /// Parameters
+ /// Key size in bits
+ public static int GetKeySize(this BikeParameters param)
+ {
+ if (param == BikeParameters.bike128) return 128;
+ if (param == BikeParameters.bike192) return 192;
+ if (param == BikeParameters.bike256) return 256;
+ throw new ArgumentException("Invalid BIKE parameters", nameof(param));
+ }
+
+ ///
+ /// Get the BIKE parameters
+ ///
+ /// Key size in bits
+ /// Parameters
+ public static BikeParameters GetParameters(int keySize) => keySize switch
+ {
+ 128 => BikeParameters.bike128,
+ 192 => BikeParameters.bike192,
+ 256 => BikeParameters.bike256,
+ _ => throw new ArgumentException("Invalid key size", nameof(keySize))
+ };
+ }
+}
diff --git a/src/wan24-Crypto-BC/AsymmetricBikePrivateKey.cs b/src/wan24-Crypto-BC/AsymmetricBikePrivateKey.cs
new file mode 100644
index 0000000..0206fdd
--- /dev/null
+++ b/src/wan24-Crypto-BC/AsymmetricBikePrivateKey.cs
@@ -0,0 +1,82 @@
+using Org.BouncyCastle.Crypto;
+using Org.BouncyCastle.Pqc.Crypto.Bike;
+using wan24.Core;
+
+namespace wan24.Crypto.BC
+{
+ ///
+ /// BIKE asymmetric private key
+ ///
+ public sealed record class AsymmetricBikePrivateKey
+ : BouncyCastleAsymmetricPqcPrivateKeyExchangeKeyBase<
+ AsymmetricBikePublicKey,
+ AsymmetricBikeAlgorithm,
+ BikePublicKeyParameters,
+ BikePrivateKeyParameters,
+ BikeKemGenerator,
+ BikeKemExtractor,
+ AsymmetricBikePrivateKey
+ >
+ {
+ ///
+ /// Constructor
+ ///
+ public AsymmetricBikePrivateKey() : base(AsymmetricBikeAlgorithm.ALGORITHM_NAME) { }
+
+ ///
+ /// Constructor
+ ///
+ /// Key data
+ public AsymmetricBikePrivateKey(byte[] keyData) : base(AsymmetricBikeAlgorithm.ALGORITHM_NAME, keyData) { }
+
+ ///
+ /// Constructor
+ ///
+ /// Keys
+ public AsymmetricBikePrivateKey(AsymmetricCipherKeyPair keys) : base(AsymmetricBikeAlgorithm.ALGORITHM_NAME, keys) { }
+
+ ///
+ new public static bool IsBcImportExportImplemented => false;
+
+ ///
+ protected override byte[] SerializeKeyData() => SerializeFullKeyData();
+
+ ///
+ protected override void DeserializeKeyData() => DeserializeFullKeyData();
+
+ ///
+ protected override BikePublicKeyParameters GetPublicKey(BikePrivateKeyParameters privateKey) => throw new NotSupportedException();
+
+ ///
+ protected override void Dispose(bool disposing)
+ {
+ base.Dispose(disposing);
+ if (Keys?.Private is not BikePrivateKeyParameters privateKey) return;
+ privateKey.GetH0().Clear();
+ privateKey.GetH1().Clear();
+ privateKey.GetSigma().Clear();
+ }
+
+ ///
+ protected override async Task DisposeCore()
+ {
+ await base.DisposeCore().DynamicContext();
+ if (Keys?.Private is not BikePrivateKeyParameters privateKey) return;
+ privateKey.GetH0().Clear();
+ privateKey.GetH1().Clear();
+ privateKey.GetSigma().Clear();
+ }
+
+ ///
+ /// Cast to public key
+ ///
+ /// Private key
+ public static implicit operator AsymmetricBikePublicKey(AsymmetricBikePrivateKey privateKey) => privateKey.PublicKey;
+
+ ///
+ /// Cast from serialized data
+ ///
+ /// Data
+ public static explicit operator AsymmetricBikePrivateKey(byte[] data) => Import(data);
+ }
+}
diff --git a/src/wan24-Crypto-BC/AsymmetricBikePublicKey.cs b/src/wan24-Crypto-BC/AsymmetricBikePublicKey.cs
new file mode 100644
index 0000000..8481007
--- /dev/null
+++ b/src/wan24-Crypto-BC/AsymmetricBikePublicKey.cs
@@ -0,0 +1,58 @@
+using Org.BouncyCastle.Pqc.Crypto.Bike;
+
+namespace wan24.Crypto.BC
+{
+ ///
+ /// BIKE asymmetric public key
+ ///
+ public sealed record class AsymmetricBikePublicKey : BouncyCastleAsymmetricPqcPublicKeyBase
+ {
+ ///
+ /// Constructor
+ ///
+ public AsymmetricBikePublicKey() : base(AsymmetricBikeAlgorithm.ALGORITHM_NAME) { }
+
+ ///
+ /// Constructor
+ ///
+ /// Key data
+ public AsymmetricBikePublicKey(byte[] keyData) : base(AsymmetricBikeAlgorithm.ALGORITHM_NAME, keyData) { }
+
+ ///
+ /// Constructor
+ ///
+ /// Public key
+ public AsymmetricBikePublicKey(BikePublicKeyParameters publicKey) : base(AsymmetricBikeAlgorithm.ALGORITHM_NAME, publicKey) { }
+
+ ///
+ new public static bool IsBcImportExportImplemented => false;
+
+ ///
+ public override int Bits
+ {
+ get
+ {
+ try
+ {
+ EnsureUndisposed();
+ if (_PublicKey is null) throw new InvalidOperationException();
+ return AsymmetricBikeHelper.GetKeySize(_PublicKey.Parameters);
+ }
+ catch (CryptographicException)
+ {
+ throw;
+ }
+ catch (Exception ex)
+ {
+ throw CryptographicException.From(ex);
+ }
+ }
+ }
+
+ ///
+ /// Cast from serialized data
+ ///
+ /// Data
+ public static explicit operator AsymmetricBikePublicKey(byte[] data) => Import(data);
+ }
+}
diff --git a/src/wan24-Crypto-BC/AsymmetricDilithiumAlgorithm.cs b/src/wan24-Crypto-BC/AsymmetricDilithiumAlgorithm.cs
index 50a1844..1dcf41f 100644
--- a/src/wan24-Crypto-BC/AsymmetricDilithiumAlgorithm.cs
+++ b/src/wan24-Crypto-BC/AsymmetricDilithiumAlgorithm.cs
@@ -49,9 +49,9 @@ public sealed record class AsymmetricDilithiumAlgorithm
///
static AsymmetricDilithiumAlgorithm() => _AllowedKeySizes = new List()
{
- 512,
- 768,
- 1024
+ 512,// 128 bit security
+ 768,// 192 bit security
+ 1024// 256 bit security
}.AsReadOnly();
///
diff --git a/src/wan24-Crypto-BC/AsymmetricDilithiumPrivateKey.cs b/src/wan24-Crypto-BC/AsymmetricDilithiumPrivateKey.cs
index 2750eff..e921764 100644
--- a/src/wan24-Crypto-BC/AsymmetricDilithiumPrivateKey.cs
+++ b/src/wan24-Crypto-BC/AsymmetricDilithiumPrivateKey.cs
@@ -34,6 +34,12 @@ public AsymmetricDilithiumPrivateKey(byte[] keyData) : base(AsymmetricDilithiumA
/// Keys
public AsymmetricDilithiumPrivateKey(AsymmetricCipherKeyPair keys) : base(AsymmetricDilithiumAlgorithm.ALGORITHM_NAME, keys) { }
+ ///
+ /// Constructor
+ ///
+ /// Private key
+ public AsymmetricDilithiumPrivateKey(DilithiumPrivateKeyParameters privateKey) : base(AsymmetricDilithiumAlgorithm.ALGORITHM_NAME, privateKey) { }
+
///
protected override DilithiumPublicKeyParameters GetPublicKey(DilithiumPrivateKeyParameters privateKey) => new(privateKey.Parameters, privateKey.Rho, privateKey.T1);
diff --git a/src/wan24-Crypto-BC/AsymmetricDilithiumPublicKey.cs b/src/wan24-Crypto-BC/AsymmetricDilithiumPublicKey.cs
index f73472c..3dedb00 100644
--- a/src/wan24-Crypto-BC/AsymmetricDilithiumPublicKey.cs
+++ b/src/wan24-Crypto-BC/AsymmetricDilithiumPublicKey.cs
@@ -33,7 +33,8 @@ public override int Bits
try
{
EnsureUndisposed();
- return _PublicKey?.Parameters.GetKeySize() ?? throw new InvalidOperationException();
+ if (_PublicKey is null) throw new InvalidOperationException();
+ return AsymmetricDilithiumHelper.GetKeySize(_PublicKey.Parameters);
}
catch (CryptographicException)
{
diff --git a/src/wan24-Crypto-BC/AsymmetricEd25519Algorithm.cs b/src/wan24-Crypto-BC/AsymmetricEd25519Algorithm.cs
index 803d05b..4e21fe3 100644
--- a/src/wan24-Crypto-BC/AsymmetricEd25519Algorithm.cs
+++ b/src/wan24-Crypto-BC/AsymmetricEd25519Algorithm.cs
@@ -8,7 +8,7 @@
namespace wan24.Crypto.BC
{
///
- /// Ed25519 asymmetric algorithm
+ /// Ed25519 asymmetric algorithm (128 bit security)
///
public sealed record class AsymmetricEd25519Algorithm
: BouncyCastleAsymmetricAlgorithmBase<
diff --git a/src/wan24-Crypto-BC/AsymmetricEd25519PrivateKey.cs b/src/wan24-Crypto-BC/AsymmetricEd25519PrivateKey.cs
index 62e4338..b5c3876 100644
--- a/src/wan24-Crypto-BC/AsymmetricEd25519PrivateKey.cs
+++ b/src/wan24-Crypto-BC/AsymmetricEd25519PrivateKey.cs
@@ -35,6 +35,12 @@ public AsymmetricEd25519PrivateKey(byte[] keyData) : base(AsymmetricEd25519Algor
/// Keys
public AsymmetricEd25519PrivateKey(AsymmetricCipherKeyPair keys) : base(AsymmetricEd25519Algorithm.ALGORITHM_NAME, keys) { }
+ ///
+ /// Constructor
+ ///
+ /// Private key
+ public AsymmetricEd25519PrivateKey(Ed25519PrivateKeyParameters privateKey) : base(AsymmetricEd25519Algorithm.ALGORITHM_NAME, privateKey) { }
+
///
/// Create a XEd25519 private key instance
///
diff --git a/src/wan24-Crypto-BC/AsymmetricEd448Algorithm.cs b/src/wan24-Crypto-BC/AsymmetricEd448Algorithm.cs
index 7a27d31..ef34d50 100644
--- a/src/wan24-Crypto-BC/AsymmetricEd448Algorithm.cs
+++ b/src/wan24-Crypto-BC/AsymmetricEd448Algorithm.cs
@@ -8,7 +8,7 @@
namespace wan24.Crypto.BC
{
///
- /// Ed448 asymmetric algorithm
+ /// Ed448 asymmetric algorithm (224 bit security)
///
public sealed record class AsymmetricEd448Algorithm
: BouncyCastleAsymmetricAlgorithmBase<
diff --git a/src/wan24-Crypto-BC/AsymmetricEd448PrivateKey.cs b/src/wan24-Crypto-BC/AsymmetricEd448PrivateKey.cs
index 915a736..5a53347 100644
--- a/src/wan24-Crypto-BC/AsymmetricEd448PrivateKey.cs
+++ b/src/wan24-Crypto-BC/AsymmetricEd448PrivateKey.cs
@@ -35,6 +35,12 @@ public AsymmetricEd448PrivateKey(byte[] keyData) : base(AsymmetricEd448Algorithm
/// Keys
public AsymmetricEd448PrivateKey(AsymmetricCipherKeyPair keys) : base(AsymmetricEd448Algorithm.ALGORITHM_NAME, keys) { }
+ ///
+ /// Constructor
+ ///
+ /// Private key
+ public AsymmetricEd448PrivateKey(Ed448PrivateKeyParameters privateKey) : base(AsymmetricEd448Algorithm.ALGORITHM_NAME, privateKey) { }
+
///
public override int Bits
{
diff --git a/src/wan24-Crypto-BC/AsymmetricFalconAlgorithm.cs b/src/wan24-Crypto-BC/AsymmetricFalconAlgorithm.cs
index 68b1ca6..5a320b2 100644
--- a/src/wan24-Crypto-BC/AsymmetricFalconAlgorithm.cs
+++ b/src/wan24-Crypto-BC/AsymmetricFalconAlgorithm.cs
@@ -49,8 +49,8 @@ public sealed record class AsymmetricFalconAlgorithm
///
static AsymmetricFalconAlgorithm() => _AllowedKeySizes = new List()
{
- 512,
- 1024
+ 512,// 128 bit security
+ 1024// 224 bit security
}.AsReadOnly();
///
diff --git a/src/wan24-Crypto-BC/AsymmetricFalconPrivateKey.cs b/src/wan24-Crypto-BC/AsymmetricFalconPrivateKey.cs
index 241658e..a6f417d 100644
--- a/src/wan24-Crypto-BC/AsymmetricFalconPrivateKey.cs
+++ b/src/wan24-Crypto-BC/AsymmetricFalconPrivateKey.cs
@@ -34,6 +34,12 @@ public AsymmetricFalconPrivateKey(byte[] keyData) : base(AsymmetricFalconAlgorit
/// Keys
public AsymmetricFalconPrivateKey(AsymmetricCipherKeyPair keys) : base(AsymmetricFalconAlgorithm.ALGORITHM_NAME, keys) { }
+ ///
+ /// Constructor
+ ///
+ /// Private key
+ public AsymmetricFalconPrivateKey(FalconPrivateKeyParameters privateKey) : base(AsymmetricFalconAlgorithm.ALGORITHM_NAME, privateKey) { }
+
///
protected override FalconPublicKeyParameters GetPublicKey(FalconPrivateKeyParameters privateKey) => new(privateKey.Parameters, privateKey.GetPublicKey());
diff --git a/src/wan24-Crypto-BC/AsymmetricFalconPublicKey.cs b/src/wan24-Crypto-BC/AsymmetricFalconPublicKey.cs
index f54b369..7a50148 100644
--- a/src/wan24-Crypto-BC/AsymmetricFalconPublicKey.cs
+++ b/src/wan24-Crypto-BC/AsymmetricFalconPublicKey.cs
@@ -32,7 +32,8 @@ public override int Bits
try
{
EnsureUndisposed();
- return _PublicKey?.Parameters.GetKeySize() ?? throw new InvalidOperationException();
+ if (_PublicKey is null) throw new InvalidOperationException();
+ return AsymmetricFalconHelper.GetKeySize(_PublicKey.Parameters);
}
catch (CryptographicException)
{
diff --git a/src/wan24-Crypto-BC/AsymmetricFrodoKemHelper.cs b/src/wan24-Crypto-BC/AsymmetricFrodoKemHelper.cs
index 613e675..18da683 100644
--- a/src/wan24-Crypto-BC/AsymmetricFrodoKemHelper.cs
+++ b/src/wan24-Crypto-BC/AsymmetricFrodoKemHelper.cs
@@ -1,5 +1,7 @@
using Org.BouncyCastle.Pqc.Crypto.Frodo;
+//TODO Use FalconKEM Shake parameter sets in newer version, use key complexity instead of session key size in bits as "key size"
+
namespace wan24.Crypto.BC
{
///
diff --git a/src/wan24-Crypto-BC/AsymmetricFrodoKemPrivateKey.cs b/src/wan24-Crypto-BC/AsymmetricFrodoKemPrivateKey.cs
index 3e589e9..305fdf8 100644
--- a/src/wan24-Crypto-BC/AsymmetricFrodoKemPrivateKey.cs
+++ b/src/wan24-Crypto-BC/AsymmetricFrodoKemPrivateKey.cs
@@ -1,10 +1,6 @@
-using Org.BouncyCastle.Asn1.Pkcs;
-using Org.BouncyCastle.Asn1.X509;
-using Org.BouncyCastle.Crypto;
+using Org.BouncyCastle.Crypto;
using Org.BouncyCastle.Pqc.Crypto.Frodo;
-using Org.BouncyCastle.Pqc.Crypto.Utilities;
using wan24.Core;
-using wan24.StreamSerializerExtensions;
namespace wan24.Crypto.BC
{
@@ -40,70 +36,13 @@ public AsymmetricFrodoKemPrivateKey(byte[] keyData) : base(AsymmetricFrodoKemAlg
public AsymmetricFrodoKemPrivateKey(AsymmetricCipherKeyPair keys) : base(AsymmetricFrodoKemAlgorithm.ALGORITHM_NAME, keys) { }
///
- protected override byte[] SerializeKeyData()
- {
- // Custom serialization required, because there seems to be no way to derive the public key from the private key
- try
- {
- EnsureUndisposed();
- if (Keys == null) throw new InvalidOperationException();
- using MemoryPoolStream ms = new()
- {
- CleanReturned = true
- };
- PrivateKeyInfo privateKeyInfo = PqcPrivateKeyInfoFactory.CreatePrivateKeyInfo(Keys.Private);
- using SecureByteArray privateKey = new(privateKeyInfo.GetDerEncoded());
- SubjectPublicKeyInfo publicKeyInfo = PqcSubjectPublicKeyInfoFactory.CreateSubjectPublicKeyInfo(Keys.Public);
- using SecureByteArray publicKey = new(publicKeyInfo.GetDerEncoded());
- ms.WriteSerializerVersion()
- .WriteBytes(privateKey.Array)
- .WriteBytes(publicKey.Array);
- return ms.ToArray();
- }
- catch (CryptographicException)
- {
- throw;
- }
- catch (Exception ex)
- {
- throw CryptographicException.From(ex);
- }
- }
+ new public static bool IsBcImportExportImplemented => false;
///
- protected override void DeserializeKeyData()
- {
- try
- {
- EnsureUndisposed();
- FrodoPrivateKeyParameters? privateKey = null;
- FrodoPublicKeyParameters? publicKey = null;
- try
- {
- using MemoryStream ms = new(KeyData.Array);
- int ssv = ms.ReadSerializerVersion();
- using SecureByteArrayRefStruct privateKeyInfo = new(ms.ReadBytes(ssv, maxLen: ushort.MaxValue).Value);
- privateKey = PqcPrivateKeyFactory.CreateKey(privateKeyInfo.Array) as FrodoPrivateKeyParameters ?? throw new InvalidDataException("Invalid private FrodoKEM key");
- using SecureByteArrayRefStruct publicKeyInfo = new(ms.ReadBytes(ssv, maxLen: ushort.MaxValue).Value);
- publicKey = PqcPublicKeyFactory.CreateKey(publicKeyInfo.Array) as FrodoPublicKeyParameters ?? throw new InvalidDataException("Invalid public FrodoKEM key");
- Keys = new(publicKey, privateKey);
- }
- catch
- {
- privateKey?.ClearPrivateByteArrayFields();
- publicKey?.ClearPrivateByteArrayFields();
- throw;
- }
- }
- catch (CryptographicException)
- {
- throw;
- }
- catch (Exception ex)
- {
- throw CryptographicException.From(ex);
- }
- }
+ protected override byte[] SerializeKeyData() => SerializeFullKeyData();
+
+ ///
+ protected override void DeserializeKeyData() => DeserializeFullKeyData();
///
protected override FrodoPublicKeyParameters GetPublicKey(FrodoPrivateKeyParameters privateKey) => throw new NotSupportedException();
diff --git a/src/wan24-Crypto-BC/AsymmetricFrodoKemPublicKey.cs b/src/wan24-Crypto-BC/AsymmetricFrodoKemPublicKey.cs
index 511f69c..d9e9a0f 100644
--- a/src/wan24-Crypto-BC/AsymmetricFrodoKemPublicKey.cs
+++ b/src/wan24-Crypto-BC/AsymmetricFrodoKemPublicKey.cs
@@ -24,6 +24,9 @@ public AsymmetricFrodoKemPublicKey(byte[] keyData) : base(AsymmetricFrodoKemAlgo
/// Public key
public AsymmetricFrodoKemPublicKey(FrodoPublicKeyParameters publicKey) : base(AsymmetricFrodoKemAlgorithm.ALGORITHM_NAME, publicKey) { }
+ ///
+ new public static bool IsBcImportExportImplemented => false;
+
///
public override int Bits
{
@@ -32,7 +35,8 @@ public override int Bits
try
{
EnsureUndisposed();
- return _PublicKey?.Parameters.GetKeySize() ?? throw new InvalidOperationException();
+ if (_PublicKey is null) throw new InvalidOperationException();
+ return AsymmetricFrodoKemHelper.GetKeySize(_PublicKey.Parameters);
}
catch (CryptographicException)
{
diff --git a/src/wan24-Crypto-BC/AsymmetricHqcAlgorithm.cs b/src/wan24-Crypto-BC/AsymmetricHqcAlgorithm.cs
new file mode 100644
index 0000000..c890a4e
--- /dev/null
+++ b/src/wan24-Crypto-BC/AsymmetricHqcAlgorithm.cs
@@ -0,0 +1,70 @@
+using Org.BouncyCastle.Pqc.Crypto.Hqc;
+using System.Collections.ObjectModel;
+
+namespace wan24.Crypto.BC
+{
+ ///
+ /// HQC asymmetric algorithm
+ ///
+ public sealed record class AsymmetricHqcAlgorithm
+ : BouncyCastleAsymmetricAlgorithmBase<
+ AsymmetricHqcPublicKey,
+ AsymmetricHqcPrivateKey,
+ HqcKeyPairGenerator,
+ HqcKeyGenerationParameters,
+ HqcParameters,
+ HqcPublicKeyParameters,
+ HqcPrivateKeyParameters,
+ AsymmetricHqcAlgorithm
+ >
+ {
+ ///
+ /// Algorithm name
+ ///
+ public const string ALGORITHM_NAME = "HQC";
+ ///
+ /// Algorithm value
+ ///
+ public const int ALGORITHM_VALUE = 16;
+ ///
+ /// Default key size in bits
+ ///
+ public const int DEFAULT_KEY_SIZE = 256;
+ ///
+ /// Algorithm usages
+ ///
+ public const AsymmetricAlgorithmUsages USAGES = AsymmetricAlgorithmUsages.KeyExchange;
+ ///
+ /// Display name
+ ///
+ public const string DISPLAY_NAME = "HQC";
+
+ ///
+ /// Allowed key sizes in bits
+ ///
+ private static readonly ReadOnlyCollection _AllowedKeySizes;
+
+ ///
+ /// Static constructor
+ ///
+ static AsymmetricHqcAlgorithm() => _AllowedKeySizes = new List()
+ {
+ 128,// 128 bit security
+ 192,// 192 bit security
+ 256// 256 bit security
+ }.AsReadOnly();
+
+ ///
+ /// Constructor
+ ///
+ public AsymmetricHqcAlgorithm()
+ : base(ALGORITHM_NAME, ALGORITHM_VALUE, USAGES, isEllipticCurveAlgorithm: false, _AllowedKeySizes, isPostQuantum: true, DEFAULT_KEY_SIZE)
+ { }
+
+ ///
+ public override string DisplayName => DISPLAY_NAME;
+
+ ///
+ protected override HqcParameters GetEngineParameters(CryptoOptions options) => AsymmetricHqcHelper.GetParameters(options.AsymmetricKeyBits);
+ }
+}
diff --git a/src/wan24-Crypto-BC/AsymmetricHqcHelper.cs b/src/wan24-Crypto-BC/AsymmetricHqcHelper.cs
new file mode 100644
index 0000000..0f4f1c4
--- /dev/null
+++ b/src/wan24-Crypto-BC/AsymmetricHqcHelper.cs
@@ -0,0 +1,36 @@
+using Org.BouncyCastle.Pqc.Crypto.Hqc;
+
+namespace wan24.Crypto.BC
+{
+ ///
+ /// HQC asymmetric algorithm helper
+ ///
+ public static class AsymmetricHqcHelper
+ {
+ ///
+ /// Get the key size in bits
+ ///
+ /// Parameters
+ /// Key size in bits
+ public static int GetKeySize(this HqcParameters param)
+ {
+ if (param == HqcParameters.hqc128) return 128;
+ if (param == HqcParameters.hqc192) return 192;
+ if (param == HqcParameters.hqc256) return 256;
+ throw new ArgumentException("Invalid HQC parameters", nameof(param));
+ }
+
+ ///
+ /// Get the HQC parameters
+ ///
+ /// Key size in bits
+ /// Parameters
+ public static HqcParameters GetParameters(int keySize) => keySize switch
+ {
+ 128 => HqcParameters.hqc128,
+ 192 => HqcParameters.hqc192,
+ 256 => HqcParameters.hqc256,
+ _ => throw new ArgumentException("Invalid key size", nameof(keySize))
+ };
+ }
+}
diff --git a/src/wan24-Crypto-BC/AsymmetricHqcPrivateKey.cs b/src/wan24-Crypto-BC/AsymmetricHqcPrivateKey.cs
new file mode 100644
index 0000000..a1586b8
--- /dev/null
+++ b/src/wan24-Crypto-BC/AsymmetricHqcPrivateKey.cs
@@ -0,0 +1,76 @@
+using Org.BouncyCastle.Crypto;
+using Org.BouncyCastle.Pqc.Crypto.Hqc;
+using wan24.Core;
+
+namespace wan24.Crypto.BC
+{
+ ///
+ /// HQC asymmetric private key
+ ///
+ public sealed record class AsymmetricHqcPrivateKey
+ : BouncyCastleAsymmetricPqcPrivateKeyExchangeKeyBase<
+ AsymmetricHqcPublicKey,
+ AsymmetricHqcAlgorithm,
+ HqcPublicKeyParameters,
+ HqcPrivateKeyParameters,
+ HqcKemGenerator,
+ HqcKemExtractor,
+ AsymmetricHqcPrivateKey
+ >
+ {
+ ///
+ /// Constructor
+ ///
+ public AsymmetricHqcPrivateKey() : base(AsymmetricHqcAlgorithm.ALGORITHM_NAME) { }
+
+ ///
+ /// Constructor
+ ///
+ /// Key data
+ public AsymmetricHqcPrivateKey(byte[] keyData) : base(AsymmetricHqcAlgorithm.ALGORITHM_NAME, keyData) { }
+
+ ///
+ /// Constructor
+ ///
+ /// Keys
+ public AsymmetricHqcPrivateKey(AsymmetricCipherKeyPair keys) : base(AsymmetricHqcAlgorithm.ALGORITHM_NAME, keys) { }
+
+ ///
+ new public static bool IsBcImportExportImplemented => false;
+
+ ///
+ protected override byte[] SerializeKeyData() => SerializeFullKeyData();
+
+ ///
+ protected override void DeserializeKeyData() => DeserializeFullKeyData();
+
+ ///
+ protected override HqcPublicKeyParameters GetPublicKey(HqcPrivateKeyParameters privateKey) => throw new NotSupportedException();
+
+ ///
+ protected override void Dispose(bool disposing)
+ {
+ base.Dispose(disposing);
+ Keys?.Private.ClearPrivateByteArrayFields();//TODO All parameter fields are private :(
+ }
+
+ ///
+ protected override async Task DisposeCore()
+ {
+ await base.DisposeCore().DynamicContext();
+ Keys?.Private.ClearPrivateByteArrayFields();//TODO All parameter fields are private :(
+ }
+
+ ///
+ /// Cast to public key
+ ///
+ /// Private key
+ public static implicit operator AsymmetricHqcPublicKey(AsymmetricHqcPrivateKey privateKey) => privateKey.PublicKey;
+
+ ///
+ /// Cast from serialized data
+ ///
+ /// Data
+ public static explicit operator AsymmetricHqcPrivateKey(byte[] data) => Import(data);
+ }
+}
diff --git a/src/wan24-Crypto-BC/AsymmetricHqcPublicKey.cs b/src/wan24-Crypto-BC/AsymmetricHqcPublicKey.cs
new file mode 100644
index 0000000..6829eb9
--- /dev/null
+++ b/src/wan24-Crypto-BC/AsymmetricHqcPublicKey.cs
@@ -0,0 +1,58 @@
+using Org.BouncyCastle.Pqc.Crypto.Hqc;
+
+namespace wan24.Crypto.BC
+{
+ ///
+ /// HQC asymmetric public key
+ ///
+ public sealed record class AsymmetricHqcPublicKey : BouncyCastleAsymmetricPqcPublicKeyBase
+ {
+ ///
+ /// Constructor
+ ///
+ public AsymmetricHqcPublicKey() : base(AsymmetricHqcAlgorithm.ALGORITHM_NAME) { }
+
+ ///
+ /// Constructor
+ ///
+ /// Key data
+ public AsymmetricHqcPublicKey(byte[] keyData) : base(AsymmetricHqcAlgorithm.ALGORITHM_NAME, keyData) { }
+
+ ///
+ /// Constructor
+ ///
+ /// Public key
+ public AsymmetricHqcPublicKey(HqcPublicKeyParameters publicKey) : base(AsymmetricHqcAlgorithm.ALGORITHM_NAME, publicKey) { }
+
+ ///
+ new public static bool IsBcImportExportImplemented => false;
+
+ ///
+ public override int Bits
+ {
+ get
+ {
+ try
+ {
+ EnsureUndisposed();
+ if (_PublicKey is null) throw new InvalidOperationException();
+ return AsymmetricHqcHelper.GetKeySize(_PublicKey.Parameters);
+ }
+ catch (CryptographicException)
+ {
+ throw;
+ }
+ catch (Exception ex)
+ {
+ throw CryptographicException.From(ex);
+ }
+ }
+ }
+
+ ///
+ /// Cast from serialized data
+ ///
+ /// Data
+ public static explicit operator AsymmetricHqcPublicKey(byte[] data) => Import(data);
+ }
+}
diff --git a/src/wan24-Crypto-BC/AsymmetricKyberAlgorithm.cs b/src/wan24-Crypto-BC/AsymmetricKyberAlgorithm.cs
index 0d1c91e..f6cfc56 100644
--- a/src/wan24-Crypto-BC/AsymmetricKyberAlgorithm.cs
+++ b/src/wan24-Crypto-BC/AsymmetricKyberAlgorithm.cs
@@ -49,9 +49,9 @@ public sealed record class AsymmetricKyberAlgorithm
///
static AsymmetricKyberAlgorithm() => _AllowedKeySizes = new List()
{
- 512,
- 768,
- 1024
+ 512,// 128 bit security
+ 768,// 192 bit security
+ 1024// 256 bit security
}.AsReadOnly();
///
diff --git a/src/wan24-Crypto-BC/AsymmetricKyberPrivateKey.cs b/src/wan24-Crypto-BC/AsymmetricKyberPrivateKey.cs
index 4ad6038..92827e7 100644
--- a/src/wan24-Crypto-BC/AsymmetricKyberPrivateKey.cs
+++ b/src/wan24-Crypto-BC/AsymmetricKyberPrivateKey.cs
@@ -35,6 +35,9 @@ public AsymmetricKyberPrivateKey(byte[] keyData) : base(AsymmetricKyberAlgorithm
/// Keys
public AsymmetricKyberPrivateKey(AsymmetricCipherKeyPair keys) : base(AsymmetricKyberAlgorithm.ALGORITHM_NAME, keys) { }
+ ///
+ new public static bool IsBcImportExportImplemented => false;
+
///
protected override byte[] SerializeKeyData() => SerializeFullKeyData();
diff --git a/src/wan24-Crypto-BC/AsymmetricKyberPublicKey.cs b/src/wan24-Crypto-BC/AsymmetricKyberPublicKey.cs
index 3ae7304..4a3b295 100644
--- a/src/wan24-Crypto-BC/AsymmetricKyberPublicKey.cs
+++ b/src/wan24-Crypto-BC/AsymmetricKyberPublicKey.cs
@@ -24,6 +24,9 @@ public AsymmetricKyberPublicKey(byte[] keyData) : base(AsymmetricKyberAlgorithm.
/// Public key
public AsymmetricKyberPublicKey(KyberPublicKeyParameters publicKey) : base(AsymmetricKyberAlgorithm.ALGORITHM_NAME, publicKey) { }
+ ///
+ new public static bool IsBcImportExportImplemented => false;
+
///
public override int Bits
{
@@ -32,7 +35,8 @@ public override int Bits
try
{
EnsureUndisposed();
- return _PublicKey?.Parameters.GetKeySize() ?? throw new InvalidOperationException();
+ if (_PublicKey is null) throw new InvalidOperationException();
+ return AsymmetricKyberHelper.GetKeySize(_PublicKey.Parameters);
}
catch (CryptographicException)
{
diff --git a/src/wan24-Crypto-BC/AsymmetricNtruEncryptAlgorithm.cs b/src/wan24-Crypto-BC/AsymmetricNtruEncryptAlgorithm.cs
index b99d428..51dc115 100644
--- a/src/wan24-Crypto-BC/AsymmetricNtruEncryptAlgorithm.cs
+++ b/src/wan24-Crypto-BC/AsymmetricNtruEncryptAlgorithm.cs
@@ -49,10 +49,10 @@ public sealed record class AsymmetricNtruEncryptAlgorithm
///
static AsymmetricNtruEncryptAlgorithm() => _AllowedKeySizes = new List()
{
- 509,
- 677,
- 701,
- 821
+ 509,// 128 bit security
+ 677,// 192 bit security
+ 701,// 256 bit security
+ 821// 123 bit security
}.AsReadOnly();
///
diff --git a/src/wan24-Crypto-BC/AsymmetricNtruEncryptPrivateKey.cs b/src/wan24-Crypto-BC/AsymmetricNtruEncryptPrivateKey.cs
index 977a4f5..476e82e 100644
--- a/src/wan24-Crypto-BC/AsymmetricNtruEncryptPrivateKey.cs
+++ b/src/wan24-Crypto-BC/AsymmetricNtruEncryptPrivateKey.cs
@@ -36,6 +36,9 @@ public AsymmetricNtruEncryptPrivateKey(byte[] keyData) : base(AsymmetricNtruEncr
/// Keys
public AsymmetricNtruEncryptPrivateKey(AsymmetricCipherKeyPair keys) : base(AsymmetricNtruEncryptAlgorithm.ALGORITHM_NAME, keys) { }
+ ///
+ new public static bool IsBcImportExportImplemented => false;
+
///
protected override byte[] SerializeKeyData()
{
diff --git a/src/wan24-Crypto-BC/AsymmetricNtruEncryptPublicKey.cs b/src/wan24-Crypto-BC/AsymmetricNtruEncryptPublicKey.cs
index 12ab9fc..99f1e3f 100644
--- a/src/wan24-Crypto-BC/AsymmetricNtruEncryptPublicKey.cs
+++ b/src/wan24-Crypto-BC/AsymmetricNtruEncryptPublicKey.cs
@@ -27,6 +27,9 @@ public AsymmetricNtruEncryptPublicKey(byte[] keyData) : base(AsymmetricNtruEncry
/// Public key
public AsymmetricNtruEncryptPublicKey(NtruPublicKeyParameters publicKey) : base(AsymmetricNtruEncryptAlgorithm.ALGORITHM_NAME, publicKey) { }
+ ///
+ new public static bool IsBcImportExportImplemented => false;
+
///
public override int Bits
{
@@ -35,7 +38,8 @@ public override int Bits
try
{
EnsureUndisposed();
- return _PublicKey?.Parameters.GetKeySize() ?? throw new InvalidOperationException();
+ if (_PublicKey is null) throw new InvalidOperationException();
+ return AsymmetricNtruHelper.GetKeySize(_PublicKey.Parameters);
}
catch (CryptographicException)
{
diff --git a/src/wan24-Crypto-BC/AsymmetricNtruHelper.cs b/src/wan24-Crypto-BC/AsymmetricNtruHelper.cs
index 8cd3a6d..dee31f7 100644
--- a/src/wan24-Crypto-BC/AsymmetricNtruHelper.cs
+++ b/src/wan24-Crypto-BC/AsymmetricNtruHelper.cs
@@ -1,5 +1,7 @@
using Org.BouncyCastle.Pqc.Crypto.Ntru;
+//TODO PqcPrivateKeyInfoFactory.CreatePrivateKeyInfo doesn't support NtruPrivateKeyParameters !? (waiting for a fix and an update of the NuGet package at present)
+
namespace wan24.Crypto.BC
{
///
diff --git a/src/wan24-Crypto-BC/AsymmetricPicnicAlgorithm.cs b/src/wan24-Crypto-BC/AsymmetricPicnicAlgorithm.cs
new file mode 100644
index 0000000..00a94d7
--- /dev/null
+++ b/src/wan24-Crypto-BC/AsymmetricPicnicAlgorithm.cs
@@ -0,0 +1,70 @@
+using Org.BouncyCastle.Pqc.Crypto.Picnic;
+using System.Collections.ObjectModel;
+
+namespace wan24.Crypto.BC
+{
+ ///
+ /// CRYSTALS-Dilithium asymmetric algorithm
+ ///
+ public sealed record class AsymmetricPicnicAlgorithm
+ : BouncyCastleAsymmetricAlgorithmBase<
+ AsymmetricPicnicPublicKey,
+ AsymmetricPicnicPrivateKey,
+ PicnicKeyPairGenerator,
+ PicnicKeyGenerationParameters,
+ PicnicParameters,
+ PicnicPublicKeyParameters,
+ PicnicPrivateKeyParameters,
+ AsymmetricPicnicAlgorithm
+ >
+ {
+ ///
+ /// Algorithm name
+ ///
+ public const string ALGORITHM_NAME = "PICNIC";
+ ///
+ /// Algorithm value
+ ///
+ public const int ALGORITHM_VALUE = 17;
+ ///
+ /// Default key size in bits
+ ///
+ public const int DEFAULT_KEY_SIZE = 128;
+ ///
+ /// Algorithm usages
+ ///
+ public const AsymmetricAlgorithmUsages USAGES = AsymmetricAlgorithmUsages.Signature;
+ ///
+ /// Display name
+ ///
+ public const string DISPLAY_NAME = "Picnic";
+
+ ///
+ /// Allowed key sizes in bits
+ ///
+ private static readonly ReadOnlyCollection _AllowedKeySizes;
+
+ ///
+ /// Static constructor
+ ///
+ static AsymmetricPicnicAlgorithm() => _AllowedKeySizes = new List()
+ {
+ 128,// 128 bit security
+ 192,// 192 bit security
+ 256// 256 bit security
+ }.AsReadOnly();
+
+ ///
+ /// Constructor
+ ///
+ public AsymmetricPicnicAlgorithm()
+ : base(ALGORITHM_NAME, ALGORITHM_VALUE, USAGES, isEllipticCurveAlgorithm: false, _AllowedKeySizes, isPostQuantum: true, DEFAULT_KEY_SIZE)
+ { }
+
+ ///
+ public override string DisplayName => DISPLAY_NAME;
+
+ ///
+ protected override PicnicParameters GetEngineParameters(CryptoOptions options) => AsymmetricPicnicHelper.GetParameters(options.AsymmetricKeyBits);
+ }
+}
diff --git a/src/wan24-Crypto-BC/AsymmetricPicnicHelper.cs b/src/wan24-Crypto-BC/AsymmetricPicnicHelper.cs
new file mode 100644
index 0000000..5c84909
--- /dev/null
+++ b/src/wan24-Crypto-BC/AsymmetricPicnicHelper.cs
@@ -0,0 +1,36 @@
+using Org.BouncyCastle.Pqc.Crypto.Picnic;
+
+namespace wan24.Crypto.BC
+{
+ ///
+ /// Picnic helper
+ ///
+ public static class AsymmetricPicnicHelper
+ {
+ ///
+ /// Get the key size in bits
+ ///
+ /// Parameters
+ /// Key size in bits
+ public static int GetKeySize(this PicnicParameters param)
+ {
+ if (param == PicnicParameters.picnicl1full) return 128;
+ if (param == PicnicParameters.picnicl3full) return 192;
+ if (param == PicnicParameters.picnicl5full) return 256;
+ throw new ArgumentException("Invalid Picnic parameters", nameof(param));
+ }
+
+ ///
+ /// Get the Picnic parameters
+ ///
+ /// Key size in bits
+ /// Parameters
+ public static PicnicParameters GetParameters(int keySize) => keySize switch
+ {
+ 128 => PicnicParameters.picnicl1full,
+ 192 => PicnicParameters.picnicl3full,
+ 256 => PicnicParameters.picnicl5full,
+ _ => throw new ArgumentException("Invalid key size", nameof(keySize))
+ };
+ }
+}
diff --git a/src/wan24-Crypto-BC/AsymmetricPicnicPrivateKey.cs b/src/wan24-Crypto-BC/AsymmetricPicnicPrivateKey.cs
new file mode 100644
index 0000000..f0162d2
--- /dev/null
+++ b/src/wan24-Crypto-BC/AsymmetricPicnicPrivateKey.cs
@@ -0,0 +1,75 @@
+using Org.BouncyCastle.Crypto;
+using Org.BouncyCastle.Pqc.Crypto.Picnic;
+using wan24.Core;
+
+namespace wan24.Crypto.BC
+{
+ ///
+ /// Picnic asymmetric private key
+ ///
+ public sealed record class AsymmetricPicnicPrivateKey
+ : BouncyCastleAsymmetricPqcPrivateSignatureKeyBase<
+ AsymmetricPicnicPublicKey,
+ AsymmetricPicnicAlgorithm,
+ PicnicPublicKeyParameters,
+ PicnicPrivateKeyParameters,
+ PicnicSigner,
+ AsymmetricPicnicPrivateKey
+ >
+ {
+ ///
+ /// Constructor
+ ///
+ public AsymmetricPicnicPrivateKey() : base(AsymmetricPicnicAlgorithm.ALGORITHM_NAME) { }
+
+ ///
+ /// Constructor
+ ///
+ /// Key data
+ public AsymmetricPicnicPrivateKey(byte[] keyData) : base(AsymmetricPicnicAlgorithm.ALGORITHM_NAME, keyData) { }
+
+ ///
+ /// Constructor
+ ///
+ /// Keys
+ public AsymmetricPicnicPrivateKey(AsymmetricCipherKeyPair keys) : base(AsymmetricPicnicAlgorithm.ALGORITHM_NAME, keys) { }
+
+ ///
+ new public static bool IsBcImportExportImplemented => false;
+
+ ///
+ protected override byte[] SerializeKeyData() => SerializeFullKeyData();
+
+ ///
+ protected override void DeserializeKeyData() => DeserializeFullKeyData();
+
+ ///
+ protected override PicnicPublicKeyParameters GetPublicKey(PicnicPrivateKeyParameters privateKey) => throw new NotSupportedException();
+
+ ///
+ protected override void Dispose(bool disposing)
+ {
+ base.Dispose(disposing);
+ Keys?.Private.ClearPrivateByteArrayFields();//TODO All parameter fields are private :(
+ }
+
+ ///
+ protected override async Task DisposeCore()
+ {
+ await base.DisposeCore().DynamicContext();
+ Keys?.Private.ClearPrivateByteArrayFields();//TODO All parameter fields are private :(
+ }
+
+ ///
+ /// Cast to public key
+ ///
+ /// Private key
+ public static implicit operator AsymmetricPicnicPublicKey(AsymmetricPicnicPrivateKey privateKey) => privateKey.PublicKey;
+
+ ///
+ /// Cast from serialized data
+ ///
+ /// Data
+ public static explicit operator AsymmetricPicnicPrivateKey(byte[] data) => Import(data);
+ }
+}
diff --git a/src/wan24-Crypto-BC/AsymmetricPicnicPublicKey.cs b/src/wan24-Crypto-BC/AsymmetricPicnicPublicKey.cs
new file mode 100644
index 0000000..e03b0e5
--- /dev/null
+++ b/src/wan24-Crypto-BC/AsymmetricPicnicPublicKey.cs
@@ -0,0 +1,56 @@
+using Org.BouncyCastle.Pqc.Crypto.Picnic;
+
+namespace wan24.Crypto.BC
+{
+ ///
+ /// Picnic asymmetric public key
+ ///
+ public sealed record class AsymmetricPicnicPublicKey
+ : BouncyCastleAsymmetricPqcPublicSignatureKeyBase
+ {
+ ///
+ /// Constructor
+ ///
+ public AsymmetricPicnicPublicKey() : base(AsymmetricPicnicAlgorithm.ALGORITHM_NAME) { }
+
+ ///
+ /// Constructor
+ ///
+ /// Key data
+ public AsymmetricPicnicPublicKey(byte[] keyData) : base(AsymmetricPicnicAlgorithm.ALGORITHM_NAME, keyData) { }
+
+ ///
+ /// Constructor
+ ///
+ /// Public key
+ public AsymmetricPicnicPublicKey(PicnicPublicKeyParameters publicKey) : base(AsymmetricPicnicAlgorithm.ALGORITHM_NAME, publicKey) { }
+
+ ///
+ public override int Bits
+ {
+ get
+ {
+ try
+ {
+ EnsureUndisposed();
+ if (_PublicKey is null) throw new InvalidOperationException();
+ return AsymmetricPicnicHelper.GetKeySize(_PublicKey.Parameters);
+ }
+ catch (CryptographicException)
+ {
+ throw;
+ }
+ catch (Exception ex)
+ {
+ throw CryptographicException.From(ex);
+ }
+ }
+ }
+
+ ///
+ /// Cast from serialized data
+ ///
+ /// Data
+ public static explicit operator AsymmetricPicnicPublicKey(byte[] data) => Import(data);
+ }
+}
diff --git a/src/wan24-Crypto-BC/AsymmetricSNtruPrimeAlgorithm.cs b/src/wan24-Crypto-BC/AsymmetricSNtruPrimeAlgorithm.cs
new file mode 100644
index 0000000..4a29e1e
--- /dev/null
+++ b/src/wan24-Crypto-BC/AsymmetricSNtruPrimeAlgorithm.cs
@@ -0,0 +1,96 @@
+using Org.BouncyCastle.Pqc.Crypto.NtruPrime;
+using Org.BouncyCastle.Security;
+using System.Collections.ObjectModel;
+using wan24.Core;
+
+namespace wan24.Crypto.BC
+{
+ ///
+ /// Streamlined NTRU Prime asymmetric algorithm
+ ///
+ public sealed record class AsymmetricSNtruPrimeAlgorithm
+ : BouncyCastleAsymmetricAlgorithmBase<
+ AsymmetricSNtruPrimePublicKey,
+ AsymmetricSNtruPrimePrivateKey,
+ SNtruPrimeKeyGenerationParameters,
+ SNtruPrimeParameters,
+ SNtruPrimePublicKeyParameters,
+ SNtruPrimePrivateKeyParameters,
+ AsymmetricSNtruPrimeAlgorithm
+ >
+ {
+ ///
+ /// Algorithm name
+ ///
+ public const string ALGORITHM_NAME = "SNTRUP";
+ ///
+ /// Algorithm value
+ ///
+ public const int ALGORITHM_VALUE = 14;
+ ///
+ /// Default key size in bits
+ ///
+ public const int DEFAULT_KEY_SIZE = 1277;
+ ///
+ /// Algorithm usages
+ ///
+ public const AsymmetricAlgorithmUsages USAGES = AsymmetricAlgorithmUsages.KeyExchange;
+ ///
+ /// Display name
+ ///
+ public const string DISPLAY_NAME = "Streamlined NTRU Prime";
+
+ ///
+ /// Allowed key sizes in bits
+ ///
+ private static readonly ReadOnlyCollection _AllowedKeySizes;
+
+ ///
+ /// Static constructor
+ ///
+ static AsymmetricSNtruPrimeAlgorithm() => _AllowedKeySizes = new List()
+ {
+ 653,// 128 bit security
+ 761,// 153 bit security
+ 857,// 175 bit security
+ 953,// 196 bit security
+ 1013,// 209 bit security
+ 1277// 270 bit security
+ }.AsReadOnly();
+
+ ///
+ /// Constructor
+ ///
+ public AsymmetricSNtruPrimeAlgorithm()
+ : base(ALGORITHM_NAME, ALGORITHM_VALUE, USAGES, isEllipticCurveAlgorithm: false, _AllowedKeySizes, isPostQuantum: true, DEFAULT_KEY_SIZE)
+ { }
+
+ ///
+ public override string DisplayName => DISPLAY_NAME;
+
+ ///
+ public override AsymmetricSNtruPrimePrivateKey CreateKeyPair(CryptoOptions? options = null)
+ {
+ try
+ {
+ options ??= DefaultOptions;
+ if (!options.AsymmetricKeyBits.In(AllowedKeySizes)) throw new ArgumentException("Invalid key size", nameof(options));
+ SNtruPrimeKeyPairGenerator keyGen = new();
+ keyGen.Init(CreateKeyGenParameters(new SecureRandom(BouncyCastleRandomGenerator.Instance()), GetEngineParameters(options), options));
+ return Activator.CreateInstance(typeof(AsymmetricSNtruPrimePrivateKey), keyGen.GenerateKeyPair()) as AsymmetricSNtruPrimePrivateKey
+ ?? throw new InvalidProgramException($"Failed to instance asymmetric private key {typeof(AsymmetricSNtruPrimePrivateKey)}");
+ }
+ catch (CryptographicException)
+ {
+ throw;
+ }
+ catch (Exception ex)
+ {
+ throw CryptographicException.From(ex);
+ }
+ }
+
+ ///
+ protected override SNtruPrimeParameters GetEngineParameters(CryptoOptions options) => AsymmetricSNtruPrimeHelper.GetParameters(options.AsymmetricKeyBits);
+ }
+}
diff --git a/src/wan24-Crypto-BC/AsymmetricSNtruPrimeHelper.cs b/src/wan24-Crypto-BC/AsymmetricSNtruPrimeHelper.cs
new file mode 100644
index 0000000..02549b0
--- /dev/null
+++ b/src/wan24-Crypto-BC/AsymmetricSNtruPrimeHelper.cs
@@ -0,0 +1,44 @@
+using Org.BouncyCastle.Pqc.Crypto.NtruPrime;
+
+//TODO PqcPrivateKeyInfoFactory.CreatePrivateKeyInfo doesn't support SNtruPrimaPrivateKeyParameters !? (waiting for a fix and an update of the NuGet package at present)
+
+namespace wan24.Crypto.BC
+{
+ ///
+ /// Streamlined NTRU Prime helper
+ ///
+ public static class AsymmetricSNtruPrimeHelper
+ {
+ ///
+ /// Get the key size in bits
+ ///
+ /// Parameters
+ /// Key size in bits
+ public static int GetKeySize(this SNtruPrimeParameters param)
+ {
+ if (param == SNtruPrimeParameters.sntrup653) return 653;
+ if (param == SNtruPrimeParameters.sntrup761) return 761;
+ if (param == SNtruPrimeParameters.sntrup857) return 857;
+ if (param == SNtruPrimeParameters.sntrup953) return 953;
+ if (param == SNtruPrimeParameters.sntrup1013) return 1013;
+ if (param == SNtruPrimeParameters.sntrup1277) return 1277;
+ throw new ArgumentException("Invalid Streamlined NTRU Prime parameters", nameof(param));
+ }
+
+ ///
+ /// Get the Streamline NTRU Prime parameters
+ ///
+ /// Key size in bits
+ /// Parameters
+ public static SNtruPrimeParameters GetParameters(int keySize) => keySize switch
+ {
+ 653 => SNtruPrimeParameters.sntrup653,
+ 761 => SNtruPrimeParameters.sntrup761,
+ 857 => SNtruPrimeParameters.sntrup857,
+ 953 => SNtruPrimeParameters.sntrup953,
+ 1013 => SNtruPrimeParameters.sntrup1013,
+ 1277 => SNtruPrimeParameters.sntrup1277,
+ _ => throw new ArgumentException("Invalid key size", nameof(keySize))
+ };
+ }
+}
diff --git a/src/wan24-Crypto-BC/AsymmetricSNtruPrimePrivateKey.cs b/src/wan24-Crypto-BC/AsymmetricSNtruPrimePrivateKey.cs
new file mode 100644
index 0000000..8b4869a
--- /dev/null
+++ b/src/wan24-Crypto-BC/AsymmetricSNtruPrimePrivateKey.cs
@@ -0,0 +1,134 @@
+using Org.BouncyCastle.Crypto;
+using Org.BouncyCastle.Pqc.Crypto.NtruPrime;
+using wan24.Core;
+using wan24.StreamSerializerExtensions;
+
+namespace wan24.Crypto.BC
+{
+ ///
+ /// Streamlined NTRU Prime asymmetric private key
+ ///
+ public sealed record class AsymmetricSNtruPrimePrivateKey
+ : BouncyCastleAsymmetricPqcPrivateKeyExchangeKeyBase<
+ AsymmetricSNtruPrimePublicKey,
+ AsymmetricSNtruPrimeAlgorithm,
+ SNtruPrimePublicKeyParameters,
+ SNtruPrimePrivateKeyParameters,
+ SNtruPrimeKemGenerator,
+ SNtruPrimeKemExtractor,
+ AsymmetricSNtruPrimePrivateKey
+ >
+ {
+ ///
+ /// Constructor
+ ///
+ public AsymmetricSNtruPrimePrivateKey() : base(AsymmetricSNtruPrimeAlgorithm.ALGORITHM_NAME) { }
+
+ ///
+ /// Constructor
+ ///
+ /// Key data
+ public AsymmetricSNtruPrimePrivateKey(byte[] keyData) : base(AsymmetricSNtruPrimeAlgorithm.ALGORITHM_NAME, keyData) { }
+
+ ///
+ /// Constructor
+ ///
+ /// Keys
+ public AsymmetricSNtruPrimePrivateKey(AsymmetricCipherKeyPair keys) : base(AsymmetricSNtruPrimeAlgorithm.ALGORITHM_NAME, keys) { }
+
+ ///
+ new public static bool IsBcImportExportImplemented => false;
+
+ ///
+ protected override byte[] SerializeKeyData()
+ {
+ try
+ {
+ EnsureUndisposed();
+ if (Keys == null) throw new InvalidOperationException();
+ using MemoryPoolStream ms = new()
+ {
+ CleanReturned = true
+ };
+ using SecureByteArray privateKey = new((Keys.Private as SNtruPrimePrivateKeyParameters)!.GetPrivateKey());
+ using SecureByteArray publicKey = new((Keys.Public as SNtruPrimePublicKeyParameters)!.GetPublicKey());
+ ms.WriteSerializerVersion()
+ .WriteNumber(Bits)
+ .WriteBytes(privateKey.Array)
+ .WriteBytes(publicKey.Array);
+ return ms.ToArray();
+ }
+ catch (CryptographicException)
+ {
+ throw;
+ }
+ catch (Exception ex)
+ {
+ throw CryptographicException.From(ex);
+ }
+ }
+
+ ///
+ protected override void DeserializeKeyData()
+ {
+ try
+ {
+ EnsureUndisposed();
+ SNtruPrimePrivateKeyParameters? privateKey = null;
+ SNtruPrimePublicKeyParameters? publicKey = null;
+ try
+ {
+ using MemoryStream ms = new(KeyData.Array);
+ int ssv = ms.ReadSerializerVersion();
+ SNtruPrimeParameters param = AsymmetricSNtruPrimeHelper.GetParameters(ms.ReadNumber(ssv));
+ privateKey = new(param, ms.ReadBytes(ssv, maxLen: ushort.MaxValue).Value);
+ publicKey = new(param, ms.ReadBytes(ssv, maxLen: ushort.MaxValue).Value);
+ Keys = new(publicKey, privateKey);
+ }
+ catch
+ {
+ privateKey?.ClearPrivateByteArrayFields();
+ publicKey?.ClearPrivateByteArrayFields();
+ throw;
+ }
+ }
+ catch (CryptographicException)
+ {
+ throw;
+ }
+ catch (Exception ex)
+ {
+ throw CryptographicException.From(ex);
+ }
+ }
+
+ ///
+ protected override SNtruPrimePublicKeyParameters GetPublicKey(SNtruPrimePrivateKeyParameters privateKey) => throw new NotSupportedException();
+
+ ///
+ protected override void Dispose(bool disposing)
+ {
+ base.Dispose(disposing);
+ Keys?.Private.ClearPrivateByteArrayFields();//TODO All parameter fields are private :(
+ }
+
+ ///
+ protected override async Task DisposeCore()
+ {
+ await base.DisposeCore().DynamicContext();
+ Keys?.Private.ClearPrivateByteArrayFields();//TODO All parameter fields are private :(
+ }
+
+ ///
+ /// Cast to public key
+ ///
+ /// Private key
+ public static implicit operator AsymmetricSNtruPrimePublicKey(AsymmetricSNtruPrimePrivateKey privateKey) => privateKey.PublicKey;
+
+ ///
+ /// Cast from serialized data
+ ///
+ /// Data
+ public static explicit operator AsymmetricSNtruPrimePrivateKey(byte[] data) => Import(data);
+ }
+}
diff --git a/src/wan24-Crypto-BC/AsymmetricSNtruPrimePublicKey.cs b/src/wan24-Crypto-BC/AsymmetricSNtruPrimePublicKey.cs
new file mode 100644
index 0000000..dbf7a4d
--- /dev/null
+++ b/src/wan24-Crypto-BC/AsymmetricSNtruPrimePublicKey.cs
@@ -0,0 +1,109 @@
+using Org.BouncyCastle.Pqc.Crypto.NtruPrime;
+using wan24.Core;
+using wan24.StreamSerializerExtensions;
+
+namespace wan24.Crypto.BC
+{
+ ///
+ /// Streamlined NTRU Prime asymmetric public key
+ ///
+ public sealed record class AsymmetricSNtruPrimePublicKey
+ : BouncyCastleAsymmetricPqcPublicKeyBase
+ {
+ ///
+ /// Constructor
+ ///
+ public AsymmetricSNtruPrimePublicKey() : base(AsymmetricSNtruPrimeAlgorithm.ALGORITHM_NAME) { }
+
+ ///
+ /// Constructor
+ ///
+ /// Key data
+ public AsymmetricSNtruPrimePublicKey(byte[] keyData) : base(AsymmetricSNtruPrimeAlgorithm.ALGORITHM_NAME, keyData) { }
+
+ ///
+ /// Constructor
+ ///
+ /// Public key
+ public AsymmetricSNtruPrimePublicKey(SNtruPrimePublicKeyParameters publicKey) : base(AsymmetricSNtruPrimeAlgorithm.ALGORITHM_NAME, publicKey) { }
+
+ ///
+ new public static bool IsBcImportExportImplemented => false;
+
+ ///
+ public override int Bits
+ {
+ get
+ {
+ try
+ {
+ EnsureUndisposed();
+ if (_PublicKey is null) throw new InvalidOperationException();
+ return AsymmetricSNtruPrimeHelper.GetKeySize(_PublicKey.Parameters);
+ }
+ catch (CryptographicException)
+ {
+ throw;
+ }
+ catch (Exception ex)
+ {
+ throw CryptographicException.From(ex);
+ }
+ }
+ }
+
+ ///
+ protected override byte[] SerializeKeyData()
+ {
+ try
+ {
+ EnsureUndisposed();
+ if (_PublicKey == null) throw new InvalidOperationException();
+ using MemoryPoolStream ms = new()
+ {
+ CleanReturned = true
+ };
+ using SecureByteArray publicKey = new(_PublicKey.GetPublicKey());
+ ms.WriteSerializerVersion()
+ .WriteNumber(Bits)
+ .WriteBytes(publicKey.Array);
+ return ms.ToArray();
+ }
+ catch (CryptographicException)
+ {
+ throw;
+ }
+ catch (Exception ex)
+ {
+ throw CryptographicException.From(ex);
+ }
+ }
+
+ ///
+ protected override void DeserializeKeyData()
+ {
+ try
+ {
+ EnsureUndisposed();
+ using MemoryStream ms = new(KeyData.Array);
+ int ssv = ms.ReadSerializerVersion();
+ SNtruPrimeParameters param = AsymmetricSNtruPrimeHelper.GetParameters(ms.ReadNumber(ssv));
+ _PublicKey = new(param, ms.ReadBytes(ssv, minLen: 1, maxLen: ushort.MaxValue).Value);
+ }
+ catch (CryptographicException)
+ {
+ throw;
+ }
+ catch (Exception ex)
+ {
+ throw CryptographicException.From(ex);
+ }
+ }
+
+ ///
+ /// Cast from serialized data
+ ///
+ /// Data
+ public static explicit operator AsymmetricSNtruPrimePublicKey(byte[] data) => Import(data);
+ }
+}
diff --git a/src/wan24-Crypto-BC/AsymmetricSphincsPlusAlgorithm.cs b/src/wan24-Crypto-BC/AsymmetricSphincsPlusAlgorithm.cs
index deba181..6ee2cb2 100644
--- a/src/wan24-Crypto-BC/AsymmetricSphincsPlusAlgorithm.cs
+++ b/src/wan24-Crypto-BC/AsymmetricSphincsPlusAlgorithm.cs
@@ -49,9 +49,9 @@ public sealed record class AsymmetricSphincsPlusAlgorithm
///
static AsymmetricSphincsPlusAlgorithm() => _AllowedKeySizes = new List()
{
- 128,
- 192,
- 256
+ 128,// 128 bit security
+ 192,// 192 bit security
+ 256// 256 bit security
}.AsReadOnly();
///
diff --git a/src/wan24-Crypto-BC/AsymmetricSphincsPlusHelper.cs b/src/wan24-Crypto-BC/AsymmetricSphincsPlusHelper.cs
index ba45ecd..dd2e66c 100644
--- a/src/wan24-Crypto-BC/AsymmetricSphincsPlusHelper.cs
+++ b/src/wan24-Crypto-BC/AsymmetricSphincsPlusHelper.cs
@@ -1,5 +1,8 @@
using Org.BouncyCastle.Pqc.Crypto.SphincsPlus;
+
+//FIXME Switch to SPHINCS+ Shake parameters, 'cause they've been approved in the FIPS standard
+
namespace wan24.Crypto.BC
{
///
diff --git a/src/wan24-Crypto-BC/AsymmetricSphincsPlusPrivateKey.cs b/src/wan24-Crypto-BC/AsymmetricSphincsPlusPrivateKey.cs
index 6d534f5..1f112d9 100644
--- a/src/wan24-Crypto-BC/AsymmetricSphincsPlusPrivateKey.cs
+++ b/src/wan24-Crypto-BC/AsymmetricSphincsPlusPrivateKey.cs
@@ -36,6 +36,12 @@ public AsymmetricSphincsPlusPrivateKey(byte[] keyData) : base(AsymmetricSphincsP
/// Keys
public AsymmetricSphincsPlusPrivateKey(AsymmetricCipherKeyPair keys) : base(AsymmetricSphincsPlusAlgorithm.ALGORITHM_NAME, keys) { }
+ ///
+ /// Constructor
+ ///
+ /// Private key
+ public AsymmetricSphincsPlusPrivateKey(SphincsPlusPrivateKeyParameters privateKey) : base(AsymmetricSphincsPlusAlgorithm.ALGORITHM_NAME, privateKey) { }
+
///
protected override SphincsPlusPublicKeyParameters GetPublicKey(SphincsPlusPrivateKeyParameters privateKey) => new(privateKey.Parameters, privateKey.GetPublicKey());
@@ -55,6 +61,7 @@ protected override byte[] SerializeKeyData()
ms.WriteSerializerVersion()
.WriteNumber(Bits)
.WriteBytes(privateKey.Array)
+ //TODO Don't include SPHINCS+ public key in serialized data
.WriteBytes(publicKey.Array);
return ms.ToArray();
}
@@ -81,7 +88,8 @@ protected override void DeserializeKeyData()
using MemoryStream ms = new(KeyData.Array);
int ssv = ms.ReadSerializerVersion();
SphincsPlusParameters param = AsymmetricSphincsPlusHelper.GetParameters(ms.ReadNumber(ssv));
- privateKey = new(param, ms.ReadBytes(ssv, maxLen: ushort.MaxValue).Value);
+ using SecureByteArrayRefStruct privateKeyInfo = new(ms.ReadBytes(ssv, maxLen: ushort.MaxValue).Value);
+ privateKey = new(param, privateKeyInfo.Array);
publicKey = new(param, ms.ReadBytes(ssv, maxLen: ushort.MaxValue).Value);
Keys = new(publicKey, privateKey);
}
diff --git a/src/wan24-Crypto-BC/AsymmetricSphincsPlusPublicKey.cs b/src/wan24-Crypto-BC/AsymmetricSphincsPlusPublicKey.cs
index 95008b9..bcb9d03 100644
--- a/src/wan24-Crypto-BC/AsymmetricSphincsPlusPublicKey.cs
+++ b/src/wan24-Crypto-BC/AsymmetricSphincsPlusPublicKey.cs
@@ -35,7 +35,8 @@ public override int Bits
try
{
EnsureUndisposed();
- return _PublicKey?.Parameters.GetKeySize() ?? throw new InvalidOperationException();
+ if (_PublicKey is null) throw new InvalidOperationException();
+ return AsymmetricSphincsPlusHelper.GetKeySize(_PublicKey.Parameters);
}
catch (CryptographicException)
{
diff --git a/src/wan24-Crypto-BC/AsymmetricX25519Algorithm.cs b/src/wan24-Crypto-BC/AsymmetricX25519Algorithm.cs
index 9f7b40d..de72243 100644
--- a/src/wan24-Crypto-BC/AsymmetricX25519Algorithm.cs
+++ b/src/wan24-Crypto-BC/AsymmetricX25519Algorithm.cs
@@ -8,7 +8,7 @@
namespace wan24.Crypto.BC
{
///
- /// X25519 asymmetric algorithm
+ /// X25519 asymmetric algorithm (128 bit security))
///
public sealed record class AsymmetricX25519Algorithm
: BouncyCastleAsymmetricAlgorithmBase<
diff --git a/src/wan24-Crypto-BC/AsymmetricX25519PrivateKey.cs b/src/wan24-Crypto-BC/AsymmetricX25519PrivateKey.cs
index 32145fc..19579f2 100644
--- a/src/wan24-Crypto-BC/AsymmetricX25519PrivateKey.cs
+++ b/src/wan24-Crypto-BC/AsymmetricX25519PrivateKey.cs
@@ -34,6 +34,12 @@ public AsymmetricX25519PrivateKey(byte[] keyData) : base(AsymmetricX25519Algorit
/// Keys
public AsymmetricX25519PrivateKey(AsymmetricCipherKeyPair keys) : base(AsymmetricX25519Algorithm.ALGORITHM_NAME, keys) { }
+ ///
+ /// Constructor
+ ///
+ /// Private key
+ public AsymmetricX25519PrivateKey(X25519PrivateKeyParameters privateKey) : base(AsymmetricX25519Algorithm.ALGORITHM_NAME, privateKey) { }
+
///
public override (byte[] Key, byte[] KeyExchangeData) GetKeyExchangeData(IAsymmetricPublicKey? publicKey = null, CryptoOptions? options = null)
{
diff --git a/src/wan24-Crypto-BC/AsymmetricX448Algorithm.cs b/src/wan24-Crypto-BC/AsymmetricX448Algorithm.cs
index 1caf7b5..45d65a1 100644
--- a/src/wan24-Crypto-BC/AsymmetricX448Algorithm.cs
+++ b/src/wan24-Crypto-BC/AsymmetricX448Algorithm.cs
@@ -8,7 +8,7 @@
namespace wan24.Crypto.BC
{
///
- /// X448 asymmetric algorithm
+ /// X448 asymmetric algorithm (224 bit security))
///
public sealed record class AsymmetricX448Algorithm
: BouncyCastleAsymmetricAlgorithmBase<
diff --git a/src/wan24-Crypto-BC/AsymmetricX448PrivateKey.cs b/src/wan24-Crypto-BC/AsymmetricX448PrivateKey.cs
index 529a3cb..aa9c58f 100644
--- a/src/wan24-Crypto-BC/AsymmetricX448PrivateKey.cs
+++ b/src/wan24-Crypto-BC/AsymmetricX448PrivateKey.cs
@@ -34,6 +34,12 @@ public AsymmetricX448PrivateKey(byte[] keyData) : base(AsymmetricX448Algorithm.A
/// Keys
public AsymmetricX448PrivateKey(AsymmetricCipherKeyPair keys) : base(AsymmetricX448Algorithm.ALGORITHM_NAME, keys) { }
+ ///
+ /// Constructor
+ ///
+ /// Private key
+ public AsymmetricX448PrivateKey(X448PrivateKeyParameters privateKey) : base(AsymmetricX448Algorithm.ALGORITHM_NAME, privateKey) { }
+
///
public override int Bits
{
diff --git a/src/wan24-Crypto-BC/AsymmetricXEd25519Algorithm.cs b/src/wan24-Crypto-BC/AsymmetricXEd25519Algorithm.cs
index a818b91..98ef2f8 100644
--- a/src/wan24-Crypto-BC/AsymmetricXEd25519Algorithm.cs
+++ b/src/wan24-Crypto-BC/AsymmetricXEd25519Algorithm.cs
@@ -8,7 +8,7 @@
namespace wan24.Crypto.BC
{
///
- /// XEd25519 asymmetric algorithm (converts the used Ed25519 private key to a X25519 private key for key exchange)
+ /// XEd25519 asymmetric algorithm (converts the used Ed25519 private key to a X25519 private key for key exchange, 128 bit security)
///
public sealed record class AsymmetricXEd25519Algorithm
: BouncyCastleAsymmetricAlgorithmBase<
diff --git a/src/wan24-Crypto-BC/AsymmetricXEd25519PrivateKey.cs b/src/wan24-Crypto-BC/AsymmetricXEd25519PrivateKey.cs
index 8d0ef44..399e5fc 100644
--- a/src/wan24-Crypto-BC/AsymmetricXEd25519PrivateKey.cs
+++ b/src/wan24-Crypto-BC/AsymmetricXEd25519PrivateKey.cs
@@ -40,6 +40,12 @@ public AsymmetricXEd25519PrivateKey(byte[] keyData) : base(AsymmetricXEd25519Alg
/// Keys
public AsymmetricXEd25519PrivateKey(AsymmetricCipherKeyPair keys) : base(AsymmetricXEd25519Algorithm.ALGORITHM_NAME, keys) { }
+ ///
+ /// Constructor
+ ///
+ /// Private key
+ public AsymmetricXEd25519PrivateKey(Ed25519PrivateKeyParameters privateKey) : base(AsymmetricXEd25519Algorithm.ALGORITHM_NAME, privateKey) { }
+
///
public override AsymmetricXEd25519PublicKey PublicKey
{
@@ -49,8 +55,7 @@ public override AsymmetricXEd25519PublicKey PublicKey
{
EnsureUndisposed();
if (Keys is null) throw new InvalidOperationException();
- return _PublicKey ??= Activator.CreateInstance(typeof(AsymmetricXEd25519PublicKey), Keys.Public, GetX25519Key().PublicKey) as AsymmetricXEd25519PublicKey
- ?? throw new InvalidProgramException($"Failed to instance {typeof(AsymmetricXEd25519PublicKey)}");
+ return _PublicKey ??= new((Keys.Public as Ed25519PublicKeyParameters)!, GetX25519Key().PublicKey);
}
catch (CryptographicException)
{
@@ -130,6 +135,7 @@ protected override async Task DisposeCore()
private AsymmetricX25519PrivateKey GetX25519Key()
{
EnsureUndisposed();
+ if (X25519Key is not null) return X25519Key;
if (Keys?.Private is not Ed25519PrivateKeyParameters privateKey) throw new InvalidOperationException();
X25519PrivateKeyParameters pk = privateKey.ToX25519PrivateKey();
return X25519Key = new(new AsymmetricCipherKeyPair(pk.GeneratePublicKey(), pk));
diff --git a/src/wan24-Crypto-BC/AsymmetricXEd25519PublicKey.cs b/src/wan24-Crypto-BC/AsymmetricXEd25519PublicKey.cs
index e2f2e37..28995b8 100644
--- a/src/wan24-Crypto-BC/AsymmetricXEd25519PublicKey.cs
+++ b/src/wan24-Crypto-BC/AsymmetricXEd25519PublicKey.cs
@@ -39,6 +39,9 @@ public AsymmetricXEd25519PublicKey(Ed25519PublicKeyParameters publicKey, Asymmet
KeyData = new(SerializeKeyData());
}
+ ///
+ new public static bool IsBcImportExportImplemented => false;
+
///
public override int Bits
{
diff --git a/src/wan24-Crypto-BC/AsymmetricXEd448Algorithm.cs b/src/wan24-Crypto-BC/AsymmetricXEd448Algorithm.cs
index b559f8c..952e1b5 100644
--- a/src/wan24-Crypto-BC/AsymmetricXEd448Algorithm.cs
+++ b/src/wan24-Crypto-BC/AsymmetricXEd448Algorithm.cs
@@ -8,7 +8,7 @@
namespace wan24.Crypto.BC
{
///
- /// XEd448 asymmetric algorithm (converts the used Ed448 private key to a X448 private key for key exchange)
+ /// XEd448 asymmetric algorithm (converts the used Ed448 private key to a X448 private key for key exchange; 224 bit security)
///
public sealed record class AsymmetricXEd448Algorithm
: BouncyCastleAsymmetricAlgorithmBase<
diff --git a/src/wan24-Crypto-BC/AsymmetricXEd448PrivateKey.cs b/src/wan24-Crypto-BC/AsymmetricXEd448PrivateKey.cs
index cf3076e..4b6fc49 100644
--- a/src/wan24-Crypto-BC/AsymmetricXEd448PrivateKey.cs
+++ b/src/wan24-Crypto-BC/AsymmetricXEd448PrivateKey.cs
@@ -40,6 +40,12 @@ public AsymmetricXEd448PrivateKey(byte[] keyData) : base(AsymmetricXEd448Algorit
/// Keys
public AsymmetricXEd448PrivateKey(AsymmetricCipherKeyPair keys) : base(AsymmetricXEd448Algorithm.ALGORITHM_NAME, keys) { }
+ ///
+ /// Constructor
+ ///
+ /// Private key
+ public AsymmetricXEd448PrivateKey(Ed448PrivateKeyParameters privateKey) : base(AsymmetricXEd448Algorithm.ALGORITHM_NAME, privateKey) { }
+
///
public override AsymmetricXEd448PublicKey PublicKey
{
@@ -49,8 +55,7 @@ public override AsymmetricXEd448PublicKey PublicKey
{
EnsureUndisposed();
if (Keys is null) throw new InvalidOperationException();
- return _PublicKey ??= Activator.CreateInstance(typeof(AsymmetricXEd448PublicKey), Keys.Public, GetX448Key().PublicKey) as AsymmetricXEd448PublicKey
- ?? throw new InvalidProgramException($"Failed to instance {typeof(AsymmetricXEd448PublicKey)}");
+ return _PublicKey ??= new((Keys.Public as Ed448PublicKeyParameters)!, GetX448Key().PublicKey);
}
catch (CryptographicException)
{
@@ -139,6 +144,7 @@ protected override async Task DisposeCore()
private AsymmetricX448PrivateKey GetX448Key()
{
EnsureUndisposed();
+ if (X448Key is not null) return X448Key;
if (Keys?.Private is not Ed448PrivateKeyParameters privateKey) throw new InvalidOperationException();
X448PrivateKeyParameters pk = privateKey.ToX448PrivateKey();
return X448Key = new(new AsymmetricCipherKeyPair(pk.GeneratePublicKey(), pk));
diff --git a/src/wan24-Crypto-BC/AsymmetricXEd448PublicKey.cs b/src/wan24-Crypto-BC/AsymmetricXEd448PublicKey.cs
index d31bb97..f360aa2 100644
--- a/src/wan24-Crypto-BC/AsymmetricXEd448PublicKey.cs
+++ b/src/wan24-Crypto-BC/AsymmetricXEd448PublicKey.cs
@@ -45,6 +45,9 @@ public AsymmetricXEd448PublicKey(Ed448PublicKeyParameters publicKey, AsymmetricX
/// Public key
public AsymmetricXEd448PublicKey(Ed448PublicKeyParameters publicKey) : base(AsymmetricXEd448Algorithm.ALGORITHM_NAME, publicKey) { }
+ ///
+ new public static bool IsBcImportExportImplemented => false;
+
///
public override int Bits
{
diff --git a/src/wan24-Crypto-BC/BcEllipticCurves.cs b/src/wan24-Crypto-BC/BcEllipticCurves.cs
index 8607ab9..d51842b 100644
--- a/src/wan24-Crypto-BC/BcEllipticCurves.cs
+++ b/src/wan24-Crypto-BC/BcEllipticCurves.cs
@@ -9,15 +9,15 @@ namespace wan24.Crypto.BC
public static class BcEllipticCurves
{
///
- /// secp256r1 curve (NIST P-256)
+ /// secp256r1 curve (NIST P-256, 128 bit security)
///
public static readonly ECDomainParameters SECP256R1_CURVE = new(SecNamedCurves.GetByOid(SecObjectIdentifiers.SecP256r1));
///
- /// secp384r1 curve (NIST P-384)
+ /// secp384r1 curve (NIST P-384, 192 bit security)
///
public static readonly ECDomainParameters SECP384R1_CURVE = new(SecNamedCurves.GetByOid(SecObjectIdentifiers.SecP384r1));
///
- /// secp521r1 curve (NIST P-521)
+ /// secp521r1 curve (NIST P-521, 260 bit security)
///
public static readonly ECDomainParameters SECP521R1_CURVE = new(SecNamedCurves.GetByOid(SecObjectIdentifiers.SecP521r1));
diff --git a/src/wan24-Crypto-BC/Bootstrap.cs b/src/wan24-Crypto-BC/Bootstrap.cs
index 8f9fea3..59d6948 100644
--- a/src/wan24-Crypto-BC/Bootstrap.cs
+++ b/src/wan24-Crypto-BC/Bootstrap.cs
@@ -1,5 +1,7 @@
using wan24.Core;
+//TODO Use SNTRUP as default key exchange algorithm in a newer version
+
[assembly: Bootstrapper(typeof(wan24.Crypto.BC.Bootstrap), nameof(wan24.Crypto.BC.Bootstrap.Boot))]
namespace wan24.Crypto.BC
@@ -19,9 +21,7 @@ public static void Boot()
AsymmetricHelper.Algorithms[AsymmetricFrodoKemAlgorithm.ALGORITHM_NAME] = AsymmetricFrodoKemAlgorithm.Instance;
AsymmetricHelper.Algorithms[AsymmetricDilithiumAlgorithm.ALGORITHM_NAME] = AsymmetricDilithiumAlgorithm.Instance;
AsymmetricHelper.Algorithms[AsymmetricFalconAlgorithm.ALGORITHM_NAME] = AsymmetricFalconAlgorithm.Instance;
- //FIXME PqcPrivateKeyInfoFactory.CreatePrivateKeyInfo fails with Frodo*KeyParameters !? (waiting for an update of the NuGet package at present)
AsymmetricHelper.Algorithms[AsymmetricSphincsPlusAlgorithm.ALGORITHM_NAME] = AsymmetricSphincsPlusAlgorithm.Instance;
- //FIXME PqcPrivateKeyInfoFactory.CreatePrivateKeyInfo doesn't support NtruPrivateKeyParameters !? (waiting for a fix and an update of the NuGet package at present)
AsymmetricHelper.Algorithms[AsymmetricNtruEncryptAlgorithm.ALGORITHM_NAME] = AsymmetricNtruEncryptAlgorithm.Instance;
AsymmetricHelper.Algorithms[AsymmetricEd25519Algorithm.ALGORITHM_NAME] = AsymmetricEd25519Algorithm.Instance;
AsymmetricHelper.Algorithms[AsymmetricEd448Algorithm.ALGORITHM_NAME] = AsymmetricEd448Algorithm.Instance;
@@ -29,6 +29,10 @@ public static void Boot()
AsymmetricHelper.Algorithms[AsymmetricX448Algorithm.ALGORITHM_NAME] = AsymmetricX448Algorithm.Instance;
AsymmetricHelper.Algorithms[AsymmetricXEd25519Algorithm.ALGORITHM_NAME] = AsymmetricXEd25519Algorithm.Instance;
AsymmetricHelper.Algorithms[AsymmetricXEd448Algorithm.ALGORITHM_NAME] = AsymmetricXEd448Algorithm.Instance;
+ AsymmetricHelper.Algorithms[AsymmetricSNtruPrimeAlgorithm.ALGORITHM_NAME] = AsymmetricSNtruPrimeAlgorithm.Instance;
+ AsymmetricHelper.Algorithms[AsymmetricBikeAlgorithm.ALGORITHM_NAME] = AsymmetricBikeAlgorithm.Instance;
+ AsymmetricHelper.Algorithms[AsymmetricHqcAlgorithm.ALGORITHM_NAME] = AsymmetricHqcAlgorithm.Instance;
+ AsymmetricHelper.Algorithms[AsymmetricPicnicAlgorithm.ALGORITHM_NAME] = AsymmetricPicnicAlgorithm.Instance;
// ChaCha20
EncryptionHelper.Algorithms[EncryptionChaCha20Algorithm.ALGORITHM_NAME] = EncryptionChaCha20Algorithm.Instance;
CryptoProfiles.Registered[EncryptionChaCha20Algorithm.PROFILE_CHACHA20_RAW] = new CryptoOptions()
diff --git a/src/wan24-Crypto-BC/BouncyCastleAsymmetricAlgorithmBase.cs b/src/wan24-Crypto-BC/BouncyCastleAsymmetricAlgorithmBase.cs
index faa1b80..4d94f43 100644
--- a/src/wan24-Crypto-BC/BouncyCastleAsymmetricAlgorithmBase.cs
+++ b/src/wan24-Crypto-BC/BouncyCastleAsymmetricAlgorithmBase.cs
@@ -18,7 +18,7 @@ namespace wan24.Crypto.BC
/// Private key type
/// Final type
public abstract record class BouncyCastleAsymmetricAlgorithmBase
- : AsymmetricAlgorithmBase
+ : BouncyCastleAsymmetricAlgorithmBase
where tPublic : BouncyCastleAsymmetricPublicKeyBase, new()
where tPrivate : BouncyCastleAsymmetricPrivateKeyBase, new()
where tKeyGen : IAsymmetricCipherKeyPairGenerator, new()
@@ -26,6 +26,70 @@ public abstract record class BouncyCastleAsymmetricAlgorithmBase, new()
+ {
+ ///
+ /// Constructor
+ ///
+ /// Algorithm name
+ /// Algorithm value
+ /// Algorithm usages
+ /// Is an elliptic curve algorithm?
+ /// Allowed key sizes in bits
+ /// Is a post quantum-safe algorithm?
+ /// Default key size in bits
+ protected BouncyCastleAsymmetricAlgorithmBase(
+ string name,
+ int value,
+ AsymmetricAlgorithmUsages usages,
+ bool isEllipticCurveAlgorithm,
+ ReadOnlyCollection allowedKeySizes,
+ bool isPostQuantum,
+ int defaultKeySize
+ )
+ : base(name, value, usages, isEllipticCurveAlgorithm, allowedKeySizes, isPostQuantum, defaultKeySize)
+ { }
+
+ ///
+ public override tPrivate CreateKeyPair(CryptoOptions? options = null)
+ {
+ try
+ {
+ options ??= DefaultOptions;
+ if (!options.AsymmetricKeyBits.In(AllowedKeySizes)) throw new ArgumentException("Invalid key size", nameof(options));
+ tKeyGen keyGen = new();
+ keyGen.Init(CreateKeyGenParameters(new SecureRandom(BouncyCastleRandomGenerator.Instance()), GetEngineParameters(options), options));
+ return Activator.CreateInstance(typeof(tPrivate), keyGen.GenerateKeyPair()) as tPrivate
+ ?? throw new InvalidProgramException($"Failed to instance asymmetric private key {typeof(tPrivate)}");
+ }
+ catch (CryptographicException)
+ {
+ throw;
+ }
+ catch (Exception ex)
+ {
+ throw CryptographicException.From(ex);
+ }
+ }
+ }
+
+ ///
+ /// Base class for a Bouncy Castle asymmetric algorithm
+ ///
+ /// Public key type
+ /// Private key type
+ /// Key generator parameters type
+ /// Key parameters type
+ /// Public key type
+ /// Private key type
+ /// Final type
+ public abstract record class BouncyCastleAsymmetricAlgorithmBase
+ : AsymmetricAlgorithmBase
+ where tPublic : BouncyCastleAsymmetricPublicKeyBase, new()
+ where tPrivate : BouncyCastleAsymmetricPrivateKeyBase, new()
+ where tKeyGenParam : KeyGenerationParameters
+ where tPublicKey : AsymmetricKeyParameter, ICipherParameters
+ where tPrivateKey : AsymmetricKeyParameter
+ where tFinal : BouncyCastleAsymmetricAlgorithmBase, new()
{
///
/// Static constructor
@@ -77,28 +141,6 @@ int defaultKeySize
///
public sealed override bool IsPostQuantum { get; }
- ///
- public override tPrivate CreateKeyPair(CryptoOptions? options = null)
- {
- try
- {
- options ??= DefaultOptions;
- if (!options.AsymmetricKeyBits.In(AllowedKeySizes)) throw new ArgumentException("Invalid key size", nameof(options));
- tKeyGen keyGen = new();
- keyGen.Init(CreateKeyGenParameters(new SecureRandom(BouncyCastleRandomGenerator.Instance()), GetEngineParameters(options), options));
- return Activator.CreateInstance(typeof(tPrivate), keyGen.GenerateKeyPair()) as tPrivate
- ?? throw new InvalidProgramException($"Failed to instance asymmetric private key {typeof(tPrivate)}");
- }
- catch (CryptographicException)
- {
- throw;
- }
- catch (Exception ex)
- {
- throw CryptographicException.From(ex);
- }
- }
-
///
public override tPrivate DeserializePrivateKeyV1(byte[] keyData) => throw new NotSupportedException();
diff --git a/src/wan24-Crypto-BC/BouncyCastleAsymmetricNonPqcPrivateKeyBase.cs b/src/wan24-Crypto-BC/BouncyCastleAsymmetricNonPqcPrivateKeyBase.cs
index 8820b61..9c37e07 100644
--- a/src/wan24-Crypto-BC/BouncyCastleAsymmetricNonPqcPrivateKeyBase.cs
+++ b/src/wan24-Crypto-BC/BouncyCastleAsymmetricNonPqcPrivateKeyBase.cs
@@ -43,6 +43,13 @@ protected BouncyCastleAsymmetricNonPqcPrivateKeyBase(string algorithm, byte[] ke
/// Keys
protected BouncyCastleAsymmetricNonPqcPrivateKeyBase(string algorithm, AsymmetricCipherKeyPair keys) : base(algorithm, keys) { }
+ ///
+ /// Constructor
+ ///
+ /// Algorithm name
+ /// Private key
+ protected BouncyCastleAsymmetricNonPqcPrivateKeyBase(string algorithm, tPrivateKey privateKey) : base(algorithm, privateKey) { }
+
///
protected override byte[] SerializeKeyData()
{
diff --git a/src/wan24-Crypto-BC/BouncyCastleAsymmetricNonPqcPrivateSignatureKeyBase.cs b/src/wan24-Crypto-BC/BouncyCastleAsymmetricNonPqcPrivateSignatureKeyBase.cs
index 11d8f3b..9f91c25 100644
--- a/src/wan24-Crypto-BC/BouncyCastleAsymmetricNonPqcPrivateSignatureKeyBase.cs
+++ b/src/wan24-Crypto-BC/BouncyCastleAsymmetricNonPqcPrivateSignatureKeyBase.cs
@@ -40,6 +40,13 @@ protected BouncyCastleAsymmetricNonPqcPrivateSignatureKeyBase(string algorithm,
/// Keys
protected BouncyCastleAsymmetricNonPqcPrivateSignatureKeyBase(string algorithm, AsymmetricCipherKeyPair keys) : base(algorithm, keys) { }
+ ///
+ /// Constructor
+ ///
+ /// Algorithm name
+ /// Private key
+ protected BouncyCastleAsymmetricNonPqcPrivateSignatureKeyBase(string algorithm, tPrivateKey privateKey) : base(algorithm, privateKey) { }
+
///
public override byte[] SignHashRaw(byte[] hash)
{
diff --git a/src/wan24-Crypto-BC/BouncyCastleAsymmetricNonPqcPrivateSignatureKeyBase2.cs b/src/wan24-Crypto-BC/BouncyCastleAsymmetricNonPqcPrivateSignatureKeyBase2.cs
index 64817a1..e7654fe 100644
--- a/src/wan24-Crypto-BC/BouncyCastleAsymmetricNonPqcPrivateSignatureKeyBase2.cs
+++ b/src/wan24-Crypto-BC/BouncyCastleAsymmetricNonPqcPrivateSignatureKeyBase2.cs
@@ -40,6 +40,13 @@ protected BouncyCastleAsymmetricNonPqcPrivateSignatureKeyBase2(string algorithm,
/// Keys
protected BouncyCastleAsymmetricNonPqcPrivateSignatureKeyBase2(string algorithm, AsymmetricCipherKeyPair keys) : base(algorithm, keys) { }
+ ///
+ /// Constructor
+ ///
+ /// Algorithm name
+ /// Private key
+ protected BouncyCastleAsymmetricNonPqcPrivateSignatureKeyBase2(string algorithm, tPrivateKey privateKey) : base(algorithm, privateKey) { }
+
///
public override byte[] SignHashRaw(byte[] hash)
{
diff --git a/src/wan24-Crypto-BC/BouncyCastleAsymmetricPqcPrivateKeyBase.cs b/src/wan24-Crypto-BC/BouncyCastleAsymmetricPqcPrivateKeyBase.cs
index 72a825e..8093df1 100644
--- a/src/wan24-Crypto-BC/BouncyCastleAsymmetricPqcPrivateKeyBase.cs
+++ b/src/wan24-Crypto-BC/BouncyCastleAsymmetricPqcPrivateKeyBase.cs
@@ -40,6 +40,28 @@ protected BouncyCastleAsymmetricPqcPrivateKeyBase(string algorithm, byte[] keyDa
/// Keys
protected BouncyCastleAsymmetricPqcPrivateKeyBase(string algorithm, AsymmetricCipherKeyPair keys) : base(algorithm, keys) { }
+ ///
+ /// Constructor
+ ///
+ /// Algorithm name
+ /// Private key
+ protected BouncyCastleAsymmetricPqcPrivateKeyBase(string algorithm, tPrivateKey privateKey) : base(algorithm, privateKey) { }
+
+ ///
+ public override byte[] ExportBc()
+ {
+ try
+ {
+ EnsureUndisposed();
+ if (Keys is null) throw new InvalidOperationException();
+ return PqcPrivateKeyInfoFactory.CreatePrivateKeyInfo(Keys.Private).GetDerEncoded();
+ }
+ catch (Exception ex)
+ {
+ throw CryptographicException.From(ex);
+ }
+ }
+
///
protected override byte[] SerializeKeyData()
{
@@ -96,14 +118,16 @@ protected override byte[] SerializeFullKeyData()
try
{
EnsureUndisposed();
- if (Keys == null) throw new InvalidOperationException();
+ if (Keys is null) throw new InvalidOperationException();
using MemoryPoolStream ms = new()
{
CleanReturned = true
};
+ using SecureByteArrayRefStruct privateKey = new(PqcPrivateKeyInfoFactory.CreatePrivateKeyInfo(Keys.Private).GetDerEncoded());
+ using SecureByteArrayRefStruct publicKey = new(PqcSubjectPublicKeyInfoFactory.CreateSubjectPublicKeyInfo(Keys.Public).GetDerEncoded());
ms.WriteSerializerVersion()
- .WriteBytes(PqcPrivateKeyInfoFactory.CreatePrivateKeyInfo(Keys.Private).GetDerEncoded())
- .WriteBytes(PqcSubjectPublicKeyInfoFactory.CreateSubjectPublicKeyInfo(Keys.Public).GetDerEncoded());
+ .WriteBytes(privateKey)
+ .WriteBytes(publicKey);
return ms.ToArray();
}
catch (CryptographicException)
@@ -128,8 +152,10 @@ protected override void DeserializeFullKeyData()
{
using MemoryStream ms = new(KeyData.Array);
int ssv = ms.ReadSerializerVersion();
- privateKey = (tPrivateKey)PqcPrivateKeyFactory.CreateKey(ms.ReadBytes(ssv, maxLen: ushort.MaxValue).Value);
- publicKey = (tPublicKey)PqcPublicKeyFactory.CreateKey(ms.ReadBytes(ssv, maxLen: ushort.MaxValue).Value);
+ using SecureByteArrayRefStruct privateKeyInfo = new(ms.ReadBytes(ssv, maxLen: ushort.MaxValue).Value);
+ using SecureByteArrayRefStruct publicKeyInfo = new(ms.ReadBytes(ssv, maxLen: ushort.MaxValue).Value);
+ privateKey = (tPrivateKey)PqcPrivateKeyFactory.CreateKey(privateKeyInfo);
+ publicKey = (tPublicKey)PqcPublicKeyFactory.CreateKey(publicKeyInfo);
Keys = new(publicKey, privateKey);
}
catch
@@ -148,5 +174,20 @@ protected override void DeserializeFullKeyData()
throw CryptographicException.From(ex);
}
}
+
+ ///
+ new public static tFinal ImportBc(in byte[] keyInfo)
+ {
+ try
+ {
+ return (tFinal)(Activator.CreateInstance(typeof(tFinal), PqcPrivateKeyFactory.CreateKey(keyInfo) as tPrivateKey
+ ?? throw new InvalidDataException($"Failed to deserialize {typeof(tPrivateKey)} from the given key data"))
+ ?? throw new InvalidProgramException($"Failed to instance {typeof(tFinal)}"));
+ }
+ catch (Exception ex)
+ {
+ throw CryptographicException.From(ex);
+ }
+ }
}
}
diff --git a/src/wan24-Crypto-BC/BouncyCastleAsymmetricPqcPrivateKeyExchangeKeyBase.cs b/src/wan24-Crypto-BC/BouncyCastleAsymmetricPqcPrivateKeyExchangeKeyBase.cs
index bab4229..988a1ff 100644
--- a/src/wan24-Crypto-BC/BouncyCastleAsymmetricPqcPrivateKeyExchangeKeyBase.cs
+++ b/src/wan24-Crypto-BC/BouncyCastleAsymmetricPqcPrivateKeyExchangeKeyBase.cs
@@ -44,6 +44,13 @@ protected BouncyCastleAsymmetricPqcPrivateKeyExchangeKeyBase(string algorithm, b
/// Keys
protected BouncyCastleAsymmetricPqcPrivateKeyExchangeKeyBase(string algorithm, AsymmetricCipherKeyPair keys) : base(algorithm, keys) { }
+ ///
+ /// Constructor
+ ///
+ /// Algorithm name
+ /// Private key
+ protected BouncyCastleAsymmetricPqcPrivateKeyExchangeKeyBase(string algorithm, tPrivateKey privateKey) : base(algorithm, privateKey) { }
+
///
public override (byte[] Key, byte[] KeyExchangeData) GetKeyExchangeData(IAsymmetricPublicKey? publicKey = null, CryptoOptions? options = null)
{
diff --git a/src/wan24-Crypto-BC/BouncyCastleAsymmetricPqcPrivateSignatureKeyBase.cs b/src/wan24-Crypto-BC/BouncyCastleAsymmetricPqcPrivateSignatureKeyBase.cs
index 6ffdb1a..3be7754 100644
--- a/src/wan24-Crypto-BC/BouncyCastleAsymmetricPqcPrivateSignatureKeyBase.cs
+++ b/src/wan24-Crypto-BC/BouncyCastleAsymmetricPqcPrivateSignatureKeyBase.cs
@@ -41,6 +41,13 @@ protected BouncyCastleAsymmetricPqcPrivateSignatureKeyBase(string algorithm, byt
/// Keys
protected BouncyCastleAsymmetricPqcPrivateSignatureKeyBase(string algorithm, AsymmetricCipherKeyPair keys) : base(algorithm, keys) { }
+ ///
+ /// Constructor
+ ///
+ /// Algorithm name
+ /// Private key
+ protected BouncyCastleAsymmetricPqcPrivateSignatureKeyBase(string algorithm, tPrivateKey privateKey) : base(algorithm, privateKey) { }
+
///
public sealed override byte[] SignHashRaw(byte[] hash)
{
diff --git a/src/wan24-Crypto-BC/BouncyCastleAsymmetricPqcPublicKeyBase.cs b/src/wan24-Crypto-BC/BouncyCastleAsymmetricPqcPublicKeyBase.cs
index ccdc373..1969b4e 100644
--- a/src/wan24-Crypto-BC/BouncyCastleAsymmetricPqcPublicKeyBase.cs
+++ b/src/wan24-Crypto-BC/BouncyCastleAsymmetricPqcPublicKeyBase.cs
@@ -34,6 +34,21 @@ protected BouncyCastleAsymmetricPqcPublicKeyBase(string algorithm, byte[] keyDat
/// Public key
protected BouncyCastleAsymmetricPqcPublicKeyBase(string algorithm, tPublicKey publicKey) : base(algorithm, publicKey) { }
+ ///
+ public override byte[] ExportBc()
+ {
+ try
+ {
+ EnsureUndisposed();
+ if (_PublicKey is null) throw new InvalidOperationException();
+ return PqcSubjectPublicKeyInfoFactory.CreateSubjectPublicKeyInfo(_PublicKey).GetDerEncoded();
+ }
+ catch (Exception ex)
+ {
+ throw CryptographicException.From(ex);
+ }
+ }
+
///
protected override byte[] SerializeKeyData()
{
@@ -70,5 +85,20 @@ protected override void DeserializeKeyData()
throw CryptographicException.From(ex);
}
}
+
+ ///
+ new public static tFinal ImportBc(in byte[] keyInfo)
+ {
+ try
+ {
+ return (tFinal)(Activator.CreateInstance(typeof(tFinal), PqcPublicKeyFactory.CreateKey(keyInfo) as tPublicKey
+ ?? throw new InvalidDataException())
+ ?? throw new InvalidProgramException($"Failed to instance {typeof(tFinal)}"));
+ }
+ catch (Exception ex)
+ {
+ throw CryptographicException.From(ex);
+ }
+ }
}
}
diff --git a/src/wan24-Crypto-BC/BouncyCastleAsymmetricPrivateKeyBase.cs b/src/wan24-Crypto-BC/BouncyCastleAsymmetricPrivateKeyBase.cs
index e00f002..218b9c4 100644
--- a/src/wan24-Crypto-BC/BouncyCastleAsymmetricPrivateKeyBase.cs
+++ b/src/wan24-Crypto-BC/BouncyCastleAsymmetricPrivateKeyBase.cs
@@ -1,4 +1,6 @@
using Org.BouncyCastle.Crypto;
+using Org.BouncyCastle.Pkcs;
+using Org.BouncyCastle.Security;
namespace wan24.Crypto.BC
{
@@ -48,9 +50,9 @@ protected BouncyCastleAsymmetricPrivateKeyBase(string algorithm, AsymmetricCiphe
{
try
{
- Keys = keys;
if (keys.Public is not tPublicKey) throw new ArgumentException("No valid public key parameters", nameof(keys));
if (keys.Private is not tPrivateKey) throw new ArgumentException("No valid private key parameters", nameof(keys));
+ Keys = keys;
KeyData = new(SerializeKeyData());
}
catch (CryptographicException)
@@ -63,6 +65,33 @@ protected BouncyCastleAsymmetricPrivateKeyBase(string algorithm, AsymmetricCiphe
}
}
+ ///
+ /// Constructor
+ ///
+ /// Algorithm name
+ /// Private key
+ protected BouncyCastleAsymmetricPrivateKeyBase(string algorithm, tPrivateKey privateKey) : this(algorithm)
+ {
+ try
+ {
+ Keys = new(GetPublicKey(privateKey), privateKey);
+ KeyData = new(SerializeKeyData());
+ }
+ catch (CryptographicException)
+ {
+ throw;
+ }
+ catch (Exception ex)
+ {
+ throw CryptographicException.From(ex);
+ }
+ }
+
+ ///
+ /// Is the key info export/import implemented in the Bouncy Castle library AND wan24-Crypto-BC?
+ ///
+ public static bool IsBcImportExportImplemented { get; } = true;
+
///
/// Private key
///
@@ -113,6 +142,25 @@ public override tPublic PublicKey
///
public override int Bits => PublicKey.Bits;
+ ///
+ /// Export the key in Bouncy Castle format, if possible
+ ///
+ /// Serialized key data (DER encoded; don't forget to clear!)
+ public virtual byte[] ExportBc()
+ {
+ try
+ {
+ EnsureUndisposed();
+ if (!IsBcImportExportImplemented) throw new NotSupportedException();
+ if (Keys is null) throw new InvalidOperationException();
+ return PrivateKeyInfoFactory.CreatePrivateKeyInfo(Keys.Private).GetDerEncoded();
+ }
+ catch (Exception ex)
+ {
+ throw CryptographicException.From(ex);
+ }
+ }
+
///
/// Serialize the key data
///
@@ -141,5 +189,25 @@ public override tPublic PublicKey
/// Private key
/// Public key
protected abstract tPublicKey GetPublicKey(tPrivateKey privateKey);
+
+ ///
+ /// Import a key in Bouncy Castle format (created by )
+ ///
+ /// Serialized key data (created by ; won't be cleared)
+ /// Key (don't forget to dispose!)
+ public static tFinal ImportBc(in byte[] keyInfo)
+ {
+ try
+ {
+ if (!IsBcImportExportImplemented) throw new NotSupportedException();
+ return (tFinal)(Activator.CreateInstance(typeof(tFinal), PrivateKeyFactory.CreateKey(keyInfo) as tPrivateKey
+ ?? throw new InvalidDataException($"Failed to deserialize {typeof(tPrivateKey)} from the given key data"))
+ ?? throw new InvalidProgramException($"Failed to instance {typeof(tFinal)}"));
+ }
+ catch (Exception ex)
+ {
+ throw CryptographicException.From(ex);
+ }
+ }
}
}
diff --git a/src/wan24-Crypto-BC/BouncyCastleAsymmetricPublicKeyBase.cs b/src/wan24-Crypto-BC/BouncyCastleAsymmetricPublicKeyBase.cs
index c2a5855..930ad13 100644
--- a/src/wan24-Crypto-BC/BouncyCastleAsymmetricPublicKeyBase.cs
+++ b/src/wan24-Crypto-BC/BouncyCastleAsymmetricPublicKeyBase.cs
@@ -1,4 +1,7 @@
using Org.BouncyCastle.Crypto;
+using Org.BouncyCastle.Security;
+using Org.BouncyCastle.X509;
+using wan24.Core;
namespace wan24.Crypto.BC
{
@@ -57,6 +60,11 @@ protected BouncyCastleAsymmetricPublicKeyBase(string algorithm, tPublicKey publi
}
}
+ ///
+ /// Is the key info export/import implemented in the Bouncy Castle library AND wan24-Crypto-BC?
+ ///
+ public static bool IsBcImportExportImplemented { get; } = true;
+
///
/// Public key
///
@@ -81,13 +89,32 @@ public tPublicKey PublicKey
}
}
+ ///
+ /// Export the key in Bouncy Castle format, if possible
+ ///
+ /// Serialized key data (DER encoded; don't forget to clear!)
+ public virtual byte[] ExportBc()
+ {
+ try
+ {
+ EnsureUndisposed();
+ if (!IsBcImportExportImplemented) throw new NotSupportedException();
+ if (_PublicKey is null) throw new InvalidOperationException();
+ return SubjectPublicKeyInfoFactory.CreateSubjectPublicKeyInfo(_PublicKey).GetDerEncoded();
+ }
+ catch(Exception ex)
+ {
+ throw CryptographicException.From(ex);
+ }
+ }
+
///
public sealed override IAsymmetricPublicKey GetCopy()
{
try
{
EnsureUndisposed();
- return Activator.CreateInstance(typeof(tFinal), (byte[])KeyData.Array.Clone()) as IAsymmetricPublicKey
+ return Activator.CreateInstance(typeof(tFinal), KeyData.Array.CloneArray()) as IAsymmetricPublicKey
?? throw new InvalidProgramException($"Failed to instance {typeof(tFinal)}");
}
catch (Exception ex)
@@ -106,5 +133,25 @@ public sealed override IAsymmetricPublicKey GetCopy()
/// Deserialize the key data
///
protected abstract void DeserializeKeyData();
+
+ ///
+ /// Import a key in Bouncy Castle format (created by )
+ ///
+ /// Serialized key data (created by ; won't be cleared)
+ /// Key (don't forget to dispose!)
+ public static tFinal ImportBc(in byte[] keyInfo)
+ {
+ try
+ {
+ if (!IsBcImportExportImplemented) throw new NotSupportedException();
+ return (tFinal)(Activator.CreateInstance(typeof(tFinal), PublicKeyFactory.CreateKey(keyInfo) as tPublicKey
+ ?? throw new InvalidDataException())
+ ?? throw new InvalidProgramException($"Failed to instance {typeof(tFinal)}"));
+ }
+ catch(Exception ex)
+ {
+ throw CryptographicException.From(ex);
+ }
+ }
}
}
diff --git a/src/wan24-Crypto-BC/README.md b/src/wan24-Crypto-BC/README.md
index 5d91cef..4b73b52 100644
--- a/src/wan24-Crypto-BC/README.md
+++ b/src/wan24-Crypto-BC/README.md
@@ -12,14 +12,18 @@ the `wan24-Crypto` library with these algorithms:
| CRYSTALS-Dilithium | 3 | CRYSTALSDILITHIUM |
| FALCON | 4 | FALCON |
| SPHINCS+ | 5 | SPHINCSPLUS |
-| FrodoKEM* | 6 | FRODOKEM |
-| NTRUEncrypt* | 7 | NTRUENCRYPT |
+| FrodoKEM | 6 | FRODOKEM |
+| NTRUEncrypt | 7 | NTRUENCRYPT |
| Ed25519 | 8 | ED25519 |
| Ed448 | 9 | ED448 |
| X25519 | 10 | X25519 |
| X448 | 11 | X448 |
| XEd25519 | 12 | XED25519 |
| XEd448 | 13 | XED448 |
+| Streamlined NTRU Prime | 14 | SNTRUP |
+| BIKE | 15 | BIKE |
+| HQC | 16 | HQC |
+| Picnic | 17 | PICNIC |
| **Symmetric** | | |
| ChaCha20 | 1 | CHACHA20 |
| XSalsa20 | 2 | XSALSA20 |
@@ -29,14 +33,10 @@ the `wan24-Crypto` library with these algorithms:
| Twofish 256 CBC (ISO10126 padding) | 7 | TWOFISH256CBC |
| Twofish 256 GCM AEAD (128 bit MAC) | 8 | TWOFISH256GCM |
-NTRUSign is currently not implemented, 'cause it'd require the using code to
-be GPL licensed. This algorithm may be included in a separate package which is
-licensed using the GPL license (to avoid misunderstandings) in the future.
-
-**NOTE**: SPHINCS+ and NTRUEncrypt key serialization uses a custom serializer
-at present, which will change in the future, as soon as Bouncy Castle
-implemented a (working) serializer (again). This change will require a manual
-key conversion from the current serialization format.
+Main goals of this extension library are to make `wan24-Crypto` usable on all
+platforms and extend its algorithms by PQC algorithms and other non-PQC
+algorithms, which are not available from .NET, but implemented in the Bouncy
+Castle library.
## How to get it
@@ -54,21 +54,7 @@ wan24.Crypto.BC.Bootstrap.Boot();
This will register the algorithms to the `wan24-Crypto` library.
-To set Bouncy Castle defaults as `wan24-Crypto` defaults:
-
-```cs
-BouncyCastle.SetDefaults();
-```
-
-Per default the current `wan24-Crypto` default will be set as counter
-algorithms to `HybridAlgorithmHelper`.
-
-Current Bouncy Castle default algorithms are:
-
-- Key exchange: NTRUEncrypt
-- Signature: CRYSTALS-Dilithium
-- Encryption: Serpent 256 bit CBC
-- PAKE encryption: Serpent 256 bit GCM
+### `wan24-Crypto` algorithm replacement
Some algorithms of the `wan24-Crypto` library are not available on some
platforms, that's why they need to be replaced in order to be used:
@@ -95,7 +81,28 @@ BouncyCastle.ReplaceNetAlgorithms();
**NOTE**: The Shake128/256 replacements don't support variable output length
and use the default output length of the `wan24-Crypto` implementations
-instead.
+instead. The `NetShake128/256HashAlgorithmAdapter` can't be replaced for this
+reason.
+
+### Use as default algorithms
+
+To set Bouncy Castle defaults as `wan24-Crypto` defaults:
+
+```cs
+BouncyCastle.SetDefaults();
+```
+
+Per default the current `wan24-Crypto` default will be set as counter
+algorithms to `HybridAlgorithmHelper`.
+
+Current Bouncy Castle default algorithms are:
+
+| Usage | Algorithm |
+| ----- | --------- |
+| Key exchange | NTRUEncrypt |
+| Signature | CRYSTALS-Dilithium |
+| Encryption | Serpent 256 bit CBC |
+| PAKE encryption | Serpent 256 bit GCM |
## Post quantum safety
@@ -107,6 +114,10 @@ These asymmetric algorithms are designed for post quantum cryptography:
- SPHINCS+ (signature)
- FrodoKEM (key exchange)
- NTRUEncrypt (key exchange)
+- Streamlined NTRU Prime (key exchange)
+- BIKE (key exchange)
+- HQC (key exchange)
+- Picnic (signature)
Normally you want to use them in hybrid mode and use classical algorithms of
the `wan24-Crypto` package as counter algorithm. To do this per default:
@@ -148,11 +159,23 @@ SignatureContainer signature = dataToSign.Sign(yourNormalPrivateKey, options: op
## Algorithm parameters used
-For CRYSTALS-Kyber and CRYSTALS-Dilithium the non-AES parameters are being
-used, since the AES parameter sets have been deprecated. When using SPHINCS+,
-the Haraka simple hashing parameters will be used (since the Haraka robust
-hashing parameters have been reprecated). For FrodoKEM the AES parameters will
-be used.
+| Algorithm | Parameters |
+| --------- | ---------- |
+| CRYSTALS-Kyber, CRYSTALS-Dilithium | non-AES |
+| SPHINCS+ | Haraka simple* |
+| FrodoKEM | AES* |
+| Picnic | Full |
+
+**NOTE**: CRYSTALS-Kyber and CRYSTALS-Dilithium AES parameters and SPHINCS+
+robust parameters are deprecated! SPHINCS+ Haraka parameters are removed from
+the FIPS standard, so `wan24-Crypto-BC` will switch to Shake parameters
+instead. Also the FrodoKEM Shake parameters will be used in the next major
+release, which will require to renew existing keys, which use the AES
+parameters from the current version of this library.
+
+**WARNING** The PQC standards are in development at the moment, so future
+incompatible changes are very likely and will be handled in a new major
+release of this library.
## Random data provider
@@ -186,8 +209,10 @@ bytes of an underlaying PRNG using a random key. The result is a CSRNG. These
stream ciphers are available with `wan24-Crypto-BC`, but you could use any
other stream cipher (but not AEAD implementations!) also:
-- ChaCha20 - `ChaCha20Rng`
-- XSalsa20 - `XSalsa20Rng`
+| Stream cipher | RNG |
+| ------------- | --- |
+| ChaCha20 | `ChaCha20Rng` |
+| XSalsa20 | `XSalsa20Rng` |
If you didn't specify an underlaying PRNG, Bouncy Castle's
`VmpcRandomGenerator` will be used and seeded using 256 bytes from `RND`.
diff --git a/src/wan24-Crypto-BC/wan24-Crypto-BC.csproj b/src/wan24-Crypto-BC/wan24-Crypto-BC.csproj
index da8803d..7763557 100644
--- a/src/wan24-Crypto-BC/wan24-Crypto-BC.csproj
+++ b/src/wan24-Crypto-BC/wan24-Crypto-BC.csproj
@@ -9,7 +9,7 @@
True
wan24-Crypto-BC
wan24-Crypto-BC
- 3.0.0
+ 3.1.0
nd1012
Andreas Zimmermann, wan24.de
wan24-Crypto-BC
@@ -33,8 +33,8 @@
-
-
+
+