using System.Security.Cryptography; using System.Text; using Microsoft.VisualStudio.TestTools.UnitTesting; using Renci.SshNet.Security; using Renci.SshNet.Security.Cryptography; using Renci.SshNet.Tests.Common; namespace Renci.SshNet.Tests.Classes.Security.Cryptography { /// /// Implements RSA digital signature algorithm. /// [TestClass] public class RsaDigitalSignatureTest : TestBase { [TestMethod] public void Sha1_SignAndVerify() { byte[] data = Encoding.UTF8.GetBytes("hello world"); RsaKey rsaKey = GetRsaKey(); var digitalSignature = new RsaDigitalSignature(rsaKey); // Verify SHA-1 is the default byte[] signedBytes = digitalSignature.Sign(data); byte[] expectedSignedBytes = new byte[] { // echo -n 'hello world' | openssl dgst -sha1 -sign Key.RSA.txt -out test.signed 0x41, 0x50, 0x12, 0x14, 0xd3, 0x7c, 0xe0, 0x40, 0x50, 0x65, 0xfb, 0x33, 0xd9, 0x17, 0x89, 0xbf, 0xb2, 0x4b, 0x85, 0x15, 0xbf, 0x9e, 0x57, 0x3b, 0x01, 0x15, 0x2b, 0x99, 0xfa, 0x62, 0x9b, 0x2a, 0x05, 0xa0, 0x73, 0xc7, 0xb7, 0x5b, 0xd9, 0x01, 0xaa, 0x56, 0x73, 0x95, 0x13, 0x41, 0x33, 0x0d, 0x7f, 0x83, 0x8a, 0x60, 0x4d, 0x19, 0xdc, 0x9b, 0xba, 0x8e, 0x61, 0xed, 0xd0, 0x8a, 0x3e, 0x38, 0x71, 0xee, 0x34, 0xc3, 0x55, 0x0f, 0x55, 0x65, 0x89, 0xbb, 0x3e, 0x41, 0xee, 0xdf, 0xf5, 0x2f, 0xab, 0x9e, 0x89, 0x37, 0x68, 0x1f, 0x9f, 0x38, 0x00, 0x81, 0x29, 0x93, 0xeb, 0x61, 0x37, 0xad, 0x8d, 0x35, 0xf1, 0x3d, 0x4b, 0x9b, 0x99, 0x74, 0x7b, 0xeb, 0xf4, 0xfb, 0x76, 0xb4, 0xb6, 0xb4, 0x09, 0x33, 0x5c, 0xfa, 0x6a, 0xad, 0x1e, 0xed, 0x1c, 0xe1, 0xb4, 0x4d, 0xf2, 0xa5, 0xc3, 0x64, 0x9a, 0x45, 0x81, 0xee, 0x1b, 0xa6, 0x1d, 0x01, 0x3c, 0x4d, 0xb5, 0x62, 0x9e, 0xff, 0x8e, 0xff, 0x6c, 0x18, 0xed, 0xe9, 0x8e, 0x03, 0x2c, 0xc5, 0x94, 0x81, 0xca, 0x8b, 0x18, 0x3f, 0x25, 0xcd, 0xe5, 0x42, 0x49, 0x43, 0x23, 0x1f, 0xdc, 0x3f, 0xa2, 0x43, 0xbc, 0xbd, 0x42, 0xf5, 0x60, 0xfb, 0x01, 0xd3, 0x67, 0x0d, 0x8d, 0x85, 0x7b, 0x51, 0x14, 0xec, 0x26, 0x53, 0x00, 0x61, 0x25, 0x16, 0x19, 0x10, 0x3c, 0x86, 0x16, 0x59, 0x84, 0x08, 0xd1, 0xf9, 0x1e, 0x05, 0x88, 0xbd, 0x4a, 0x01, 0x43, 0x4e, 0xec, 0x76, 0x0b, 0xd7, 0x2c, 0xe9, 0x98, 0xb1, 0x4c, 0x0a, 0x13, 0xc6, 0x95, 0xf9, 0x8f, 0x95, 0x5c, 0x98, 0x4c, 0x8f, 0x97, 0x4a, 0xad, 0x0d, 0xfe, 0x84, 0xf0, 0x56, 0xc3, 0x29, 0x73, 0x75, 0x55, 0x3c, 0xd9, 0x5e, 0x5b, 0x6f, 0xf9, 0x81, 0xbc, 0xbc, 0x50, 0x75, 0x7d, 0xa8 }; CollectionAssert.AreEqual(expectedSignedBytes, signedBytes); // Also verify RsaKey uses SHA-1 by default CollectionAssert.AreEqual(expectedSignedBytes, rsaKey.Sign(data)); Assert.IsTrue(digitalSignature.Verify(data, signedBytes)); } [TestMethod] public void Sha256_SignAndVerify() { byte[] data = Encoding.UTF8.GetBytes("hello world"); RsaKey rsaKey = GetRsaKey(); var digitalSignature = new RsaDigitalSignature(rsaKey, HashAlgorithmName.SHA256); byte[] signedBytes = digitalSignature.Sign(data); CollectionAssert.AreEqual(new byte[] { // echo -n 'hello world' | openssl dgst -sha256 -sign Key.RSA.txt -out test.signed 0x2e, 0xef, 0x01, 0x49, 0x5c, 0x66, 0x37, 0x56, 0xc2, 0xfb, 0x7b, 0xfa, 0x80, 0x2f, 0xdb, 0xaa, 0x0d, 0x15, 0xd9, 0x8d, 0xa9, 0xad, 0x81, 0x4f, 0x09, 0x2e, 0x53, 0x9e, 0xce, 0x5d, 0x68, 0x07, 0xae, 0xb9, 0xc0, 0x45, 0xfa, 0x30, 0xd0, 0xf7, 0xd6, 0xa6, 0x8d, 0x19, 0x24, 0x3a, 0xea, 0x91, 0x3e, 0xa2, 0x4a, 0x42, 0x2e, 0x21, 0xf1, 0x48, 0x57, 0xca, 0x2b, 0x6c, 0x9f, 0x79, 0x54, 0x91, 0x3e, 0x3a, 0x4d, 0xd1, 0x70, 0x87, 0x3d, 0xbe, 0x22, 0x97, 0xc9, 0xb0, 0x02, 0xf0, 0xa2, 0xae, 0x7a, 0xbb, 0x8b, 0xaf, 0xc0, 0x3b, 0xab, 0x71, 0xe8, 0x29, 0x1c, 0x18, 0x88, 0xca, 0x74, 0x1b, 0x34, 0x4f, 0xd1, 0x83, 0x39, 0x6e, 0x8f, 0x69, 0x3d, 0x7e, 0xef, 0xef, 0x57, 0x7c, 0xff, 0x21, 0x9c, 0x10, 0x2b, 0xd1, 0x4f, 0x26, 0xbe, 0xaa, 0xd2, 0xd9, 0x03, 0x14, 0x75, 0x97, 0x11, 0xaf, 0xf0, 0x28, 0xf2, 0xd3, 0x07, 0x79, 0x5b, 0x27, 0xdc, 0x97, 0xd8, 0xce, 0x4e, 0x78, 0x89, 0x16, 0x91, 0x2a, 0xb2, 0x47, 0x53, 0x94, 0xe9, 0xa1, 0x15, 0x98, 0x29, 0x0c, 0xa1, 0xf5, 0xe2, 0x8e, 0x11, 0xdc, 0x0c, 0x1c, 0x10, 0xa4, 0xf2, 0x46, 0x5c, 0x78, 0x0c, 0xc1, 0x4a, 0x65, 0x21, 0x8a, 0x2e, 0x32, 0x6c, 0x72, 0x06, 0xf9, 0x7f, 0xa1, 0x6c, 0x2e, 0x13, 0x06, 0x41, 0xaa, 0x23, 0xdd, 0xc8, 0x1c, 0x61, 0xb6, 0x96, 0x87, 0xc4, 0x84, 0xc8, 0x61, 0xec, 0x4e, 0xdd, 0x49, 0x9e, 0x4f, 0x0d, 0x8c, 0xf1, 0x7f, 0xf2, 0x6c, 0x73, 0x5a, 0xa6, 0x3b, 0xbf, 0x4e, 0xba, 0x57, 0x6b, 0xb3, 0x1e, 0x6c, 0x57, 0x76, 0x87, 0x9f, 0xb4, 0x3b, 0xcb, 0xcd, 0xe5, 0x10, 0x7a, 0x4c, 0xeb, 0xc0, 0xc4, 0xc3, 0x75, 0x51, 0x5f, 0xb7, 0x7c, 0xbc, 0x55, 0x8d, 0x05, 0xc7, 0xed, 0xc7, 0x52, 0x4a }, signedBytes); Assert.IsTrue(digitalSignature.Verify(data, signedBytes)); } [TestMethod] public void Sha512_SignAndVerify() { byte[] data = Encoding.UTF8.GetBytes("hello world"); RsaKey rsaKey = GetRsaKey(); var digitalSignature = new RsaDigitalSignature(rsaKey, HashAlgorithmName.SHA512); byte[] signedBytes = digitalSignature.Sign(data); CollectionAssert.AreEqual(new byte[] { // echo -n 'hello world' | openssl dgst -sha512 -sign Key.RSA.txt -out test.signed 0x69, 0x70, 0xb5, 0x9f, 0x32, 0x86, 0x3b, 0xae, 0xc0, 0x79, 0x6e, 0xdb, 0x35, 0xd5, 0xa6, 0x22, 0xcd, 0x2b, 0x4b, 0xd2, 0x68, 0x1a, 0x65, 0x41, 0xa6, 0xd9, 0x20, 0x54, 0x31, 0x9a, 0xb1, 0x44, 0x6e, 0x8f, 0x56, 0x4b, 0xfc, 0x27, 0x7f, 0x3f, 0xe7, 0x47, 0xcb, 0x78, 0x03, 0x05, 0x79, 0x8a, 0x16, 0x7b, 0x12, 0x01, 0x3a, 0xa2, 0xd5, 0x0d, 0x2b, 0x16, 0x38, 0xef, 0x84, 0x6b, 0xd7, 0x19, 0xeb, 0xac, 0x54, 0x01, 0x9d, 0xa6, 0x80, 0x74, 0x43, 0xa8, 0x6e, 0x5e, 0x33, 0x05, 0x06, 0x1d, 0x6d, 0xfe, 0x32, 0x4f, 0xe3, 0xcb, 0x3e, 0x2d, 0x4e, 0xe1, 0x47, 0x03, 0x69, 0xb4, 0x59, 0x80, 0x59, 0x05, 0x15, 0xa0, 0x11, 0x34, 0x47, 0x58, 0xd7, 0x93, 0x2d, 0x40, 0xf2, 0x2c, 0x37, 0x48, 0x6b, 0x3c, 0xd3, 0x03, 0x09, 0x32, 0x74, 0xa0, 0x2d, 0x33, 0x11, 0x99, 0x10, 0xb4, 0x09, 0x31, 0xec, 0xa3, 0x2c, 0x63, 0xba, 0x50, 0xd1, 0x02, 0x45, 0xae, 0xb5, 0x75, 0x7e, 0xfa, 0xfc, 0x06, 0xb6, 0x6a, 0xb2, 0xa1, 0x73, 0x14, 0xa5, 0xaa, 0x17, 0x88, 0x03, 0x19, 0x14, 0x9b, 0xe1, 0x10, 0xf8, 0x2f, 0x73, 0x01, 0xc7, 0x8d, 0x37, 0xef, 0x98, 0x69, 0xc2, 0xe2, 0x7a, 0x11, 0xd5, 0xb8, 0xc9, 0x35, 0x45, 0xcb, 0x56, 0x4b, 0x92, 0x4a, 0xe0, 0x4c, 0xd6, 0x82, 0xae, 0xad, 0x5b, 0xe9, 0x40, 0x7e, 0x2a, 0x48, 0x7d, 0x57, 0xc5, 0xfd, 0xe9, 0x98, 0xe0, 0xbb, 0x09, 0xa1, 0xf5, 0x48, 0x45, 0xcb, 0xee, 0xb9, 0x99, 0x81, 0x44, 0x15, 0x2e, 0x50, 0x39, 0x64, 0x58, 0x4c, 0x34, 0x86, 0xf8, 0x81, 0x9e, 0x1d, 0xb6, 0x97, 0xe0, 0xce, 0x16, 0xca, 0x20, 0x46, 0xe9, 0x49, 0x8f, 0xe6, 0xa0, 0x23, 0x08, 0x80, 0xa6, 0x37, 0x70, 0x06, 0xcc, 0x8f, 0xf4, 0xa0, 0x74, 0x53, 0x26, 0x38 }, signedBytes); Assert.IsTrue(digitalSignature.Verify(data, signedBytes)); } [TestMethod] public void SignatureDoesNotTruncateLeadingZeroes() { // A regression test for https://github.com/sshnet/SSH.NET/issues/1388 byte[] data = { 0x41, 0xdb, 0xf3, 0x09, 0x56 }; RsaKey rsaKey = GetRsaKey(); var digitalSignature = new RsaDigitalSignature(rsaKey, HashAlgorithmName.SHA1); byte[] signedBytes = digitalSignature.Sign(data); CollectionAssert.AreEqual(new byte[] { 0x00, 0xa8, 0x35, 0x24, 0xc8, 0xc1, 0x94, 0x97, 0xc3, 0xdf, 0x94, 0x32, 0x62, 0xf2, 0x12, 0x57, 0x49, 0x22, 0x7e, 0x52, 0xfe, 0x6e, 0x23, 0x1f, 0x28, 0x84, 0xf9, 0x3e, 0x16, 0xda, 0xc3, 0x6f, 0xa0, 0xa4, 0x00, 0x9a, 0x9b, 0xf2, 0x3e, 0xf5, 0x47, 0x3a, 0x7a, 0x8a, 0xd1, 0x1e, 0xf1, 0xd0, 0x0b, 0x4d, 0x04, 0x16, 0x6f, 0x29, 0xf1, 0xe7, 0x26, 0xfd, 0x5a, 0x6e, 0x9a, 0xc4, 0x53, 0x7f, 0xbe, 0xa3, 0x3b, 0xa0, 0x95, 0x02, 0xe2, 0xcd, 0xd9, 0xa1, 0x4d, 0xae, 0x63, 0x4f, 0x95, 0x5e, 0x4f, 0xd6, 0x34, 0x3a, 0x05, 0x93, 0xcb, 0xb4, 0x18, 0xd2, 0xd0, 0xd6, 0x5f, 0x8c, 0xe3, 0x77, 0xca, 0x7f, 0x88, 0xfb, 0x72, 0x00, 0x00, 0x74, 0x31, 0xb7, 0xc5, 0xe8, 0xe2, 0x92, 0xf9, 0xab, 0x63, 0x8f, 0x87, 0x07, 0xc5, 0x90, 0xf2, 0xdd, 0x6d, 0xc6, 0x38, 0xee, 0x19, 0x65, 0x05, 0xa8, 0xda, 0xfc, 0x32, 0xe9, 0xbf, 0x2a, 0x0d, 0x6b, 0x2b, 0xac, 0x92, 0x48, 0xda, 0x3b, 0x8f, 0x4f, 0x68, 0x58, 0xa6, 0xa0, 0xcb, 0xdc, 0x44, 0xe3, 0x12, 0x12, 0xb3, 0x0a, 0xf2, 0x4c, 0xa6, 0x17, 0xab, 0xdb, 0x5b, 0x79, 0x63, 0x83, 0x8b, 0x10, 0x1c, 0x13, 0xc7, 0xf1, 0x15, 0x88, 0xc6, 0x92, 0xcd, 0x6f, 0x81, 0xde, 0x02, 0x1d, 0x35, 0x91, 0xf4, 0x0c, 0x66, 0xe6, 0x7c, 0x3f, 0x02, 0x98, 0xa7, 0x79, 0x6c, 0x90, 0x67, 0x14, 0x80, 0x18, 0xeb, 0xe7, 0x52, 0x44, 0x6b, 0x1b, 0x24, 0xac, 0x71, 0xaa, 0xde, 0xeb, 0xf7, 0x3c, 0xfc, 0xc0, 0x46, 0x23, 0x40, 0x2f, 0xb0, 0xf2, 0x0b, 0x2e, 0xfd, 0xd6, 0xd5, 0x2b, 0x3f, 0x00, 0xd8, 0xfe, 0x30, 0xa6, 0x67, 0xbc, 0x3d, 0xad, 0xb2, 0xf4, 0xf3, 0x98, 0xb5, 0x0a, 0x91, 0xf3, 0x9d, 0xfb, 0xe8, 0xeb, 0xe0, 0x35, 0x5b, 0x11, 0xcf, 0xdb, }, signedBytes); Assert.IsTrue(digitalSignature.Verify(data, signedBytes)); } private static RsaKey GetRsaKey() { using (var stream = GetData("Key.RSA.txt")) { return (RsaKey)new PrivateKeyFile(stream).Key; } } } }