diff options
author | David Hook <dgh@cryptoworkshop.com> | 2020-04-25 16:53:47 +1000 |
---|---|---|
committer | David Hook <dgh@cryptoworkshop.com> | 2020-04-25 16:53:47 +1000 |
commit | 99467b8431c1a871792ecb34fd5eeb962353b1d2 (patch) | |
tree | 043b017ad8dd740c71e8f0661a170109672b6bb6 | |
parent | github #237 - gost 2012 parsing (diff) | |
download | BouncyCastle.NET-ed25519-99467b8431c1a871792ecb34fd5eeb962353b1d2.tar.xz |
first cut at PKCS#5 Scheme 2 in PKCS#12
-rw-r--r-- | crypto/src/pkcs/EncryptedPrivateKeyInfoFactory.cs | 38 | ||||
-rw-r--r-- | crypto/src/pkcs/PKCS12StoreBuilder.cs | 11 | ||||
-rw-r--r-- | crypto/src/pkcs/Pkcs12Store.cs | 34 | ||||
-rw-r--r-- | crypto/src/security/PbeUtilities.cs | 30 |
4 files changed, 108 insertions, 5 deletions
diff --git a/crypto/src/pkcs/EncryptedPrivateKeyInfoFactory.cs b/crypto/src/pkcs/EncryptedPrivateKeyInfoFactory.cs index b6b7bac65..000eb7ae5 100644 --- a/crypto/src/pkcs/EncryptedPrivateKeyInfoFactory.cs +++ b/crypto/src/pkcs/EncryptedPrivateKeyInfoFactory.cs @@ -60,5 +60,43 @@ namespace Org.BouncyCastle.Pkcs AlgorithmIdentifier algID = new AlgorithmIdentifier(oid, pbeParameters); return new EncryptedPrivateKeyInfo(algID, encoding); } + + public static EncryptedPrivateKeyInfo CreateEncryptedPrivateKeyInfo( + DerObjectIdentifier cipherAlgorithm, + DerObjectIdentifier prfAlgorithm, + char[] passPhrase, + byte[] salt, + int iterationCount, + SecureRandom random, + AsymmetricKeyParameter key) + { + return CreateEncryptedPrivateKeyInfo( + cipherAlgorithm, prfAlgorithm, passPhrase, salt, iterationCount, random, + PrivateKeyInfoFactory.CreatePrivateKeyInfo(key)); + } + + public static EncryptedPrivateKeyInfo CreateEncryptedPrivateKeyInfo( + DerObjectIdentifier cipherAlgorithm, + DerObjectIdentifier prfAlgorithm, + char[] passPhrase, + byte[] salt, + int iterationCount, + SecureRandom random, + PrivateKeyInfo keyInfo) + { + IBufferedCipher cipher = CipherUtilities.GetCipher(cipherAlgorithm) as IBufferedCipher; + if (cipher == null) + throw new Exception("Unknown encryption algorithm: " + cipherAlgorithm); + + Asn1Encodable pbeParameters = PbeUtilities.GenerateAlgorithmParameters( + cipherAlgorithm, prfAlgorithm, salt, iterationCount, random); + ICipherParameters cipherParameters = PbeUtilities.GenerateCipherParameters( + PkcsObjectIdentifiers.IdPbeS2, passPhrase, pbeParameters); + cipher.Init(true, cipherParameters); + byte[] encoding = cipher.DoFinal(keyInfo.GetEncoded()); + + AlgorithmIdentifier algID = new AlgorithmIdentifier(PkcsObjectIdentifiers.IdPbeS2, pbeParameters); + return new EncryptedPrivateKeyInfo(algID, encoding); + } } } diff --git a/crypto/src/pkcs/PKCS12StoreBuilder.cs b/crypto/src/pkcs/PKCS12StoreBuilder.cs index c8fa0f603..b61a9ea63 100644 --- a/crypto/src/pkcs/PKCS12StoreBuilder.cs +++ b/crypto/src/pkcs/PKCS12StoreBuilder.cs @@ -9,6 +9,8 @@ namespace Org.BouncyCastle.Pkcs { private DerObjectIdentifier keyAlgorithm = PkcsObjectIdentifiers.PbeWithShaAnd3KeyTripleDesCbc; private DerObjectIdentifier certAlgorithm = PkcsObjectIdentifiers.PbewithShaAnd40BitRC2Cbc; + private DerObjectIdentifier keyPrfAlgorithm = null; + private DerObjectIdentifier certPrfAlgorithm = null; private bool useDerEncoding = false; public Pkcs12StoreBuilder() @@ -17,7 +19,7 @@ namespace Org.BouncyCastle.Pkcs public Pkcs12Store Build() { - return new Pkcs12Store(keyAlgorithm, certAlgorithm, useDerEncoding); + return new Pkcs12Store(keyAlgorithm, keyPrfAlgorithm, certAlgorithm, certPrfAlgorithm, useDerEncoding); } public Pkcs12StoreBuilder SetCertAlgorithm(DerObjectIdentifier certAlgorithm) @@ -32,6 +34,13 @@ namespace Org.BouncyCastle.Pkcs return this; } + // Specify a PKCS#5 Scheme 2 encryption for keys + public Pkcs12StoreBuilder SetKeyAlgorithm(DerObjectIdentifier keyAlgorithm, DerObjectIdentifier keyPrfAlgorithm) + { + this.keyAlgorithm = keyAlgorithm; + this.keyPrfAlgorithm = keyPrfAlgorithm; + return this; + } public Pkcs12StoreBuilder SetUseDerEncoding(bool useDerEncoding) { this.useDerEncoding = useDerEncoding; diff --git a/crypto/src/pkcs/Pkcs12Store.cs b/crypto/src/pkcs/Pkcs12Store.cs index 50db14d61..0eff8eb92 100644 --- a/crypto/src/pkcs/Pkcs12Store.cs +++ b/crypto/src/pkcs/Pkcs12Store.cs @@ -27,7 +27,9 @@ namespace Org.BouncyCastle.Pkcs private readonly IDictionary chainCerts = Platform.CreateHashtable(); private readonly IDictionary keyCerts = Platform.CreateHashtable(); private readonly DerObjectIdentifier keyAlgorithm; + private readonly DerObjectIdentifier keyPrfAlgorithm; private readonly DerObjectIdentifier certAlgorithm; + private readonly DerObjectIdentifier certPrfAlgorithm; private readonly bool useDerEncoding; private AsymmetricKeyEntry unmarkedKeyEntry = null; @@ -89,12 +91,28 @@ namespace Org.BouncyCastle.Pkcs bool useDerEncoding) { this.keyAlgorithm = keyAlgorithm; + this.keyPrfAlgorithm = null; this.certAlgorithm = certAlgorithm; + this.certPrfAlgorithm = null; + this.useDerEncoding = useDerEncoding; + } + + internal Pkcs12Store( + DerObjectIdentifier keyAlgorithm, + DerObjectIdentifier keyPrfAlgorithm, + DerObjectIdentifier certAlgorithm, + DerObjectIdentifier certPrfAlgorithm, + bool useDerEncoding) + { + this.keyAlgorithm = keyAlgorithm; + this.keyPrfAlgorithm = keyPrfAlgorithm; + this.certAlgorithm = certAlgorithm; + this.certPrfAlgorithm = certPrfAlgorithm; this.useDerEncoding = useDerEncoding; } // TODO Consider making obsolete -// [Obsolete("Use 'Pkcs12StoreBuilder' instead")] + // [Obsolete("Use 'Pkcs12StoreBuilder' instead")] public Pkcs12Store() : this(PkcsObjectIdentifiers.PbeWithShaAnd3KeyTripleDesCbc, PkcsObjectIdentifiers.PbewithShaAnd40BitRC2Cbc, false) @@ -748,8 +766,16 @@ namespace Org.BouncyCastle.Pkcs else { bagOid = PkcsObjectIdentifiers.Pkcs8ShroudedKeyBag; - bagData = EncryptedPrivateKeyInfoFactory.CreateEncryptedPrivateKeyInfo( - keyAlgorithm, password, kSalt, MinIterations, privKey.Key); + if (keyPrfAlgorithm != null) + { + bagData = EncryptedPrivateKeyInfoFactory.CreateEncryptedPrivateKeyInfo( + keyAlgorithm, keyPrfAlgorithm, password, kSalt, MinIterations, random, privKey.Key); + } + else + { + bagData = EncryptedPrivateKeyInfoFactory.CreateEncryptedPrivateKeyInfo( + keyAlgorithm, password, kSalt, MinIterations, privKey.Key); + } } Asn1EncodableVector kName = new Asn1EncodableVector(); @@ -952,7 +978,7 @@ namespace Org.BouncyCastle.Pkcs byte[] certBagsEncoding = new DerSequence(certBags).GetDerEncoded(); ContentInfo certsInfo; - if (password == null) + if (password == null || certAlgorithm == null) { certsInfo = new ContentInfo(PkcsObjectIdentifiers.Data, new BerOctetString(certBagsEncoding)); } diff --git a/crypto/src/security/PbeUtilities.cs b/crypto/src/security/PbeUtilities.cs index ce47e38e5..622c6dd43 100644 --- a/crypto/src/security/PbeUtilities.cs +++ b/crypto/src/security/PbeUtilities.cs @@ -42,6 +42,7 @@ namespace Org.BouncyCastle.Security { algorithms["PKCS5SCHEME1"] = "Pkcs5scheme1"; algorithms["PKCS5SCHEME2"] = "Pkcs5scheme2"; + algorithms["PBKDF2"] = "Pkcs5scheme2"; algorithms[PkcsObjectIdentifiers.IdPbeS2.Id] = "Pkcs5scheme2"; // algorithms[PkcsObjectIdentifiers.IdPbkdf2.Id] = "Pkcs5scheme2"; @@ -324,6 +325,35 @@ namespace Org.BouncyCastle.Security } } + public static Asn1Encodable GenerateAlgorithmParameters( + DerObjectIdentifier cipherAlgorithm, + DerObjectIdentifier hashAlgorithm, + byte[] salt, + int iterationCount, + SecureRandom secureRandom) + { + EncryptionScheme encScheme; + if (NistObjectIdentifiers.IdAes128Cbc.Equals(cipherAlgorithm) + || NistObjectIdentifiers.IdAes192Cbc.Equals(cipherAlgorithm) + || NistObjectIdentifiers.IdAes256Cbc.Equals(cipherAlgorithm) + || NistObjectIdentifiers.IdAes128Cfb.Equals(cipherAlgorithm) + || NistObjectIdentifiers.IdAes192Cfb.Equals(cipherAlgorithm) + || NistObjectIdentifiers.IdAes256Cfb.Equals(cipherAlgorithm)) + { + byte[] iv = new byte[16]; + secureRandom.NextBytes(iv); + encScheme = new EncryptionScheme(cipherAlgorithm, new DerOctetString(iv)); + } + else + { + throw new ArgumentException("unknown cipher: " + cipherAlgorithm); + } + + KeyDerivationFunc func = new KeyDerivationFunc(PkcsObjectIdentifiers.IdPbkdf2, new Pbkdf2Params(salt, iterationCount, new AlgorithmIdentifier(hashAlgorithm, DerNull.Instance))); + + return new PbeS2Parameters(func, encScheme); + } + public static ICipherParameters GenerateCipherParameters( DerObjectIdentifier algorithmOid, char[] password, |