/** * Read a Key Pair */ private AsymmetricCipherKeyPair ReadKeyPair( string type, string endMarker) { // // extract the key // IDictionary fields = new Hashtable(); byte[] keyBytes = ReadBytesAndFields(endMarker, fields); 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": { 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": { // 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()); DerBitString pubKey = pKey.GetPublicKey(); //Console.WriteLine(pubKey == null); SubjectPublicKeyInfo pubInfo = new SubjectPublicKeyInfo(algId, pubKey.GetBytes()); // TODO Are the keys returned here ECDSA, as Java version forces? privSpec = PrivateKeyFactory.CreateKey(privInfo); pubSpec = PublicKeyFactory.CreateKey(pubInfo); break; } default: throw new ArgumentException("Unknown key type: " + type, "type"); } return new AsymmetricCipherKeyPair(pubSpec, privSpec); } catch (Exception e) { throw new PemException( "problem creating " + type + " private key: " + 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 { IAsymmetricKeyParameter 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()); } }
private AsymmetricCipherKeyPair ReadECPrivateKey( string endMarker) { try { byte[] bytes = ReadBytes(endMarker); ECPrivateKeyStructure pKey = new ECPrivateKeyStructure( (Asn1Sequence) Asn1Object.FromByteArray(bytes)); AlgorithmIdentifier algId = new AlgorithmIdentifier( X9ObjectIdentifiers.IdECPublicKey, pKey.GetParameters()); PrivateKeyInfo privInfo = new PrivateKeyInfo(algId, pKey.ToAsn1Object()); SubjectPublicKeyInfo pubInfo = new SubjectPublicKeyInfo(algId, pKey.GetPublicKey().GetBytes()); // TODO Are the keys returned here ECDSA, as Java version forces? return new AsymmetricCipherKeyPair( PublicKeyFactory.CreateKey(pubInfo), PrivateKeyFactory.CreateKey(privInfo)); } catch (InvalidCastException e) { throw new IOException("wrong ASN.1 object found in stream.", e); } catch (Exception e) { throw new PemException("problem parsing EC private key.", e); } }