public override object Deserialize(Stream aStream)
{
FileData fileData = new FileData();
/* check for required parameters */
if (aStream == null) {
throw new ArgumentNullException("aStream");
}
string line;
string[] pair = new string[2];
int lineCount, i;
StreamReader reader = new StreamReader(aStream, Encoding.GetEncoding(1252));
char[] delimArray = { cDelimeter };
try {
/* read file version */
line = reader.ReadLine();
pair = line.Split(delimArray, 2);
if (!pair[0].StartsWith(puttyUserKeyFileKey)) {
throw new PpkFormatterException(PpkFormatterException.PpkErrorType.FileFormat,
puttyUserKeyFileKey + " expected");
}
string ppkFileVersion = pair[0].Remove(0, puttyUserKeyFileKey.Length);
if (!ppkFileVersion.TryParseVersion(ref fileData.ppkFileVersion)) {
throw new PpkFormatterException(PpkFormatterException.PpkErrorType.FileVersion);
}
if (fileData.ppkFileVersion == Version.V1) {
if (WarnOldFileFormatCallbackMethod != null) {
WarnOldFileFormatCallbackMethod.Invoke();
}
}
/* read public key encryption algorithm type */
string algorithm = pair[1].Trim();
if (!algorithm.TryParsePublicKeyAlgorithm(ref fileData.publicKeyAlgorithm)) {
throw new PpkFormatterException(PpkFormatterException.PpkErrorType.PublicKeyEncryption);
}
/* read private key encryption algorithm type */
line = reader.ReadLine();
pair = line.Split(delimArray, 2);
if (pair[0] != privateKeyEncryptionKey) {
throw new PpkFormatterException(PpkFormatterException.PpkErrorType.FileFormat,
privateKeyEncryptionKey + " expected");
}
algorithm = pair[1].Trim();
if (!algorithm.TryParsePrivateKeyAlgorithm(ref fileData.privateKeyAlgorithm)) {
throw new PpkFormatterException(PpkFormatterException.PpkErrorType.PrivateKeyEncryption);
}
/* read comment */
line = reader.ReadLine();
pair = line.Split(delimArray, 2);
if (pair[0] != commentKey) {
throw new PpkFormatterException(PpkFormatterException.PpkErrorType.FileFormat,
commentKey + " expected");
}
fileData.comment = pair[1].Trim();
/* read public key */
line = reader.ReadLine();
pair = line.Split(delimArray, 2);
if (pair[0] != publicKeyLinesKey) {
throw new PpkFormatterException(PpkFormatterException.PpkErrorType.FileFormat,
publicKeyLinesKey + " expected");
}
if (!int.TryParse(pair[1], out lineCount)) {
throw new PpkFormatterException(PpkFormatterException.PpkErrorType.FileFormat,
"integer expected");
}
string publicKeyString = string.Empty;
for (i = 0; i < lineCount; i++) {
publicKeyString += reader.ReadLine();
}
fileData.publicKeyBlob = Util.FromBase64(publicKeyString);
/* read private key */
line = reader.ReadLine();
pair = line.Split(delimArray, 2);
if (pair[0] != privateKeyLinesKey) {
throw new PpkFormatterException(PpkFormatterException.PpkErrorType.FileFormat,
privateKeyLinesKey + " expected");
}
if (!int.TryParse(pair[1], out lineCount)) {
throw new PpkFormatterException(PpkFormatterException.PpkErrorType.FileFormat,
"integer expected");
}
string privateKeyString = string.Empty;
for (i = 0; i < lineCount; i++) {
privateKeyString += reader.ReadLine();
}
fileData.privateKeyBlob =
new PinnedArray<byte>(Util.FromBase64(privateKeyString));
/* read MAC */
line = reader.ReadLine();
pair = line.Split(delimArray, 2);
if (pair[0] != privateMACKey) {
fileData.isHMAC = false;
if (pair[0] != privateHashKey || fileData.ppkFileVersion != Version.V1) {
throw new PpkFormatterException(PpkFormatterException.PpkErrorType.FileFormat,
privateMACKey + " expected");
}
} else {
fileData.isHMAC = true;
}
string privateMACString = pair[1].Trim();
fileData.privateMAC = Util.FromHex(privateMACString);
/* get passphrase and decrypt private key if required */
if (fileData.privateKeyAlgorithm != PrivateKeyAlgorithm.None) {
if (GetPassphraseCallbackMethod == null) {
throw new CallbackNullException();
}
fileData.passphrase = GetPassphraseCallbackMethod.Invoke(fileData.comment);
DecryptPrivateKey(ref fileData);
}
VerifyIntegrity(fileData);
AsymmetricCipherKeyPair cipherKeyPair =
CreateCipherKeyPair(fileData.publicKeyAlgorithm,
fileData.publicKeyBlob, fileData.privateKeyBlob.Data);
SshKey key = new SshKey(SshVersion.SSH2, cipherKeyPair, fileData.comment);
return key;
} catch (PpkFormatterException) {
throw;
} catch (CallbackNullException) {
throw;
} catch (Exception ex) {
throw new PpkFormatterException(
PpkFormatterException.PpkErrorType.FileFormat,
"See inner exception.", ex);
} finally {
if (fileData.publicKeyBlob != null) {
Array.Clear(fileData.publicKeyBlob, 0, fileData.publicKeyBlob.Length);
}
if (fileData.privateKeyBlob != null) {
fileData.privateKeyBlob.Dispose();
}
if (fileData.privateMAC != null) {
Array.Clear(fileData.privateMAC, 0, fileData.privateMAC.Length);
}
reader.Close();
}
}