diff options
author | Peter Dettman <peter.dettman@bouncycastle.org> | 2014-07-21 17:09:02 +0700 |
---|---|---|
committer | Peter Dettman <peter.dettman@bouncycastle.org> | 2014-07-21 17:09:02 +0700 |
commit | 1b5c1c2c06974fab9cd7dc04a836e32b3dc6e21a (patch) | |
tree | 6ab92802e95e09a5a55ee32898e9c4c1b3a90c68 /crypto/src | |
parent | Port update from Java (diff) | |
download | BouncyCastle.NET-ed25519-1b5c1c2c06974fab9cd7dc04a836e32b3dc6e21a.tar.xz |
Port of PrivateKeyInfo changes from Java
Diffstat (limited to 'crypto/src')
-rw-r--r-- | crypto/src/asn1/pkcs/PrivateKeyInfo.cs | 143 | ||||
-rw-r--r-- | crypto/src/cms/KeyAgreeRecipientInformation.cs | 410 | ||||
-rw-r--r-- | crypto/src/openssl/MiscPemGenerator.cs | 470 | ||||
-rw-r--r-- | crypto/src/security/PrivateKeyFactory.cs | 16 |
4 files changed, 524 insertions, 515 deletions
diff --git a/crypto/src/asn1/pkcs/PrivateKeyInfo.cs b/crypto/src/asn1/pkcs/PrivateKeyInfo.cs index 91b6fb456..a63595d54 100644 --- a/crypto/src/asn1/pkcs/PrivateKeyInfo.cs +++ b/crypto/src/asn1/pkcs/PrivateKeyInfo.cs @@ -10,46 +10,46 @@ namespace Org.BouncyCastle.Asn1.Pkcs public class PrivateKeyInfo : Asn1Encodable { - private readonly Asn1Object privKey; + private readonly Asn1OctetString privKey; private readonly AlgorithmIdentifier algID; - private readonly Asn1Set attributes; + private readonly Asn1Set attributes; - public static PrivateKeyInfo GetInstance( - object obj) - { - if (obj is PrivateKeyInfo) - return (PrivateKeyInfo) obj; + public static PrivateKeyInfo GetInstance(Asn1TaggedObject obj, bool explicitly) + { + return GetInstance(Asn1Sequence.GetInstance(obj, explicitly)); + } - if (obj != null) - return new PrivateKeyInfo(Asn1Sequence.GetInstance(obj)); + public static PrivateKeyInfo GetInstance( + object obj) + { + if (obj == null) + return null; + if (obj is PrivateKeyInfo) + return (PrivateKeyInfo) obj; + return new PrivateKeyInfo(Asn1Sequence.GetInstance(obj)); + } - return null; - } + public PrivateKeyInfo(AlgorithmIdentifier algID, Asn1Object privateKey) + : this(algID, privateKey, null) + { + } - public PrivateKeyInfo( + public PrivateKeyInfo( AlgorithmIdentifier algID, - Asn1Object privateKey) - : this(algID, privateKey, null) - { - } - - public PrivateKeyInfo( - AlgorithmIdentifier algID, - Asn1Object privateKey, - Asn1Set attributes) - { - this.privKey = privateKey; - this.algID = algID; - this.attributes = attributes; - } - - private PrivateKeyInfo( - Asn1Sequence seq) + Asn1Object privateKey, + Asn1Set attributes) + { + this.algID = algID; + this.privKey = new DerOctetString(privateKey.GetEncoded(Asn1Encodable.Der)); + this.attributes = attributes; + } + + private PrivateKeyInfo(Asn1Sequence seq) { IEnumerator e = seq.GetEnumerator(); - e.MoveNext(); - BigInteger version = ((DerInteger) e.Current).Value; + e.MoveNext(); + BigInteger version = ((DerInteger)e.Current).Value; if (version.IntValue != 0) { throw new ArgumentException("wrong version for private key info: " + version.IntValue); @@ -57,41 +57,53 @@ namespace Org.BouncyCastle.Asn1.Pkcs e.MoveNext(); algID = AlgorithmIdentifier.GetInstance(e.Current); + e.MoveNext(); + privKey = Asn1OctetString.GetInstance(e.Current); - try - { - e.MoveNext(); - Asn1OctetString data = (Asn1OctetString) e.Current; - - privKey = Asn1Object.FromByteArray(data.GetOctets()); - } - catch (IOException) + if (e.MoveNext()) { - throw new ArgumentException("Error recoverying private key from sequence"); + attributes = Asn1Set.GetInstance((Asn1TaggedObject)e.Current, false); } + } - if (e.MoveNext()) - { - attributes = Asn1Set.GetInstance((Asn1TaggedObject) e.Current, false); - } - } + public virtual AlgorithmIdentifier PrivateKeyAlgorithm + { + get { return algID; } + } - public AlgorithmIdentifier AlgorithmID - { - get { return algID; } - } + [Obsolete("Use 'PrivateKeyAlgorithm' property instead")] + public virtual AlgorithmIdentifier AlgorithmID + { + get { return algID; } + } - public Asn1Object PrivateKey - { - get { return privKey; } - } + public virtual Asn1Object ParsePrivateKey() + { + return Asn1Object.FromByteArray(privKey.GetOctets()); + } - public Asn1Set Attributes - { - get { return attributes; } - } + [Obsolete("Use 'ParsePrivateKey' instead")] + public virtual Asn1Object PrivateKey + { + get + { + try + { + return ParsePrivateKey(); + } + catch (IOException e) + { + throw new InvalidOperationException("unable to parse private key"); + } + } + } - /** + public virtual Asn1Set Attributes + { + get { return attributes; } + } + + /** * write out an RSA private key with its associated information * as described in Pkcs8. * <pre> @@ -110,17 +122,14 @@ namespace Org.BouncyCastle.Asn1.Pkcs */ public override Asn1Object ToAsn1Object() { - Asn1EncodableVector v = new Asn1EncodableVector( - new DerInteger(0), - algID, - new DerOctetString(privKey)); + Asn1EncodableVector v = new Asn1EncodableVector(new DerInteger(0), algID, privKey); - if (attributes != null) - { - v.Add(new DerTaggedObject(false, 0, attributes)); - } + if (attributes != null) + { + v.Add(new DerTaggedObject(false, 0, attributes)); + } - return new DerSequence(v); + return new DerSequence(v); } } } diff --git a/crypto/src/cms/KeyAgreeRecipientInformation.cs b/crypto/src/cms/KeyAgreeRecipientInformation.cs index 38a94b0a4..8e006e545 100644 --- a/crypto/src/cms/KeyAgreeRecipientInformation.cs +++ b/crypto/src/cms/KeyAgreeRecipientInformation.cs @@ -18,209 +18,209 @@ using Org.BouncyCastle.X509; namespace Org.BouncyCastle.Cms { - /** - * the RecipientInfo class for a recipient who has been sent a message - * encrypted using key agreement. - */ - public class KeyAgreeRecipientInformation - : RecipientInformation - { - private KeyAgreeRecipientInfo info; - private Asn1OctetString encryptedKey; - - internal static void ReadRecipientInfo(IList infos, KeyAgreeRecipientInfo info, - CmsSecureReadable secureReadable) - { - try - { - foreach (Asn1Encodable rek in info.RecipientEncryptedKeys) - { - RecipientEncryptedKey id = RecipientEncryptedKey.GetInstance(rek.ToAsn1Object()); - - RecipientID rid = new RecipientID(); - - Asn1.Cms.KeyAgreeRecipientIdentifier karid = id.Identifier; - - Asn1.Cms.IssuerAndSerialNumber iAndSN = karid.IssuerAndSerialNumber; - if (iAndSN != null) - { - rid.Issuer = iAndSN.Name; - rid.SerialNumber = iAndSN.SerialNumber.Value; - } - else - { - Asn1.Cms.RecipientKeyIdentifier rKeyID = karid.RKeyID; - - // Note: 'date' and 'other' fields of RecipientKeyIdentifier appear to be only informational - - rid.SubjectKeyIdentifier = rKeyID.SubjectKeyIdentifier.GetOctets(); - } - - infos.Add(new KeyAgreeRecipientInformation(info, rid, id.EncryptedKey, - secureReadable)); - } - } - catch (IOException e) - { - throw new ArgumentException("invalid rid in KeyAgreeRecipientInformation", e); - } - } - - internal KeyAgreeRecipientInformation( - KeyAgreeRecipientInfo info, - RecipientID rid, - Asn1OctetString encryptedKey, - CmsSecureReadable secureReadable) - : base(info.KeyEncryptionAlgorithm, secureReadable) - { - this.info = info; - this.rid = rid; - this.encryptedKey = encryptedKey; - } - - private AsymmetricKeyParameter GetSenderPublicKey( - AsymmetricKeyParameter receiverPrivateKey, - OriginatorIdentifierOrKey originator) - { - OriginatorPublicKey opk = originator.OriginatorPublicKey; - if (opk != null) - { - return GetPublicKeyFromOriginatorPublicKey(receiverPrivateKey, opk); - } - - OriginatorID origID = new OriginatorID(); - - Asn1.Cms.IssuerAndSerialNumber iAndSN = originator.IssuerAndSerialNumber; - if (iAndSN != null) - { - origID.Issuer = iAndSN.Name; - origID.SerialNumber = iAndSN.SerialNumber.Value; - } - else - { - SubjectKeyIdentifier ski = originator.SubjectKeyIdentifier; - - origID.SubjectKeyIdentifier = ski.GetKeyIdentifier(); - } - - return GetPublicKeyFromOriginatorID(origID); - } - - private AsymmetricKeyParameter GetPublicKeyFromOriginatorPublicKey( - AsymmetricKeyParameter receiverPrivateKey, - OriginatorPublicKey originatorPublicKey) - { - PrivateKeyInfo privInfo = PrivateKeyInfoFactory.CreatePrivateKeyInfo(receiverPrivateKey); - SubjectPublicKeyInfo pubInfo = new SubjectPublicKeyInfo( - privInfo.AlgorithmID, - originatorPublicKey.PublicKey.GetBytes()); - return PublicKeyFactory.CreateKey(pubInfo); - } - - private AsymmetricKeyParameter GetPublicKeyFromOriginatorID( - OriginatorID origID) - { - // TODO Support all alternatives for OriginatorIdentifierOrKey - // see RFC 3852 6.2.2 - throw new CmsException("No support for 'originator' as IssuerAndSerialNumber or SubjectKeyIdentifier"); - } - - private KeyParameter CalculateAgreedWrapKey( - string wrapAlg, - AsymmetricKeyParameter senderPublicKey, - AsymmetricKeyParameter receiverPrivateKey) - { - DerObjectIdentifier agreeAlgID = keyEncAlg.ObjectID; - - ICipherParameters senderPublicParams = senderPublicKey; - ICipherParameters receiverPrivateParams = receiverPrivateKey; - - if (agreeAlgID.Id.Equals(CmsEnvelopedGenerator.ECMqvSha1Kdf)) - { - byte[] ukmEncoding = info.UserKeyingMaterial.GetOctets(); - MQVuserKeyingMaterial ukm = MQVuserKeyingMaterial.GetInstance( - Asn1Object.FromByteArray(ukmEncoding)); - - AsymmetricKeyParameter ephemeralKey = GetPublicKeyFromOriginatorPublicKey( - receiverPrivateKey, ukm.EphemeralPublicKey); - - senderPublicParams = new MqvPublicParameters( - (ECPublicKeyParameters)senderPublicParams, - (ECPublicKeyParameters)ephemeralKey); - receiverPrivateParams = new MqvPrivateParameters( - (ECPrivateKeyParameters)receiverPrivateParams, - (ECPrivateKeyParameters)receiverPrivateParams); - } - - IBasicAgreement agreement = AgreementUtilities.GetBasicAgreementWithKdf( - agreeAlgID, wrapAlg); - agreement.Init(receiverPrivateParams); - BigInteger agreedValue = agreement.CalculateAgreement(senderPublicParams); - - int wrapKeySize = GeneratorUtilities.GetDefaultKeySize(wrapAlg) / 8; - byte[] wrapKeyBytes = X9IntegerConverter.IntegerToBytes(agreedValue, wrapKeySize); - return ParameterUtilities.CreateKeyParameter(wrapAlg, wrapKeyBytes); - } - - private KeyParameter UnwrapSessionKey( - string wrapAlg, - KeyParameter agreedKey) - { - byte[] encKeyOctets = encryptedKey.GetOctets(); - - IWrapper keyCipher = WrapperUtilities.GetWrapper(wrapAlg); - keyCipher.Init(false, agreedKey); - byte[] sKeyBytes = keyCipher.Unwrap(encKeyOctets, 0, encKeyOctets.Length); - return ParameterUtilities.CreateKeyParameter(GetContentAlgorithmName(), sKeyBytes); - } - - internal KeyParameter GetSessionKey( - AsymmetricKeyParameter receiverPrivateKey) - { - try - { - string wrapAlg = DerObjectIdentifier.GetInstance( - Asn1Sequence.GetInstance(keyEncAlg.Parameters)[0]).Id; - - AsymmetricKeyParameter senderPublicKey = GetSenderPublicKey( - receiverPrivateKey, info.Originator); - - KeyParameter agreedWrapKey = CalculateAgreedWrapKey(wrapAlg, - senderPublicKey, receiverPrivateKey); - - return UnwrapSessionKey(wrapAlg, agreedWrapKey); - } - catch (SecurityUtilityException e) - { - throw new CmsException("couldn't create cipher.", e); - } - catch (InvalidKeyException e) - { - throw new CmsException("key invalid in message.", e); - } - catch (Exception e) - { - throw new CmsException("originator key invalid.", e); - } - } - - /** - * decrypt the content and return an input stream. - */ - public override CmsTypedStream GetContentStream( - ICipherParameters key) - { - if (!(key is AsymmetricKeyParameter)) - throw new ArgumentException("KeyAgreement requires asymmetric key", "key"); - - AsymmetricKeyParameter receiverPrivateKey = (AsymmetricKeyParameter) key; - - if (!receiverPrivateKey.IsPrivate) - throw new ArgumentException("Expected private key", "key"); - - KeyParameter sKey = GetSessionKey(receiverPrivateKey); - - return GetContentFromSessionKey(sKey); - } - } + /** + * the RecipientInfo class for a recipient who has been sent a message + * encrypted using key agreement. + */ + public class KeyAgreeRecipientInformation + : RecipientInformation + { + private KeyAgreeRecipientInfo info; + private Asn1OctetString encryptedKey; + + internal static void ReadRecipientInfo(IList infos, KeyAgreeRecipientInfo info, + CmsSecureReadable secureReadable) + { + try + { + foreach (Asn1Encodable rek in info.RecipientEncryptedKeys) + { + RecipientEncryptedKey id = RecipientEncryptedKey.GetInstance(rek.ToAsn1Object()); + + RecipientID rid = new RecipientID(); + + Asn1.Cms.KeyAgreeRecipientIdentifier karid = id.Identifier; + + Asn1.Cms.IssuerAndSerialNumber iAndSN = karid.IssuerAndSerialNumber; + if (iAndSN != null) + { + rid.Issuer = iAndSN.Name; + rid.SerialNumber = iAndSN.SerialNumber.Value; + } + else + { + Asn1.Cms.RecipientKeyIdentifier rKeyID = karid.RKeyID; + + // Note: 'date' and 'other' fields of RecipientKeyIdentifier appear to be only informational + + rid.SubjectKeyIdentifier = rKeyID.SubjectKeyIdentifier.GetOctets(); + } + + infos.Add(new KeyAgreeRecipientInformation(info, rid, id.EncryptedKey, + secureReadable)); + } + } + catch (IOException e) + { + throw new ArgumentException("invalid rid in KeyAgreeRecipientInformation", e); + } + } + + internal KeyAgreeRecipientInformation( + KeyAgreeRecipientInfo info, + RecipientID rid, + Asn1OctetString encryptedKey, + CmsSecureReadable secureReadable) + : base(info.KeyEncryptionAlgorithm, secureReadable) + { + this.info = info; + this.rid = rid; + this.encryptedKey = encryptedKey; + } + + private AsymmetricKeyParameter GetSenderPublicKey( + AsymmetricKeyParameter receiverPrivateKey, + OriginatorIdentifierOrKey originator) + { + OriginatorPublicKey opk = originator.OriginatorPublicKey; + if (opk != null) + { + return GetPublicKeyFromOriginatorPublicKey(receiverPrivateKey, opk); + } + + OriginatorID origID = new OriginatorID(); + + Asn1.Cms.IssuerAndSerialNumber iAndSN = originator.IssuerAndSerialNumber; + if (iAndSN != null) + { + origID.Issuer = iAndSN.Name; + origID.SerialNumber = iAndSN.SerialNumber.Value; + } + else + { + SubjectKeyIdentifier ski = originator.SubjectKeyIdentifier; + + origID.SubjectKeyIdentifier = ski.GetKeyIdentifier(); + } + + return GetPublicKeyFromOriginatorID(origID); + } + + private AsymmetricKeyParameter GetPublicKeyFromOriginatorPublicKey( + AsymmetricKeyParameter receiverPrivateKey, + OriginatorPublicKey originatorPublicKey) + { + PrivateKeyInfo privInfo = PrivateKeyInfoFactory.CreatePrivateKeyInfo(receiverPrivateKey); + SubjectPublicKeyInfo pubInfo = new SubjectPublicKeyInfo( + privInfo.PrivateKeyAlgorithm, + originatorPublicKey.PublicKey.GetBytes()); + return PublicKeyFactory.CreateKey(pubInfo); + } + + private AsymmetricKeyParameter GetPublicKeyFromOriginatorID( + OriginatorID origID) + { + // TODO Support all alternatives for OriginatorIdentifierOrKey + // see RFC 3852 6.2.2 + throw new CmsException("No support for 'originator' as IssuerAndSerialNumber or SubjectKeyIdentifier"); + } + + private KeyParameter CalculateAgreedWrapKey( + string wrapAlg, + AsymmetricKeyParameter senderPublicKey, + AsymmetricKeyParameter receiverPrivateKey) + { + DerObjectIdentifier agreeAlgID = keyEncAlg.ObjectID; + + ICipherParameters senderPublicParams = senderPublicKey; + ICipherParameters receiverPrivateParams = receiverPrivateKey; + + if (agreeAlgID.Id.Equals(CmsEnvelopedGenerator.ECMqvSha1Kdf)) + { + byte[] ukmEncoding = info.UserKeyingMaterial.GetOctets(); + MQVuserKeyingMaterial ukm = MQVuserKeyingMaterial.GetInstance( + Asn1Object.FromByteArray(ukmEncoding)); + + AsymmetricKeyParameter ephemeralKey = GetPublicKeyFromOriginatorPublicKey( + receiverPrivateKey, ukm.EphemeralPublicKey); + + senderPublicParams = new MqvPublicParameters( + (ECPublicKeyParameters)senderPublicParams, + (ECPublicKeyParameters)ephemeralKey); + receiverPrivateParams = new MqvPrivateParameters( + (ECPrivateKeyParameters)receiverPrivateParams, + (ECPrivateKeyParameters)receiverPrivateParams); + } + + IBasicAgreement agreement = AgreementUtilities.GetBasicAgreementWithKdf( + agreeAlgID, wrapAlg); + agreement.Init(receiverPrivateParams); + BigInteger agreedValue = agreement.CalculateAgreement(senderPublicParams); + + int wrapKeySize = GeneratorUtilities.GetDefaultKeySize(wrapAlg) / 8; + byte[] wrapKeyBytes = X9IntegerConverter.IntegerToBytes(agreedValue, wrapKeySize); + return ParameterUtilities.CreateKeyParameter(wrapAlg, wrapKeyBytes); + } + + private KeyParameter UnwrapSessionKey( + string wrapAlg, + KeyParameter agreedKey) + { + byte[] encKeyOctets = encryptedKey.GetOctets(); + + IWrapper keyCipher = WrapperUtilities.GetWrapper(wrapAlg); + keyCipher.Init(false, agreedKey); + byte[] sKeyBytes = keyCipher.Unwrap(encKeyOctets, 0, encKeyOctets.Length); + return ParameterUtilities.CreateKeyParameter(GetContentAlgorithmName(), sKeyBytes); + } + + internal KeyParameter GetSessionKey( + AsymmetricKeyParameter receiverPrivateKey) + { + try + { + string wrapAlg = DerObjectIdentifier.GetInstance( + Asn1Sequence.GetInstance(keyEncAlg.Parameters)[0]).Id; + + AsymmetricKeyParameter senderPublicKey = GetSenderPublicKey( + receiverPrivateKey, info.Originator); + + KeyParameter agreedWrapKey = CalculateAgreedWrapKey(wrapAlg, + senderPublicKey, receiverPrivateKey); + + return UnwrapSessionKey(wrapAlg, agreedWrapKey); + } + catch (SecurityUtilityException e) + { + throw new CmsException("couldn't create cipher.", e); + } + catch (InvalidKeyException e) + { + throw new CmsException("key invalid in message.", e); + } + catch (Exception e) + { + throw new CmsException("originator key invalid.", e); + } + } + + /** + * decrypt the content and return an input stream. + */ + public override CmsTypedStream GetContentStream( + ICipherParameters key) + { + if (!(key is AsymmetricKeyParameter)) + throw new ArgumentException("KeyAgreement requires asymmetric key", "key"); + + AsymmetricKeyParameter receiverPrivateKey = (AsymmetricKeyParameter) key; + + if (!receiverPrivateKey.IsPrivate) + throw new ArgumentException("Expected private key", "key"); + + KeyParameter sKey = GetSessionKey(receiverPrivateKey); + + return GetContentFromSessionKey(sKey); + } + } } diff --git a/crypto/src/openssl/MiscPemGenerator.cs b/crypto/src/openssl/MiscPemGenerator.cs index c4c537904..6b91e8b1c 100644 --- a/crypto/src/openssl/MiscPemGenerator.cs +++ b/crypto/src/openssl/MiscPemGenerator.cs @@ -21,117 +21,117 @@ using Org.BouncyCastle.X509; namespace Org.BouncyCastle.OpenSsl { - /** - * PEM generator for the original set of PEM objects used in Open SSL. - */ - public class MiscPemGenerator - : PemObjectGenerator - { - private object obj; - private string algorithm; - private char[] password; - private SecureRandom random; - - public MiscPemGenerator(object obj) - { - this.obj = obj; - } - - public MiscPemGenerator( - object obj, - string algorithm, - char[] password, - SecureRandom random) - { - this.obj = obj; - this.algorithm = algorithm; - this.password = password; - this.random = random; - } - - private static PemObject CreatePemObject(object obj) - { - if (obj == null) - throw new ArgumentNullException("obj"); - - if (obj is AsymmetricCipherKeyPair) - { - return CreatePemObject(((AsymmetricCipherKeyPair)obj).Private); - } - - string type; - byte[] encoding; - - if (obj is PemObject) - return (PemObject)obj; - - if (obj is PemObjectGenerator) - return ((PemObjectGenerator)obj).Generate(); - - if (obj is X509Certificate) - { - // TODO Should we prefer "X509 CERTIFICATE" here? - type = "CERTIFICATE"; - try - { - encoding = ((X509Certificate)obj).GetEncoded(); - } - catch (CertificateEncodingException e) - { - throw new IOException("Cannot Encode object: " + e.ToString()); - } - } - else if (obj is X509Crl) - { - type = "X509 CRL"; - try - { - encoding = ((X509Crl)obj).GetEncoded(); - } - catch (CrlException e) - { - throw new IOException("Cannot Encode object: " + e.ToString()); - } - } - else if (obj is AsymmetricKeyParameter) - { - AsymmetricKeyParameter akp = (AsymmetricKeyParameter) obj; - if (akp.IsPrivate) - { - string keyType; - encoding = EncodePrivateKey(akp, out keyType); - - type = keyType + " PRIVATE KEY"; - } - else - { - type = "PUBLIC KEY"; - - encoding = SubjectPublicKeyInfoFactory.CreateSubjectPublicKeyInfo(akp).GetDerEncoded(); - } - } - else if (obj is IX509AttributeCertificate) - { - type = "ATTRIBUTE CERTIFICATE"; - encoding = ((X509V2AttributeCertificate)obj).GetEncoded(); - } - else if (obj is Pkcs10CertificationRequest) - { - type = "CERTIFICATE REQUEST"; - encoding = ((Pkcs10CertificationRequest)obj).GetEncoded(); - } - else if (obj is Asn1.Cms.ContentInfo) - { - type = "PKCS7"; - encoding = ((Asn1.Cms.ContentInfo)obj).GetEncoded(); - } - else - { - throw new PemGenerationException("Object type not supported: " + obj.GetType().FullName); - } - - return new PemObject(type, encoding); - } + /** + * PEM generator for the original set of PEM objects used in Open SSL. + */ + public class MiscPemGenerator + : PemObjectGenerator + { + private object obj; + private string algorithm; + private char[] password; + private SecureRandom random; + + public MiscPemGenerator(object obj) + { + this.obj = obj; + } + + public MiscPemGenerator( + object obj, + string algorithm, + char[] password, + SecureRandom random) + { + this.obj = obj; + this.algorithm = algorithm; + this.password = password; + this.random = random; + } + + private static PemObject CreatePemObject(object obj) + { + if (obj == null) + throw new ArgumentNullException("obj"); + + if (obj is AsymmetricCipherKeyPair) + { + return CreatePemObject(((AsymmetricCipherKeyPair)obj).Private); + } + + string type; + byte[] encoding; + + if (obj is PemObject) + return (PemObject)obj; + + if (obj is PemObjectGenerator) + return ((PemObjectGenerator)obj).Generate(); + + if (obj is X509Certificate) + { + // TODO Should we prefer "X509 CERTIFICATE" here? + type = "CERTIFICATE"; + try + { + encoding = ((X509Certificate)obj).GetEncoded(); + } + catch (CertificateEncodingException e) + { + throw new IOException("Cannot Encode object: " + e.ToString()); + } + } + else if (obj is X509Crl) + { + type = "X509 CRL"; + try + { + encoding = ((X509Crl)obj).GetEncoded(); + } + catch (CrlException e) + { + throw new IOException("Cannot Encode object: " + e.ToString()); + } + } + else if (obj is AsymmetricKeyParameter) + { + AsymmetricKeyParameter akp = (AsymmetricKeyParameter) obj; + if (akp.IsPrivate) + { + string keyType; + encoding = EncodePrivateKey(akp, out keyType); + + type = keyType + " PRIVATE KEY"; + } + else + { + type = "PUBLIC KEY"; + + encoding = SubjectPublicKeyInfoFactory.CreateSubjectPublicKeyInfo(akp).GetDerEncoded(); + } + } + else if (obj is IX509AttributeCertificate) + { + type = "ATTRIBUTE CERTIFICATE"; + encoding = ((X509V2AttributeCertificate)obj).GetEncoded(); + } + else if (obj is Pkcs10CertificationRequest) + { + type = "CERTIFICATE REQUEST"; + encoding = ((Pkcs10CertificationRequest)obj).GetEncoded(); + } + else if (obj is Asn1.Cms.ContentInfo) + { + type = "PKCS7"; + encoding = ((Asn1.Cms.ContentInfo)obj).GetEncoded(); + } + else + { + throw new PemGenerationException("Object type not supported: " + obj.GetType().FullName); + } + + return new PemObject(type, encoding); + } // private string GetHexEncoded(byte[] bytes) // { @@ -147,130 +147,130 @@ namespace Org.BouncyCastle.OpenSsl // return new string(chars); // } - private static PemObject CreatePemObject( - object obj, - string algorithm, - char[] password, - SecureRandom random) - { - if (obj == null) - throw new ArgumentNullException("obj"); - if (algorithm == null) - throw new ArgumentNullException("algorithm"); - if (password == null) - throw new ArgumentNullException("password"); - if (random == null) - throw new ArgumentNullException("random"); - - if (obj is AsymmetricCipherKeyPair) - { - return CreatePemObject(((AsymmetricCipherKeyPair)obj).Private, algorithm, password, random); - } - - string type = null; - byte[] keyData = null; - - if (obj is AsymmetricKeyParameter) - { - AsymmetricKeyParameter akp = (AsymmetricKeyParameter) obj; - if (akp.IsPrivate) - { - string keyType; - keyData = EncodePrivateKey(akp, out keyType); - - type = keyType + " PRIVATE KEY"; - } - } - - if (type == null || keyData == null) - { - // TODO Support other types? - throw new PemGenerationException("Object type not supported: " + obj.GetType().FullName); - } - - - string dekAlgName = Platform.ToUpperInvariant(algorithm); + private static PemObject CreatePemObject( + object obj, + string algorithm, + char[] password, + SecureRandom random) + { + if (obj == null) + throw new ArgumentNullException("obj"); + if (algorithm == null) + throw new ArgumentNullException("algorithm"); + if (password == null) + throw new ArgumentNullException("password"); + if (random == null) + throw new ArgumentNullException("random"); + + if (obj is AsymmetricCipherKeyPair) + { + return CreatePemObject(((AsymmetricCipherKeyPair)obj).Private, algorithm, password, random); + } + + string type = null; + byte[] keyData = null; + + if (obj is AsymmetricKeyParameter) + { + AsymmetricKeyParameter akp = (AsymmetricKeyParameter) obj; + if (akp.IsPrivate) + { + string keyType; + keyData = EncodePrivateKey(akp, out keyType); + + type = keyType + " PRIVATE KEY"; + } + } + + if (type == null || keyData == null) + { + // TODO Support other types? + throw new PemGenerationException("Object type not supported: " + obj.GetType().FullName); + } + + + string dekAlgName = Platform.ToUpperInvariant(algorithm); // Note: For backward compatibility - if (dekAlgName == "DESEDE") - { - dekAlgName = "DES-EDE3-CBC"; - } - - int ivLength = dekAlgName.StartsWith("AES-") ? 16 : 8; - - byte[] iv = new byte[ivLength]; - random.NextBytes(iv); - - byte[] encData = PemUtilities.Crypt(true, keyData, password, dekAlgName, iv); - - IList headers = Platform.CreateArrayList(2); - - headers.Add(new PemHeader("Proc-Type", "4,ENCRYPTED")); - headers.Add(new PemHeader("DEK-Info", dekAlgName + "," + Hex.ToHexString(iv))); - - return new PemObject(type, headers, encData); - } - - private static byte[] EncodePrivateKey( - AsymmetricKeyParameter akp, - out string keyType) - { - PrivateKeyInfo info = PrivateKeyInfoFactory.CreatePrivateKeyInfo(akp); - - DerObjectIdentifier oid = info.AlgorithmID.ObjectID; - - if (oid.Equals(X9ObjectIdentifiers.IdDsa)) - { - keyType = "DSA"; - - DsaParameter p = DsaParameter.GetInstance(info.AlgorithmID.Parameters); - - BigInteger x = ((DsaPrivateKeyParameters) akp).X; - BigInteger y = p.G.ModPow(x, p.P); - - // TODO Create an ASN1 object somewhere for this? - return new DerSequence( - new DerInteger(0), - new DerInteger(p.P), - new DerInteger(p.Q), - new DerInteger(p.G), - new DerInteger(y), - new DerInteger(x)).GetEncoded(); - } - - if (oid.Equals(PkcsObjectIdentifiers.RsaEncryption)) - { - keyType = "RSA"; - } - else if (oid.Equals(CryptoProObjectIdentifiers.GostR3410x2001) - || oid.Equals(X9ObjectIdentifiers.IdECPublicKey)) - { - keyType = "EC"; - } - else - { - throw new ArgumentException("Cannot handle private key of type: " + akp.GetType().FullName, "akp"); - } - - return info.PrivateKey.GetEncoded(); - } - - public PemObject Generate() - { - try - { - if (algorithm != null) - { - return CreatePemObject(obj, algorithm, password, random); - } - - return CreatePemObject(obj); - } - catch (IOException e) - { - throw new PemGenerationException("encoding exception", e); - } - } - } + if (dekAlgName == "DESEDE") + { + dekAlgName = "DES-EDE3-CBC"; + } + + int ivLength = dekAlgName.StartsWith("AES-") ? 16 : 8; + + byte[] iv = new byte[ivLength]; + random.NextBytes(iv); + + byte[] encData = PemUtilities.Crypt(true, keyData, password, dekAlgName, iv); + + IList headers = Platform.CreateArrayList(2); + + headers.Add(new PemHeader("Proc-Type", "4,ENCRYPTED")); + headers.Add(new PemHeader("DEK-Info", dekAlgName + "," + Hex.ToHexString(iv))); + + return new PemObject(type, headers, encData); + } + + private static byte[] EncodePrivateKey( + AsymmetricKeyParameter akp, + out string keyType) + { + PrivateKeyInfo info = PrivateKeyInfoFactory.CreatePrivateKeyInfo(akp); + AlgorithmIdentifier algID = info.PrivateKeyAlgorithm; + DerObjectIdentifier oid = algID.ObjectID; + + if (oid.Equals(X9ObjectIdentifiers.IdDsa)) + { + keyType = "DSA"; + + DsaParameter p = DsaParameter.GetInstance(algID.Parameters); + + BigInteger x = ((DsaPrivateKeyParameters) akp).X; + BigInteger y = p.G.ModPow(x, p.P); + + // TODO Create an ASN1 object somewhere for this? + return new DerSequence( + new DerInteger(0), + new DerInteger(p.P), + new DerInteger(p.Q), + new DerInteger(p.G), + new DerInteger(y), + new DerInteger(x)).GetEncoded(); + } + + if (oid.Equals(PkcsObjectIdentifiers.RsaEncryption)) + { + keyType = "RSA"; + } + else if (oid.Equals(CryptoProObjectIdentifiers.GostR3410x2001) + || oid.Equals(X9ObjectIdentifiers.IdECPublicKey)) + { + keyType = "EC"; + } + else + { + throw new ArgumentException("Cannot handle private key of type: " + akp.GetType().FullName, "akp"); + } + + return info.ParsePrivateKey().GetEncoded(); + } + + public PemObject Generate() + { + try + { + if (algorithm != null) + { + return CreatePemObject(obj, algorithm, password, random); + } + + return CreatePemObject(obj); + } + catch (IOException e) + { + throw new PemGenerationException("encoding exception", e); + } + } + } } diff --git a/crypto/src/security/PrivateKeyFactory.cs b/crypto/src/security/PrivateKeyFactory.cs index c5ddd5d78..c346352f5 100644 --- a/crypto/src/security/PrivateKeyFactory.cs +++ b/crypto/src/security/PrivateKeyFactory.cs @@ -43,7 +43,7 @@ namespace Org.BouncyCastle.Security public static AsymmetricKeyParameter CreateKey( PrivateKeyInfo keyInfo) { - AlgorithmIdentifier algID = keyInfo.AlgorithmID; + AlgorithmIdentifier algID = keyInfo.PrivateKeyAlgorithm; DerObjectIdentifier algOid = algID.ObjectID; // TODO See RSAUtil.isRsaOid in Java build @@ -53,7 +53,7 @@ namespace Org.BouncyCastle.Security || algOid.Equals(PkcsObjectIdentifiers.IdRsaesOaep)) { RsaPrivateKeyStructure keyStructure = new RsaPrivateKeyStructure( - Asn1Sequence.GetInstance(keyInfo.PrivateKey)); + Asn1Sequence.GetInstance(keyInfo.ParsePrivateKey())); return new RsaPrivateCrtKeyParameters( keyStructure.Modulus, @@ -71,7 +71,7 @@ namespace Org.BouncyCastle.Security { DHParameter para = new DHParameter( Asn1Sequence.GetInstance(algID.Parameters.ToAsn1Object())); - DerInteger derX = (DerInteger)keyInfo.PrivateKey; + DerInteger derX = (DerInteger)keyInfo.ParsePrivateKey(); BigInteger lVal = para.L; int l = lVal == null ? 0 : lVal.IntValue; @@ -83,7 +83,7 @@ namespace Org.BouncyCastle.Security { ElGamalParameter para = new ElGamalParameter( Asn1Sequence.GetInstance(algID.Parameters.ToAsn1Object())); - DerInteger derX = (DerInteger)keyInfo.PrivateKey; + DerInteger derX = (DerInteger)keyInfo.ParsePrivateKey(); return new ElGamalPrivateKeyParameters( derX.Value, @@ -91,7 +91,7 @@ namespace Org.BouncyCastle.Security } else if (algOid.Equals(X9ObjectIdentifiers.IdDsa)) { - DerInteger derX = (DerInteger) keyInfo.PrivateKey; + DerInteger derX = (DerInteger)keyInfo.ParsePrivateKey(); Asn1Encodable ae = algID.Parameters; DsaParameters parameters = null; @@ -118,7 +118,7 @@ namespace Org.BouncyCastle.Security } ECPrivateKeyStructure ec = new ECPrivateKeyStructure( - Asn1Sequence.GetInstance(keyInfo.PrivateKey)); + Asn1Sequence.GetInstance(keyInfo.ParsePrivateKey())); BigInteger d = ec.GetKey(); if (para.IsNamedCurve) @@ -135,7 +135,7 @@ namespace Org.BouncyCastle.Security Asn1Sequence.GetInstance(algID.Parameters.ToAsn1Object())); ECPrivateKeyStructure ec = new ECPrivateKeyStructure( - Asn1Sequence.GetInstance(keyInfo.PrivateKey)); + Asn1Sequence.GetInstance(keyInfo.ParsePrivateKey())); ECDomainParameters ecP = ECGost3410NamedCurves.GetByOid(gostParams.PublicKeyParamSet); @@ -149,7 +149,7 @@ namespace Org.BouncyCastle.Security Gost3410PublicKeyAlgParameters gostParams = new Gost3410PublicKeyAlgParameters( Asn1Sequence.GetInstance(algID.Parameters.ToAsn1Object())); - DerOctetString derX = (DerOctetString) keyInfo.PrivateKey; + DerOctetString derX = (DerOctetString)keyInfo.ParsePrivateKey(); byte[] keyEnc = derX.GetOctets(); byte[] keyBytes = new byte[keyEnc.Length]; |