public override void Serialize(Stream aStream, object aObject) { /* check for required parameters */ if (aStream == null) { throw new ArgumentNullException("aStream"); } if (aObject == null) { throw new ArgumentNullException("aObject"); } PasswordFinder pwFinder = null; if (GetPassphraseCallbackMethod != null) { pwFinder = new PasswordFinder(GetPassphraseCallbackMethod); } PinnedArray<char> passphrase = null; if (pwFinder != null) { passphrase = new PinnedArray<char>(0); passphrase.Data = pwFinder.GetPassword(); } byte cipherType; if (passphrase == null || passphrase.Data.Length == 0) { cipherType = SSH_CIPHER_NONE; } else { cipherType = SSH_CIPHER_3DES; } BlobBuilder builder = new BlobBuilder(); ISshKey sshKey = aObject as ISshKey; RsaKeyParameters publicKeyParams = sshKey.GetPublicKeyParameters() as RsaKeyParameters; RsaPrivateCrtKeyParameters privateKeyParams = sshKey.GetPrivateKeyParameters() as RsaPrivateCrtKeyParameters; /* writing info headers */ builder.AddBytes(Encoding.ASCII.GetBytes(FILE_HEADER_LINE + "\n")); builder.AddByte(0); //end of string builder.AddByte(cipherType); //cipher builder.AddInt(0); //reserved /* writing public key */ builder.AddInt(sshKey.Size); builder.AddSsh1BigIntBlob(publicKeyParams.Modulus); builder.AddSsh1BigIntBlob(publicKeyParams.Exponent); builder.AddStringBlob(sshKey.Comment); /* writing private key */ BlobBuilder privateKeyBuilder = new BlobBuilder(); /* adding some control values */ Random random = new Random(); byte[] resultCheck = new byte[2]; random.NextBytes(resultCheck); privateKeyBuilder.AddByte(resultCheck[0]); privateKeyBuilder.AddByte(resultCheck[1]); privateKeyBuilder.AddByte(resultCheck[0]); privateKeyBuilder.AddByte(resultCheck[1]); privateKeyBuilder.AddSsh1BigIntBlob(privateKeyParams.Exponent); privateKeyBuilder.AddSsh1BigIntBlob(privateKeyParams.DQ); privateKeyBuilder.AddSsh1BigIntBlob(privateKeyParams.P); privateKeyBuilder.AddSsh1BigIntBlob(privateKeyParams.Q); if (cipherType == SSH_CIPHER_NONE) { /* plain-text */ builder.AddBytes(privateKeyBuilder.GetBlobAsPinnedByteArray().Data); } else { byte[] keydata; using (MD5 md5 = MD5.Create()) { keydata = md5.ComputeHash(Encoding.ASCII.GetBytes(passphrase.Data)); } /* encryption */ DesSsh1Engine desEngine = new DesSsh1Engine(); desEngine.Init(true, new KeyParameter(keydata)); BufferedBlockCipher bufferedBlockCipher = new BufferedBlockCipher(desEngine); byte[] ouputBuffer = bufferedBlockCipher.ProcessBytes( privateKeyBuilder.GetBlobAsPinnedByteArray().Data); builder.AddBytes(ouputBuffer); passphrase.Dispose(); } /* writing result to file */ var builderOutput = builder.GetBlobAsPinnedByteArray(); aStream.Write(builderOutput.Data, 0, builderOutput.Data.Length); aStream.Close(); }
public void TestAnswerSSH2_AGENTC_ADD_ID_CONSTRAINED() { /* most code is shared with SSH2_AGENTC_ADD_IDENTITY, so we just * need to test the differences */ Agent.ConfirmUserPermissionDelegate confirmCallback = delegate(ISshKey k, Process p) { return true; }; Agent agent = new TestAgent(); /* test that no confirmation callback returns failure */ BlobBuilder builder = new BlobBuilder(); RsaPrivateCrtKeyParameters rsaParameters = (RsaPrivateCrtKeyParameters)rsaKey.GetPrivateKeyParameters(); builder.AddStringBlob(rsaKey.Algorithm.GetIdentifierString()); builder.AddBigIntBlob(rsaParameters.Modulus); builder.AddBigIntBlob(rsaParameters.PublicExponent); builder.AddBigIntBlob(rsaParameters.Exponent); builder.AddBigIntBlob(rsaParameters.QInv); builder.AddBigIntBlob(rsaParameters.P); builder.AddBigIntBlob(rsaParameters.Q); builder.AddStringBlob(rsaKey.Comment); //save blob so far so we don't have to repeat later. byte[] commonBlob = builder.GetBlob(); builder.AddByte((byte)Agent.KeyConstraintType.SSH_AGENT_CONSTRAIN_CONFIRM); builder.InsertHeader(Agent.Message.SSH2_AGENTC_ADD_ID_CONSTRAINED); PrepareMessage(builder); agent.AnswerMessage(stream); RewindStream(); Agent.BlobHeader header = parser.ReadHeader(); Assert.That(header.BlobLength, Is.EqualTo(1)); Assert.That(header.Message, Is.EqualTo(Agent.Message.SSH_AGENT_FAILURE)); /* test adding key with confirm constraint */ agent = new TestAgent(); agent.ConfirmUserPermissionCallback = confirmCallback; PrepareMessage(builder); agent.AnswerMessage(stream); RewindStream(); header = parser.ReadHeader(); Assert.That(header.BlobLength, Is.EqualTo(1)); Assert.That(header.Message, Is.EqualTo(Agent.Message.SSH_AGENT_SUCCESS)); ISshKey returnedKey = agent.GetAllKeys().First(); Assert.That(returnedKey.Constraints.Count(), Is.EqualTo(1)); Assert.That(returnedKey.Constraints[0].Type, Is.EqualTo(Agent.KeyConstraintType.SSH_AGENT_CONSTRAIN_CONFIRM)); Assert.That(returnedKey.Constraints[0].Data, Is.Null); /* test adding key with lifetime constraint */ agent = new TestAgent(); builder.Clear(); builder.AddBytes(commonBlob); builder.AddByte((byte)Agent.KeyConstraintType.SSH_AGENT_CONSTRAIN_LIFETIME); builder.AddInt(10); builder.InsertHeader(Agent.Message.SSH2_AGENTC_ADD_ID_CONSTRAINED); PrepareMessage(builder); agent.AnswerMessage(stream); RewindStream(); header = parser.ReadHeader(); Assert.That(header.BlobLength, Is.EqualTo(1)); Assert.That(header.Message, Is.EqualTo(Agent.Message.SSH_AGENT_SUCCESS)); returnedKey = agent.GetAllKeys().First(); Assert.That(returnedKey.Constraints.Count(), Is.EqualTo(1)); Assert.That(returnedKey.Constraints[0].Type, Is.EqualTo(Agent.KeyConstraintType.SSH_AGENT_CONSTRAIN_LIFETIME)); Assert.That(returnedKey.Constraints[0].Data.GetType(), Is.EqualTo(Agent.KeyConstraintType.SSH_AGENT_CONSTRAIN_LIFETIME.GetDataType())); Assert.That(returnedKey.Constraints[0].Data, Is.EqualTo(10)); /* test adding key with multiple constraints */ agent = new TestAgent(); agent.ConfirmUserPermissionCallback = confirmCallback; builder.Clear(); builder.AddBytes(commonBlob); builder.AddByte((byte)Agent.KeyConstraintType.SSH_AGENT_CONSTRAIN_CONFIRM); builder.AddByte((byte)Agent.KeyConstraintType.SSH_AGENT_CONSTRAIN_LIFETIME); builder.AddInt(10); builder.InsertHeader(Agent.Message.SSH2_AGENTC_ADD_ID_CONSTRAINED); PrepareMessage(builder); agent.AnswerMessage(stream); RewindStream(); header = parser.ReadHeader(); Assert.That(header.BlobLength, Is.EqualTo(1)); Assert.That(header.Message, Is.EqualTo(Agent.Message.SSH_AGENT_SUCCESS)); returnedKey = agent.GetAllKeys().First(); Assert.That(returnedKey.Constraints.Count(), Is.EqualTo(2)); Assert.That(returnedKey.Constraints[0].Type, Is.EqualTo(Agent.KeyConstraintType.SSH_AGENT_CONSTRAIN_CONFIRM)); Assert.That(returnedKey.Constraints[0].Data, Is.Null); Assert.That(returnedKey.Constraints[1].Type, Is.EqualTo(Agent.KeyConstraintType.SSH_AGENT_CONSTRAIN_LIFETIME)); Assert.That(returnedKey.Constraints[1].Data, Is.EqualTo(10)); /* test adding key with multiple constraints in different order */ agent = new TestAgent(); agent.ConfirmUserPermissionCallback = confirmCallback; builder.Clear(); builder.AddBytes(commonBlob); builder.AddByte((byte)Agent.KeyConstraintType.SSH_AGENT_CONSTRAIN_LIFETIME); builder.AddInt(10); builder.AddByte((byte)Agent.KeyConstraintType.SSH_AGENT_CONSTRAIN_CONFIRM); builder.InsertHeader(Agent.Message.SSH2_AGENTC_ADD_ID_CONSTRAINED); PrepareMessage(builder); agent.AnswerMessage(stream); RewindStream(); header = parser.ReadHeader(); Assert.That(header.BlobLength, Is.EqualTo(1)); Assert.That(header.Message, Is.EqualTo(Agent.Message.SSH_AGENT_SUCCESS)); returnedKey = agent.GetAllKeys().First(); Assert.That(returnedKey.Constraints.Count(), Is.EqualTo(2)); Assert.That(returnedKey.Constraints[0].Type, Is.EqualTo(Agent.KeyConstraintType.SSH_AGENT_CONSTRAIN_LIFETIME)); Assert.That(returnedKey.Constraints[0].Data, Is.EqualTo(10)); Assert.That(returnedKey.Constraints[1].Type, Is.EqualTo(Agent.KeyConstraintType.SSH_AGENT_CONSTRAIN_CONFIRM)); Assert.That(returnedKey.Constraints[1].Data, Is.Null); }