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;
}
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());
}
}