/** * Return the number of bytes or characters required to contain the * passed in object if it is PEM encoded. * * @param obj pem object to be output * @return an estimate of the number of bytes */ public int GetOutputSize(PemObject obj) { // BEGIN and END boundaries. int size = (2 * (obj.Type.Length + 10 + nlLength)) + 6 + 4; if (obj.Headers.Count > 0) { foreach (PemHeader header in obj.Headers) { size += header.Name.Length + ": ".Length + header.Value.Length + nlLength; } size += nlLength; } // base64 encoding int dataLen = ((obj.Content.Length + 2) / 3) * 4; size += dataLen + (((dataLen + LineLength - 1) / LineLength) * nlLength); return size; }
/** * 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()); } }
/** * 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()); } }
/** * 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 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 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()); } }
private AsymmetricKeyParameter ReadPublicKey(PemObject pemObject) { return PublicKeyFactory.CreateKey(pemObject.Content); }
private AsymmetricKeyParameter ReadRsaPublicKey(PemObject pemObject) { RsaPublicKeyStructure rsaPubStructure = RsaPublicKeyStructure.GetInstance( Asn1Object.FromByteArray(pemObject.Content)); return new RsaKeyParameters( false, // not private rsaPubStructure.Modulus, rsaPubStructure.PublicExponent); }