diff --git a/crypto/src/openssl/PEMReader.cs b/crypto/src/openssl/PEMReader.cs
index a2fedab96..b3a1177ce 100644
--- a/crypto/src/openssl/PEMReader.cs
+++ b/crypto/src/openssl/PEMReader.cs
@@ -23,20 +23,20 @@ using Org.BouncyCastle.X509;
namespace Org.BouncyCastle.OpenSsl
{
- /**
- * Class for reading OpenSSL PEM encoded streams containing
- * X509 certificates, PKCS8 encoded keys and PKCS7 objects.
- * <p>
- * In the case of PKCS7 objects the reader will return a CMS ContentInfo object. Keys and
- * Certificates will be returned using the appropriate java.security type.</p>
- */
- public class PemReader
- : Org.BouncyCastle.Utilities.IO.Pem.PemReader
- {
+ /**
+ * Class for reading OpenSSL PEM encoded streams containing
+ * X509 certificates, PKCS8 encoded keys and PKCS7 objects.
+ * <p>
+ * In the case of PKCS7 objects the reader will return a CMS ContentInfo object. Keys and
+ * Certificates will be returned using the appropriate java.security type.</p>
+ */
+ public class PemReader
+ : Org.BouncyCastle.Utilities.IO.Pem.PemReader
+ {
// private static readonly IDictionary parsers = new Hashtable();
- static PemReader()
- {
+ static PemReader()
+ {
// parsers.Add("CERTIFICATE REQUEST", new PKCS10CertificationRequestParser());
// parsers.Add("NEW CERTIFICATE REQUEST", new PKCS10CertificationRequestParser());
// parsers.Add("CERTIFICATE", new X509CertificateParser(provider));
@@ -52,323 +52,323 @@ namespace Org.BouncyCastle.OpenSsl
// parsers.Add("EC PRIVATE KEY", new ECDSAKeyPairParser(provider));
// parsers.Add("ENCRYPTED PRIVATE KEY", new EncryptedPrivateKeyParser(provider));
// parsers.Add("PRIVATE KEY", new PrivateKeyParser(provider));
- }
-
- private readonly IPasswordFinder pFinder;
-
- /**
- * Create a new PemReader
- *
- * @param reader the Reader
- */
- public PemReader(
- TextReader reader)
- : this(reader, null)
- {
- }
-
- /**
- * Create a new PemReader with a password finder
- *
- * @param reader the Reader
- * @param pFinder the password finder
- */
- public PemReader(
- TextReader reader,
- IPasswordFinder pFinder)
- : base(reader)
- {
- this.pFinder = pFinder;
- }
-
- public object ReadObject()
- {
- PemObject obj = ReadPemObject();
-
- if (obj == null)
- return null;
-
- // TODO Follow Java build and map to parser objects?
+ }
+
+ private readonly IPasswordFinder pFinder;
+
+ /**
+ * Create a new PemReader
+ *
+ * @param reader the Reader
+ */
+ public PemReader(
+ TextReader reader)
+ : this(reader, null)
+ {
+ }
+
+ /**
+ * Create a new PemReader with a password finder
+ *
+ * @param reader the Reader
+ * @param pFinder the password finder
+ */
+ public PemReader(
+ TextReader reader,
+ IPasswordFinder pFinder)
+ : base(reader)
+ {
+ this.pFinder = pFinder;
+ }
+
+ public object ReadObject()
+ {
+ PemObject obj = ReadPemObject();
+
+ if (obj == null)
+ return null;
+
+ // TODO Follow Java build and map to parser objects?
// if (parsers.Contains(obj.Type))
// return ((PemObjectParser)parsers[obj.Type]).ParseObject(obj);
- if (obj.Type.EndsWith("PRIVATE KEY"))
- return ReadPrivateKey(obj);
-
- switch (obj.Type)
- {
- case "PUBLIC KEY":
- return ReadPublicKey(obj);
- case "RSA PUBLIC KEY":
- return ReadRsaPublicKey(obj);
- case "CERTIFICATE REQUEST":
- case "NEW CERTIFICATE REQUEST":
- return ReadCertificateRequest(obj);
- case "CERTIFICATE":
- case "X509 CERTIFICATE":
- return ReadCertificate(obj);
- case "PKCS7":
- return ReadPkcs7(obj);
- case "X509 CRL":
- return ReadCrl(obj);
- case "ATTRIBUTE CERTIFICATE":
- return ReadAttributeCertificate(obj);
- // TODO Add back in when tests done, and return type issue resolved
- //case "EC PARAMETERS":
- // return ReadECParameters(obj);
- default:
- throw new IOException("unrecognised object: " + obj.Type);
- }
- }
-
- private AsymmetricKeyParameter ReadRsaPublicKey(PemObject pemObject)
- {
- RsaPublicKeyStructure rsaPubStructure = RsaPublicKeyStructure.GetInstance(
- Asn1Object.FromByteArray(pemObject.Content));
-
- return new RsaKeyParameters(
- false, // not private
- rsaPubStructure.Modulus,
- rsaPubStructure.PublicExponent);
- }
-
- private AsymmetricKeyParameter ReadPublicKey(PemObject pemObject)
- {
- return PublicKeyFactory.CreateKey(pemObject.Content);
- }
-
- /**
- * Reads in a X509Certificate.
- *
- * @return the X509Certificate
- * @throws IOException if an I/O error occured
- */
- private X509Certificate ReadCertificate(PemObject pemObject)
- {
- try
- {
- return new X509CertificateParser().ReadCertificate(pemObject.Content);
- }
- catch (Exception e)
- {
- throw new PemException("problem parsing cert: " + e.ToString());
- }
- }
-
- /**
- * Reads in a X509CRL.
- *
- * @return the X509Certificate
- * @throws IOException if an I/O error occured
- */
- private X509Crl ReadCrl(PemObject pemObject)
- {
- try
- {
- return new X509CrlParser().ReadCrl(pemObject.Content);
- }
- catch (Exception e)
- {
- throw new PemException("problem parsing cert: " + e.ToString());
- }
- }
-
- /**
- * Reads in a PKCS10 certification request.
- *
- * @return the certificate request.
- * @throws IOException if an I/O error occured
- */
- private Pkcs10CertificationRequest ReadCertificateRequest(PemObject pemObject)
- {
- try
- {
- return new Pkcs10CertificationRequest(pemObject.Content);
- }
- catch (Exception e)
- {
- throw new PemException("problem parsing cert: " + e.ToString());
- }
- }
-
- /**
- * Reads in a X509 Attribute Certificate.
- *
- * @return the X509 Attribute Certificate
- * @throws IOException if an I/O error occured
- */
- private IX509AttributeCertificate ReadAttributeCertificate(PemObject pemObject)
- {
- return new X509V2AttributeCertificate(pemObject.Content);
- }
-
- /**
- * Reads in a PKCS7 object. This returns a ContentInfo object suitable for use with the CMS
- * API.
- *
- * @return the X509Certificate
- * @throws IOException if an I/O error occured
- */
- // TODO Consider returning Asn1.Pkcs.ContentInfo
- private Asn1.Cms.ContentInfo ReadPkcs7(PemObject pemObject)
- {
- try
- {
- return Asn1.Cms.ContentInfo.GetInstance(
- Asn1Object.FromByteArray(pemObject.Content));
- }
- catch (Exception e)
- {
- throw new PemException("problem parsing PKCS7 object: " + e.ToString());
- }
- }
-
- /**
- * Read a Key Pair
- */
- private object ReadPrivateKey(PemObject pemObject)
- {
- //
- // extract the key
- //
- Debug.Assert(pemObject.Type.EndsWith("PRIVATE KEY"));
-
- string type = pemObject.Type.Substring(0, pemObject.Type.Length - "PRIVATE KEY".Length).Trim();
- byte[] keyBytes = pemObject.Content;
-
- IDictionary fields = Platform.CreateHashtable();
- foreach (PemHeader header in pemObject.Headers)
- {
- fields[header.Name] = header.Value;
- }
-
- string procType = (string) fields["Proc-Type"];
-
- if (procType == "4,ENCRYPTED")
- {
- if (pFinder == null)
- throw new PasswordException("No password finder specified, but a password is required");
-
- char[] password = pFinder.GetPassword();
-
- if (password == null)
- throw new PasswordException("Password is null, but a password is required");
-
- string dekInfo = (string) fields["DEK-Info"];
- string[] tknz = dekInfo.Split(',');
-
- string dekAlgName = tknz[0].Trim();
- byte[] iv = Hex.Decode(tknz[1].Trim());
-
- keyBytes = PemUtilities.Crypt(false, keyBytes, password, dekAlgName, iv);
- }
-
- try
- {
- AsymmetricKeyParameter pubSpec, privSpec;
- Asn1Sequence seq = (Asn1Sequence) Asn1Object.FromByteArray(keyBytes);
-
- switch (type)
- {
- case "RSA":
- {
- if (seq.Count != 9)
- throw new PemException("malformed sequence in RSA private key");
-
- RsaPrivateKeyStructure rsa = new RsaPrivateKeyStructure(seq);
-
- pubSpec = new RsaKeyParameters(false, rsa.Modulus, rsa.PublicExponent);
- privSpec = new RsaPrivateCrtKeyParameters(
- rsa.Modulus, rsa.PublicExponent, rsa.PrivateExponent,
- rsa.Prime1, rsa.Prime2, rsa.Exponent1, rsa.Exponent2,
- rsa.Coefficient);
-
- break;
- }
-
- case "DSA":
- {
- if (seq.Count != 6)
- throw new PemException("malformed sequence in DSA private key");
-
- // TODO Create an ASN1 object somewhere for this?
- //DerInteger v = (DerInteger)seq[0];
- DerInteger p = (DerInteger)seq[1];
- DerInteger q = (DerInteger)seq[2];
- DerInteger g = (DerInteger)seq[3];
- DerInteger y = (DerInteger)seq[4];
- DerInteger x = (DerInteger)seq[5];
-
- DsaParameters parameters = new DsaParameters(p.Value, q.Value, g.Value);
-
- privSpec = new DsaPrivateKeyParameters(x.Value, parameters);
- pubSpec = new DsaPublicKeyParameters(y.Value, parameters);
-
- break;
- }
-
- case "EC":
- {
- ECPrivateKeyStructure pKey = new ECPrivateKeyStructure(seq);
- AlgorithmIdentifier algId = new AlgorithmIdentifier(
- X9ObjectIdentifiers.IdECPublicKey, pKey.GetParameters());
-
- PrivateKeyInfo privInfo = new PrivateKeyInfo(algId, pKey.ToAsn1Object());
-
- // TODO Are the keys returned here ECDSA, as Java version forces?
- privSpec = PrivateKeyFactory.CreateKey(privInfo);
-
- DerBitString pubKey = pKey.GetPublicKey();
- if (pubKey != null)
- {
- SubjectPublicKeyInfo pubInfo = new SubjectPublicKeyInfo(algId, pubKey.GetBytes());
-
- // TODO Are the keys returned here ECDSA, as Java version forces?
- pubSpec = PublicKeyFactory.CreateKey(pubInfo);
- }
- else
- {
- pubSpec = ECKeyPairGenerator.GetCorrespondingPublicKey(
- (ECPrivateKeyParameters)privSpec);
- }
-
- break;
- }
-
- case "ENCRYPTED":
- {
- char[] password = pFinder.GetPassword();
-
- if (password == null)
- throw new PasswordException("Password is null, but a password is required");
-
- return PrivateKeyFactory.DecryptKey(password, EncryptedPrivateKeyInfo.GetInstance(seq));
- }
-
- case "":
- {
- return PrivateKeyFactory.CreateKey(PrivateKeyInfo.GetInstance(seq));
- }
-
- default:
- throw new ArgumentException("Unknown key type: " + type, "type");
- }
-
- return new AsymmetricCipherKeyPair(pubSpec, privSpec);
- }
- catch (IOException e)
- {
- throw e;
- }
- catch (Exception e)
- {
- throw new PemException(
- "problem creating " + type + " private key: " + e.ToString());
- }
- }
-
- // TODO Add an equivalent class for ECNamedCurveParameterSpec?
- //private ECNamedCurveParameterSpec ReadECParameters(
+ if (obj.Type.EndsWith("PRIVATE KEY"))
+ return ReadPrivateKey(obj);
+
+ switch (obj.Type)
+ {
+ case "PUBLIC KEY":
+ return ReadPublicKey(obj);
+ case "RSA PUBLIC KEY":
+ return ReadRsaPublicKey(obj);
+ case "CERTIFICATE REQUEST":
+ case "NEW CERTIFICATE REQUEST":
+ return ReadCertificateRequest(obj);
+ case "CERTIFICATE":
+ case "X509 CERTIFICATE":
+ return ReadCertificate(obj);
+ case "PKCS7":
+ return ReadPkcs7(obj);
+ case "X509 CRL":
+ return ReadCrl(obj);
+ case "ATTRIBUTE CERTIFICATE":
+ return ReadAttributeCertificate(obj);
+ // TODO Add back in when tests done, and return type issue resolved
+ //case "EC PARAMETERS":
+ // return ReadECParameters(obj);
+ default:
+ throw new IOException("unrecognised object: " + obj.Type);
+ }
+ }
+
+ private AsymmetricKeyParameter ReadRsaPublicKey(PemObject pemObject)
+ {
+ RsaPublicKeyStructure rsaPubStructure = RsaPublicKeyStructure.GetInstance(
+ Asn1Object.FromByteArray(pemObject.Content));
+
+ return new RsaKeyParameters(
+ false, // not private
+ rsaPubStructure.Modulus,
+ rsaPubStructure.PublicExponent);
+ }
+
+ private AsymmetricKeyParameter ReadPublicKey(PemObject pemObject)
+ {
+ return PublicKeyFactory.CreateKey(pemObject.Content);
+ }
+
+ /**
+ * Reads in a X509Certificate.
+ *
+ * @return the X509Certificate
+ * @throws IOException if an I/O error occured
+ */
+ private X509Certificate ReadCertificate(PemObject pemObject)
+ {
+ try
+ {
+ return new X509CertificateParser().ReadCertificate(pemObject.Content);
+ }
+ catch (Exception e)
+ {
+ throw new PemException("problem parsing cert: " + e.ToString());
+ }
+ }
+
+ /**
+ * Reads in a X509CRL.
+ *
+ * @return the X509Certificate
+ * @throws IOException if an I/O error occured
+ */
+ private X509Crl ReadCrl(PemObject pemObject)
+ {
+ try
+ {
+ return new X509CrlParser().ReadCrl(pemObject.Content);
+ }
+ catch (Exception e)
+ {
+ throw new PemException("problem parsing cert: " + e.ToString());
+ }
+ }
+
+ /**
+ * Reads in a PKCS10 certification request.
+ *
+ * @return the certificate request.
+ * @throws IOException if an I/O error occured
+ */
+ private Pkcs10CertificationRequest ReadCertificateRequest(PemObject pemObject)
+ {
+ try
+ {
+ return new Pkcs10CertificationRequest(pemObject.Content);
+ }
+ catch (Exception e)
+ {
+ throw new PemException("problem parsing cert: " + e.ToString());
+ }
+ }
+
+ /**
+ * Reads in a X509 Attribute Certificate.
+ *
+ * @return the X509 Attribute Certificate
+ * @throws IOException if an I/O error occured
+ */
+ private IX509AttributeCertificate ReadAttributeCertificate(PemObject pemObject)
+ {
+ return new X509V2AttributeCertificate(pemObject.Content);
+ }
+
+ /**
+ * Reads in a PKCS7 object. This returns a ContentInfo object suitable for use with the CMS
+ * API.
+ *
+ * @return the X509Certificate
+ * @throws IOException if an I/O error occured
+ */
+ // TODO Consider returning Asn1.Pkcs.ContentInfo
+ private Asn1.Cms.ContentInfo ReadPkcs7(PemObject pemObject)
+ {
+ try
+ {
+ return Asn1.Cms.ContentInfo.GetInstance(
+ Asn1Object.FromByteArray(pemObject.Content));
+ }
+ catch (Exception e)
+ {
+ throw new PemException("problem parsing PKCS7 object: " + e.ToString());
+ }
+ }
+
+ /**
+ * Read a Key Pair
+ */
+ private object ReadPrivateKey(PemObject pemObject)
+ {
+ //
+ // extract the key
+ //
+ Debug.Assert(pemObject.Type.EndsWith("PRIVATE KEY"));
+
+ string type = pemObject.Type.Substring(0, pemObject.Type.Length - "PRIVATE KEY".Length).Trim();
+ byte[] keyBytes = pemObject.Content;
+
+ IDictionary fields = Platform.CreateHashtable();
+ foreach (PemHeader header in pemObject.Headers)
+ {
+ fields[header.Name] = header.Value;
+ }
+
+ string procType = (string) fields["Proc-Type"];
+
+ if (procType == "4,ENCRYPTED")
+ {
+ if (pFinder == null)
+ throw new PasswordException("No password finder specified, but a password is required");
+
+ char[] password = pFinder.GetPassword();
+
+ if (password == null)
+ throw new PasswordException("Password is null, but a password is required");
+
+ string dekInfo = (string) fields["DEK-Info"];
+ string[] tknz = dekInfo.Split(',');
+
+ string dekAlgName = tknz[0].Trim();
+ byte[] iv = Hex.Decode(tknz[1].Trim());
+
+ keyBytes = PemUtilities.Crypt(false, keyBytes, password, dekAlgName, iv);
+ }
+
+ try
+ {
+ AsymmetricKeyParameter pubSpec, privSpec;
+ Asn1Sequence seq = Asn1Sequence.GetInstance(keyBytes);
+
+ switch (type)
+ {
+ case "RSA":
+ {
+ if (seq.Count != 9)
+ throw new PemException("malformed sequence in RSA private key");
+
+ RsaPrivateKeyStructure rsa = new RsaPrivateKeyStructure(seq);
+
+ pubSpec = new RsaKeyParameters(false, rsa.Modulus, rsa.PublicExponent);
+ privSpec = new RsaPrivateCrtKeyParameters(
+ rsa.Modulus, rsa.PublicExponent, rsa.PrivateExponent,
+ rsa.Prime1, rsa.Prime2, rsa.Exponent1, rsa.Exponent2,
+ rsa.Coefficient);
+
+ break;
+ }
+
+ case "DSA":
+ {
+ if (seq.Count != 6)
+ throw new PemException("malformed sequence in DSA private key");
+
+ // TODO Create an ASN1 object somewhere for this?
+ //DerInteger v = (DerInteger)seq[0];
+ DerInteger p = (DerInteger)seq[1];
+ DerInteger q = (DerInteger)seq[2];
+ DerInteger g = (DerInteger)seq[3];
+ DerInteger y = (DerInteger)seq[4];
+ DerInteger x = (DerInteger)seq[5];
+
+ DsaParameters parameters = new DsaParameters(p.Value, q.Value, g.Value);
+
+ privSpec = new DsaPrivateKeyParameters(x.Value, parameters);
+ pubSpec = new DsaPublicKeyParameters(y.Value, parameters);
+
+ break;
+ }
+
+ case "EC":
+ {
+ ECPrivateKeyStructure pKey = new ECPrivateKeyStructure(seq);
+ AlgorithmIdentifier algId = new AlgorithmIdentifier(
+ X9ObjectIdentifiers.IdECPublicKey, pKey.GetParameters());
+
+ PrivateKeyInfo privInfo = new PrivateKeyInfo(algId, pKey.ToAsn1Object());
+
+ // TODO Are the keys returned here ECDSA, as Java version forces?
+ privSpec = PrivateKeyFactory.CreateKey(privInfo);
+
+ DerBitString pubKey = pKey.GetPublicKey();
+ if (pubKey != null)
+ {
+ SubjectPublicKeyInfo pubInfo = new SubjectPublicKeyInfo(algId, pubKey.GetBytes());
+
+ // TODO Are the keys returned here ECDSA, as Java version forces?
+ pubSpec = PublicKeyFactory.CreateKey(pubInfo);
+ }
+ else
+ {
+ pubSpec = ECKeyPairGenerator.GetCorrespondingPublicKey(
+ (ECPrivateKeyParameters)privSpec);
+ }
+
+ break;
+ }
+
+ case "ENCRYPTED":
+ {
+ char[] password = pFinder.GetPassword();
+
+ if (password == null)
+ throw new PasswordException("Password is null, but a password is required");
+
+ return PrivateKeyFactory.DecryptKey(password, EncryptedPrivateKeyInfo.GetInstance(seq));
+ }
+
+ case "":
+ {
+ return PrivateKeyFactory.CreateKey(PrivateKeyInfo.GetInstance(seq));
+ }
+
+ default:
+ throw new ArgumentException("Unknown key type: " + type, "type");
+ }
+
+ return new AsymmetricCipherKeyPair(pubSpec, privSpec);
+ }
+ catch (IOException e)
+ {
+ throw e;
+ }
+ catch (Exception e)
+ {
+ throw new PemException(
+ "problem creating " + type + " private key: " + e.ToString());
+ }
+ }
+
+ // TODO Add an equivalent class for ECNamedCurveParameterSpec?
+ //private ECNamedCurveParameterSpec ReadECParameters(
// private X9ECParameters ReadECParameters(PemObject pemObject)
// {
// DerObjectIdentifier oid = (DerObjectIdentifier)Asn1Object.FromByteArray(pemObject.Content);
@@ -377,31 +377,31 @@ namespace Org.BouncyCastle.OpenSsl
// return GetCurveParameters(oid.Id);
// }
- //private static ECDomainParameters GetCurveParameters(
- private static X9ECParameters GetCurveParameters(
- string name)
- {
- // TODO ECGost3410NamedCurves support (returns ECDomainParameters though)
- X9ECParameters ecP = X962NamedCurves.GetByName(name);
-
- if (ecP == null)
- {
- ecP = SecNamedCurves.GetByName(name);
- if (ecP == null)
- {
- ecP = NistNamedCurves.GetByName(name);
- if (ecP == null)
- {
- ecP = TeleTrusTNamedCurves.GetByName(name);
-
- if (ecP == null)
- throw new Exception("unknown curve name: " + name);
- }
- }
- }
-
- //return new ECDomainParameters(ecP.Curve, ecP.G, ecP.N, ecP.H, ecP.GetSeed());
- return ecP;
- }
- }
+ //private static ECDomainParameters GetCurveParameters(
+ private static X9ECParameters GetCurveParameters(
+ string name)
+ {
+ // TODO ECGost3410NamedCurves support (returns ECDomainParameters though)
+ X9ECParameters ecP = X962NamedCurves.GetByName(name);
+
+ if (ecP == null)
+ {
+ ecP = SecNamedCurves.GetByName(name);
+ if (ecP == null)
+ {
+ ecP = NistNamedCurves.GetByName(name);
+ if (ecP == null)
+ {
+ ecP = TeleTrusTNamedCurves.GetByName(name);
+
+ if (ecP == null)
+ throw new Exception("unknown curve name: " + name);
+ }
+ }
+ }
+
+ //return new ECDomainParameters(ecP.Curve, ecP.G, ecP.N, ecP.H, ecP.GetSeed());
+ return ecP;
+ }
+ }
}
|