public void WritePrivatePartInSECSHStyleFile(Stream dest, string comment, string passphrase)
{
//step1 key body
SSH2DataWriter wr = new SSH2DataWriter();
wr.WriteInt32(0); //this field is filled later
if (_keypair.Algorithm == PublicKeyAlgorithm.RSA) {
RSAKeyPair rsa = (RSAKeyPair)_keypair;
RSAPublicKey pub = (RSAPublicKey)_keypair.PublicKey;
wr.WriteBigIntWithBits(pub.Exponent);
wr.WriteBigIntWithBits(rsa.D);
wr.WriteBigIntWithBits(pub.Modulus);
wr.WriteBigIntWithBits(rsa.U);
wr.WriteBigIntWithBits(rsa.P);
wr.WriteBigIntWithBits(rsa.Q);
}
else {
DSAKeyPair dsa = (DSAKeyPair)_keypair;
DSAPublicKey pub = (DSAPublicKey)_keypair.PublicKey;
wr.WriteInt32(0);
wr.WriteBigIntWithBits(pub.P);
wr.WriteBigIntWithBits(pub.G);
wr.WriteBigIntWithBits(pub.Q);
wr.WriteBigIntWithBits(pub.Y);
wr.WriteBigIntWithBits(dsa.X);
}
int padding_len = 0;
if (passphrase != null) {
padding_len = 8 - (int)wr.Length % 8;
wr.Write(new byte[padding_len]);
}
byte[] encrypted_body = wr.ToByteArray();
SSHUtil.WriteIntToByteArray(encrypted_body, 0, encrypted_body.Length - padding_len - 4);
//encrypt if necessary
if (passphrase != null) {
Cipher c = CipherFactory.CreateCipher(SSHProtocol.SSH2, CipherAlgorithm.TripleDES, PassphraseToKey(passphrase, 24));
Debug.Assert(encrypted_body.Length % 8 == 0);
byte[] tmp = new Byte[encrypted_body.Length];
c.Encrypt(encrypted_body, 0, encrypted_body.Length, tmp, 0);
encrypted_body = tmp;
}
//step2 make binary key data
wr = new SSH2DataWriter();
wr.WriteInt32(MAGIC_VAL);
wr.WriteInt32(0); //for total size
wr.WriteString(_keypair.Algorithm == PublicKeyAlgorithm.RSA ?
"if-modn{sign{rsa-pkcs1-sha1},encrypt{rsa-pkcs1v2-oaep}}" :
"dl-modp{sign{dsa-nist-sha1},dh{plain}}");
wr.WriteString(passphrase == null ? "none" : "3des-cbc");
wr.WriteAsString(encrypted_body);
byte[] rawdata = wr.ToByteArray();
SSHUtil.WriteIntToByteArray(rawdata, 4, rawdata.Length); //fix total length
//step3 write final data
StreamWriter sw = new StreamWriter(dest, Encoding.ASCII);
sw.WriteLine("---- BEGIN SSH2 ENCRYPTED PRIVATE KEY ----");
if (comment != null)
WriteKeyFileBlock(sw, "Comment: " + comment, true);
WriteKeyFileBlock(sw, Encoding.ASCII.GetString(Base64.Encode(rawdata)), false);
sw.WriteLine("---- END SSH2 ENCRYPTED PRIVATE KEY ----");
sw.Close();
}