private static IKeyPair ExtractKeyPair(PrivateKeyFileDataReader privateKeySectionReader) { var keyType = privateKeySectionReader.ReadString(Encoding.UTF8); IKeyPair keyPair = null; if (keyType == KeyTypes.ED25519) { var publicKey = privateKeySectionReader.ReadBytes(privateKeySectionReader.ReadInt32()); privateKeySectionReader.ReadInt32(); //length of private + public key var privateKey = privateKeySectionReader.ReadBytes(32); privateKeySectionReader.ReadBytes(32); //public key (again) var comment = privateKeySectionReader.ReadString(Encoding.UTF8); keyPair = new Ed25519KeyPair(comment, publicKey, privateKey); } else if (keyType == KeyTypes.RSA) { var n = privateKeySectionReader.ReadBigInteger(); //Modulus var e = privateKeySectionReader.ReadBigInteger(); //Public Exponent var d = privateKeySectionReader.ReadBigInteger(); //Private Exponent var iqmp = privateKeySectionReader.ReadBigInteger(); //q^-1 mod p var p = privateKeySectionReader.ReadBigInteger(); //Prime 1 var q = privateKeySectionReader.ReadBigInteger(); //Prime 2 var comment = privateKeySectionReader.ReadString(Encoding.UTF8); keyPair = new RsaKeyPair(comment, n, e, d, iqmp, p, q); } else if (keyType == KeyTypes.ECDSA256 || keyType == KeyTypes.ECDSA384 || keyType == KeyTypes.ECDSA521) { int curveLength = privateKeySectionReader.ReadInt32(); var curve = Encoding.ASCII.GetString(privateKeySectionReader.ReadBytes(curveLength)); var publicKey = privateKeySectionReader.ReadBytes(privateKeySectionReader.ReadInt32()); var privateKey = privateKeySectionReader.ReadBytes(privateKeySectionReader.ReadInt32()); var comment = privateKeySectionReader.ReadString(Encoding.UTF8); keyPair = new EcdsaKeyPair(keyType, comment, curve, publicKey, privateKey); } else if (keyType == KeyTypes.DSA) { var p = privateKeySectionReader.ReadBigInteger(); var q = privateKeySectionReader.ReadBigInteger(); var g = privateKeySectionReader.ReadBigInteger(); var y = privateKeySectionReader.ReadBigInteger(); var x = privateKeySectionReader.ReadBigInteger(); var comment = privateKeySectionReader.ReadString(Encoding.UTF8); keyPair = new DsaKeyPair(comment, p, q, g, y, x); } else { throw new OpenSshKeyParseException($"key type '{keyType}' is not supported by this parser"); } return(keyPair); }
public static IKeyPair ParseOpenSshKeyFile(string privateKeyFileText, string passPhrase = null) { ValidPrivateKeyFileText(privateKeyFileText); try { IKeyPair keyPair = null; ValidateHeader(privateKeyFileText); using (var keyFileReader = GetPrivateKeyFileDataReader(privateKeyFileText)) { ValidateMagicHeader(keyFileReader.ReadBytes(AUTH_MAGIC.Length)); var cipherName = keyFileReader.ReadString(Encoding.UTF8); var kdfName = keyFileReader.ReadString(Encoding.UTF8); byte[] salt = null; var rounds = 0; if (keyFileReader.ReadInt32() > 0) //kdf options { salt = keyFileReader.ReadBytes(keyFileReader.ReadInt32()); rounds = keyFileReader.ReadInt32(); } ValidateEncryptionFields(cipherName, kdfName, passPhrase); ValidateNumberOfKeys(keyFileReader.ReadInt32()); keyFileReader.ReadBytes(keyFileReader.ReadInt32()); //skip public key section //we skipped the public key section but for reference, here is what parsing it would look like: /* * using (var publicKeySectionReader = new PrivateKeyFileDataReader(keyFileReader.ReadBytes(keyFileReader.ReadInt32()))) * { * publicKeySectionReader.ReadString(Encoding.UTF8); //key type * publicKeySectionReader.ReadBytes(); //public key, the parts of which will be dependant on the key type * } */ var privateKeySectionBytes = keyFileReader.ReadBytes(keyFileReader.ReadInt32()); if (cipherName != "none") { privateKeySectionBytes = DecryptPrivateKeySection(cipherName, privateKeySectionBytes, salt, rounds, passPhrase); } ValidatePrivateKeySectionLength(privateKeySectionBytes.Length); using (var privateKeySectionReader = new PrivateKeyFileDataReader(privateKeySectionBytes)) { ValidateCheckInts(privateKeySectionReader.ReadInt32(), privateKeySectionReader.ReadInt32()); keyPair = ExtractKeyPair(privateKeySectionReader); ValidatePrivateKeyPadding(privateKeySectionReader.ReadBytes()); } } return(keyPair); } catch (Exception e) { if (e is OpenSshKeyParseException) { throw e; } throw new OpenSshKeyParseException($"unexpected failure parsing key: {e.Message}"); } }