mirror of
https://github.com/sshnet/SSH.NET.git
synced 2026-09-10 17:25:51 +00:00
Refactor and reorganize cipher encryption (more need to be done)
Add padding for private key DES-EDE3-CBC, DES-EDE3-CFB and others encryption/decryption Add internally implemented DSA digital signature Change encruption and hash algorithm definition in ConnectionInfo from Type to Lambda expression
This commit is contained in:
@@ -5,6 +5,8 @@ using System.Text;
|
||||
using Microsoft.VisualStudio.TestTools.UnitTesting;
|
||||
using Renci.SshNet.Security;
|
||||
using Renci.SshNet.Tests.Properties;
|
||||
using Renci.SshNet.Security.Cryptography.Ciphers;
|
||||
using Renci.SshNet.Security.Cryptography.Ciphers.Modes;
|
||||
|
||||
namespace Renci.SshNet.Tests.Security
|
||||
{
|
||||
@@ -16,7 +18,7 @@ namespace Renci.SshNet.Tests.Security
|
||||
{
|
||||
var connectionInfo = new PasswordConnectionInfo(Resources.HOST, 22, Resources.USERNAME, Resources.PASSWORD);
|
||||
connectionInfo.Encryptions.Clear();
|
||||
connectionInfo.Encryptions.Add("3des-cbc", typeof(CipherTripleDes192Cbc));
|
||||
connectionInfo.Encryptions.Add("3des-cbc", new CipherInfo(192, (key, iv) => { return new TripleDesCipher(key, new CbcCipherMode(iv), null); }));
|
||||
|
||||
using (var client = new SshClient(connectionInfo))
|
||||
{
|
||||
@@ -30,7 +32,7 @@ namespace Renci.SshNet.Tests.Security
|
||||
{
|
||||
var connectionInfo = new PasswordConnectionInfo(Resources.HOST, 22, Resources.USERNAME, Resources.PASSWORD);
|
||||
connectionInfo.Encryptions.Clear();
|
||||
connectionInfo.Encryptions.Add("aes128-cbc", typeof(CipherAes128Cbc));
|
||||
connectionInfo.Encryptions.Add("aes128-cbc", new CipherInfo(128, (key, iv) => { return new AesCipher(key, new CbcCipherMode(iv), null); }));
|
||||
|
||||
using (var client = new SshClient(connectionInfo))
|
||||
{
|
||||
@@ -44,7 +46,7 @@ namespace Renci.SshNet.Tests.Security
|
||||
{
|
||||
var connectionInfo = new PasswordConnectionInfo(Resources.HOST, 22, Resources.USERNAME, Resources.PASSWORD);
|
||||
connectionInfo.Encryptions.Clear();
|
||||
connectionInfo.Encryptions.Add("aes192-cbc", typeof(CipherAes192Cbc));
|
||||
connectionInfo.Encryptions.Add("aes192-cbc", new CipherInfo(192, (key, iv) => { return new AesCipher(key, new CbcCipherMode(iv), null); }));
|
||||
|
||||
using (var client = new SshClient(connectionInfo))
|
||||
{
|
||||
@@ -58,7 +60,7 @@ namespace Renci.SshNet.Tests.Security
|
||||
{
|
||||
var connectionInfo = new PasswordConnectionInfo(Resources.HOST, 22, Resources.USERNAME, Resources.PASSWORD);
|
||||
connectionInfo.Encryptions.Clear();
|
||||
connectionInfo.Encryptions.Add("aes256-cbc", typeof(CipherAes256Cbc));
|
||||
connectionInfo.Encryptions.Add("aes256-cbc", new CipherInfo(256, (key, iv) => { return new AesCipher(key, new CbcCipherMode(iv), null); }));
|
||||
|
||||
using (var client = new SshClient(connectionInfo))
|
||||
{
|
||||
@@ -72,7 +74,7 @@ namespace Renci.SshNet.Tests.Security
|
||||
{
|
||||
var connectionInfo = new PasswordConnectionInfo(Resources.HOST, 22, Resources.USERNAME, Resources.PASSWORD);
|
||||
connectionInfo.Encryptions.Clear();
|
||||
connectionInfo.Encryptions.Add("aes128-ctr", typeof(CipherAes128Ctr));
|
||||
connectionInfo.Encryptions.Add("aes128-ctr", new CipherInfo(128, (key, iv) => { return new AesCipher(key, new CtrCipherMode(iv), null); }));
|
||||
|
||||
using (var client = new SshClient(connectionInfo))
|
||||
{
|
||||
@@ -86,7 +88,7 @@ namespace Renci.SshNet.Tests.Security
|
||||
{
|
||||
var connectionInfo = new PasswordConnectionInfo(Resources.HOST, 22, Resources.USERNAME, Resources.PASSWORD);
|
||||
connectionInfo.Encryptions.Clear();
|
||||
connectionInfo.Encryptions.Add("aes192-ctr", typeof(CipherAes192Ctr));
|
||||
connectionInfo.Encryptions.Add("aes192-ctr", new CipherInfo(192, (key, iv) => { return new AesCipher(key, new CtrCipherMode(iv), null); }));
|
||||
|
||||
using (var client = new SshClient(connectionInfo))
|
||||
{
|
||||
@@ -100,7 +102,7 @@ namespace Renci.SshNet.Tests.Security
|
||||
{
|
||||
var connectionInfo = new PasswordConnectionInfo(Resources.HOST, 22, Resources.USERNAME, Resources.PASSWORD);
|
||||
connectionInfo.Encryptions.Clear();
|
||||
connectionInfo.Encryptions.Add("aes256-ctr", typeof(CipherAes256Ctr));
|
||||
connectionInfo.Encryptions.Add("aes256-ctr", new CipherInfo(256, (key, iv) => { return new AesCipher(key, new CtrCipherMode(iv), null); }));
|
||||
|
||||
using (var client = new SshClient(connectionInfo))
|
||||
{
|
||||
@@ -114,7 +116,7 @@ namespace Renci.SshNet.Tests.Security
|
||||
{
|
||||
var connectionInfo = new PasswordConnectionInfo(Resources.HOST, 22, Resources.USERNAME, Resources.PASSWORD);
|
||||
connectionInfo.Encryptions.Clear();
|
||||
connectionInfo.Encryptions.Add("blowfish-cbc", typeof(CipherBlowfish));
|
||||
connectionInfo.Encryptions.Add("blowfish-cbc", new CipherInfo(128, (key, iv) => { return new BlowfishCipher(key, new CbcCipherMode(iv), null); }));
|
||||
|
||||
using (var client = new SshClient(connectionInfo))
|
||||
{
|
||||
@@ -128,7 +130,7 @@ namespace Renci.SshNet.Tests.Security
|
||||
{
|
||||
var connectionInfo = new PasswordConnectionInfo(Resources.HOST, 22, Resources.USERNAME, Resources.PASSWORD);
|
||||
connectionInfo.Encryptions.Clear();
|
||||
connectionInfo.Encryptions.Add("cast128-cbc", typeof(CipherCast128Cbc));
|
||||
connectionInfo.Encryptions.Add("cast128-cbc", new CipherInfo(128, (key, iv) => { return new CastCipher(key, new CbcCipherMode(iv), null); }));
|
||||
|
||||
using (var client = new SshClient(connectionInfo))
|
||||
{
|
||||
|
||||
@@ -5,6 +5,7 @@ using System.Text;
|
||||
using Microsoft.VisualStudio.TestTools.UnitTesting;
|
||||
using Renci.SshNet.Security;
|
||||
using Renci.SshNet.Tests.Properties;
|
||||
using Renci.SshNet.Security.Cryptography;
|
||||
|
||||
namespace Renci.SshNet.Tests.Security
|
||||
{
|
||||
@@ -16,7 +17,7 @@ namespace Renci.SshNet.Tests.Security
|
||||
{
|
||||
var connectionInfo = new PasswordConnectionInfo(Resources.HOST, 22, Resources.USERNAME, Resources.PASSWORD);
|
||||
connectionInfo.HmacAlgorithms.Clear();
|
||||
connectionInfo.HmacAlgorithms.Add("hmac-md5", typeof(HMacMD5));
|
||||
connectionInfo.HmacAlgorithms.Add("hmac-md5", (key) => { return new HMac<MD5Hash>(key.Take(16).ToArray());});
|
||||
|
||||
using (var client = new SshClient(connectionInfo))
|
||||
{
|
||||
@@ -30,7 +31,7 @@ namespace Renci.SshNet.Tests.Security
|
||||
{
|
||||
var connectionInfo = new PasswordConnectionInfo(Resources.HOST, 22, Resources.USERNAME, Resources.PASSWORD);
|
||||
connectionInfo.HmacAlgorithms.Clear();
|
||||
connectionInfo.HmacAlgorithms.Add("hmac-sha1", typeof(HMacSha1));
|
||||
connectionInfo.HmacAlgorithms.Add("hmac-sha1", (key) => { return new HMac<SHA1Hash>(key.Take(20).ToArray()); });
|
||||
|
||||
using (var client = new SshClient(connectionInfo))
|
||||
{
|
||||
|
||||
@@ -4,15 +4,18 @@ Microsoft Visual Studio Solution File, Format Version 11.00
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Renci.SshNet", "Renci.SshNet\Renci.SshNet.csproj", "{2F5F8C90-0BD1-424F-997C-7BC6280919D1}"
|
||||
EndProject
|
||||
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution Items", "{A3063E62-89D5-43FF-AB1A-FFBECB4A1850}"
|
||||
ProjectSection(SolutionItems) = preProject
|
||||
Renci.SshNet.vsmdi = Renci.SshNet.vsmdi
|
||||
EndProjectSection
|
||||
EndProject
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Renci.SshNet.Tests", "Renci.SshNet.Tests\Renci.SshNet.Tests.csproj", "{C45379B9-17B1-4E89-BC2E-6D41726413E8}"
|
||||
EndProject
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Test", "Test\Test.csproj", "{EFAF2072-A01F-4970-878A-AAD40326AFD2}"
|
||||
EndProject
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Renci.SshNet.Silverlight", "Renci.SshNet.Silverlight\Renci.SshNet.Silverlight.csproj", "{77C294BB-1DC2-49DC-BE16-963F8F22794D}"
|
||||
EndProject
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Test.Web", "Test.Web\Test.Web.csproj", "{1A1BAB9E-0DAD-4171-A979-6F2F221E3C28}"
|
||||
EndProject
|
||||
Global
|
||||
GlobalSection(TeamFoundationVersionControl) = preSolution
|
||||
SccNumberOfProjects = 3
|
||||
SccNumberOfProjects = 4
|
||||
SccEnterpriseProvider = {4CA58AB2-18FA-4F8D-95D4-32DDF27D184C}
|
||||
SccTeamFoundationServer = https://tfs.codeplex.com/tfs/tfs11
|
||||
SccLocalPath0 = .
|
||||
@@ -22,6 +25,9 @@ Global
|
||||
SccProjectUniqueName2 = Renci.SshNet.Tests\\Renci.SshNet.Tests.csproj
|
||||
SccProjectName2 = Renci.SshNet.Tests
|
||||
SccLocalPath2 = Renci.SshNet.Tests
|
||||
SccProjectUniqueName3 = Renci.SshNet.Silverlight\\Renci.SshNet.Silverlight.csproj
|
||||
SccProjectName3 = Renci.SshNet.Silverlight
|
||||
SccLocalPath3 = Renci.SshNet.Silverlight
|
||||
EndGlobalSection
|
||||
GlobalSection(TestCaseManagementSettings) = postSolution
|
||||
CategoryFile = Renci.SshNet.vsmdi
|
||||
@@ -55,6 +61,36 @@ Global
|
||||
{C45379B9-17B1-4E89-BC2E-6D41726413E8}.Release|Mixed Platforms.ActiveCfg = Release|Any CPU
|
||||
{C45379B9-17B1-4E89-BC2E-6D41726413E8}.Release|Mixed Platforms.Build.0 = Release|Any CPU
|
||||
{C45379B9-17B1-4E89-BC2E-6D41726413E8}.Release|x86.ActiveCfg = Release|Any CPU
|
||||
{EFAF2072-A01F-4970-878A-AAD40326AFD2}.Debug|Any CPU.ActiveCfg = Debug|x86
|
||||
{EFAF2072-A01F-4970-878A-AAD40326AFD2}.Debug|Mixed Platforms.ActiveCfg = Debug|x86
|
||||
{EFAF2072-A01F-4970-878A-AAD40326AFD2}.Debug|Mixed Platforms.Build.0 = Debug|x86
|
||||
{EFAF2072-A01F-4970-878A-AAD40326AFD2}.Debug|x86.ActiveCfg = Debug|x86
|
||||
{EFAF2072-A01F-4970-878A-AAD40326AFD2}.Debug|x86.Build.0 = Debug|x86
|
||||
{EFAF2072-A01F-4970-878A-AAD40326AFD2}.Release|Any CPU.ActiveCfg = Release|x86
|
||||
{EFAF2072-A01F-4970-878A-AAD40326AFD2}.Release|Mixed Platforms.ActiveCfg = Release|x86
|
||||
{EFAF2072-A01F-4970-878A-AAD40326AFD2}.Release|Mixed Platforms.Build.0 = Release|x86
|
||||
{EFAF2072-A01F-4970-878A-AAD40326AFD2}.Release|x86.ActiveCfg = Release|x86
|
||||
{EFAF2072-A01F-4970-878A-AAD40326AFD2}.Release|x86.Build.0 = Release|x86
|
||||
{77C294BB-1DC2-49DC-BE16-963F8F22794D}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{77C294BB-1DC2-49DC-BE16-963F8F22794D}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{77C294BB-1DC2-49DC-BE16-963F8F22794D}.Debug|Mixed Platforms.ActiveCfg = Debug|Any CPU
|
||||
{77C294BB-1DC2-49DC-BE16-963F8F22794D}.Debug|Mixed Platforms.Build.0 = Debug|Any CPU
|
||||
{77C294BB-1DC2-49DC-BE16-963F8F22794D}.Debug|x86.ActiveCfg = Debug|Any CPU
|
||||
{77C294BB-1DC2-49DC-BE16-963F8F22794D}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{77C294BB-1DC2-49DC-BE16-963F8F22794D}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{77C294BB-1DC2-49DC-BE16-963F8F22794D}.Release|Mixed Platforms.ActiveCfg = Release|Any CPU
|
||||
{77C294BB-1DC2-49DC-BE16-963F8F22794D}.Release|Mixed Platforms.Build.0 = Release|Any CPU
|
||||
{77C294BB-1DC2-49DC-BE16-963F8F22794D}.Release|x86.ActiveCfg = Release|Any CPU
|
||||
{1A1BAB9E-0DAD-4171-A979-6F2F221E3C28}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{1A1BAB9E-0DAD-4171-A979-6F2F221E3C28}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{1A1BAB9E-0DAD-4171-A979-6F2F221E3C28}.Debug|Mixed Platforms.ActiveCfg = Debug|Any CPU
|
||||
{1A1BAB9E-0DAD-4171-A979-6F2F221E3C28}.Debug|Mixed Platforms.Build.0 = Debug|Any CPU
|
||||
{1A1BAB9E-0DAD-4171-A979-6F2F221E3C28}.Debug|x86.ActiveCfg = Debug|Any CPU
|
||||
{1A1BAB9E-0DAD-4171-A979-6F2F221E3C28}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{1A1BAB9E-0DAD-4171-A979-6F2F221E3C28}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{1A1BAB9E-0DAD-4171-A979-6F2F221E3C28}.Release|Mixed Platforms.ActiveCfg = Release|Any CPU
|
||||
{1A1BAB9E-0DAD-4171-A979-6F2F221E3C28}.Release|Mixed Platforms.Build.0 = Release|Any CPU
|
||||
{1A1BAB9E-0DAD-4171-A979-6F2F221E3C28}.Release|x86.ActiveCfg = Release|Any CPU
|
||||
EndGlobalSection
|
||||
GlobalSection(SolutionProperties) = preSolution
|
||||
HideSolutionNode = FALSE
|
||||
|
||||
@@ -1,44 +0,0 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<TestLists xmlns="http://microsoft.com/schemas/VisualStudio/TeamTest/2010">
|
||||
<TestList name="SftpClient" id="1405242d-fd39-46f3-88aa-a561b16d9136" parentListId="8c43106b-9dc1-4907-a29f-aa66a61bf5b6">
|
||||
<Description>Tests that affect SftpClient.</Description>
|
||||
<TestLinks>
|
||||
<TestLink id="cea8b905-fcf5-11e0-972a-3b87e3b06d10" name="Test_Sftp_DeleteDirectory_Without_Connecting" storage="renci.sshnet.tests\bin\debug\renci.sshnet.tests.dll" type="Microsoft.VisualStudio.TestTools.TestTypes.Unit.UnitTestElement, Microsoft.VisualStudio.QualityTools.Tips.UnitTest.ObjectModel, Version=10.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a" />
|
||||
<TestLink id="86b4e210-a8c7-86d0-9b57-acd5d0060acb" name="Test_Sftp_CreateDirectory_Without_Connecting" storage="renci.sshnet.tests\bin\debug\renci.sshnet.tests.dll" type="Microsoft.VisualStudio.TestTools.TestTypes.Unit.UnitTestElement, Microsoft.VisualStudio.QualityTools.Tips.UnitTest.ObjectModel, Version=10.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a" />
|
||||
<TestLink id="aa7f3916-bb55-a71b-d160-15c09fd64091" name="Test_Sftp_BeginDownloadFile_Null" storage="renci.sshnet.tests\bin\debug\renci.sshnet.tests.dll" type="Microsoft.VisualStudio.TestTools.TestTypes.Unit.UnitTestElement, Microsoft.VisualStudio.QualityTools.Tips.UnitTest.ObjectModel, Version=10.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a" />
|
||||
<TestLink id="7c8b8c07-1c12-c2f3-fa49-520c689784e8" name="Test_Sftp_ListDirectory_Current" storage="renci.sshnet.tests\bin\debug\renci.sshnet.tests.dll" type="Microsoft.VisualStudio.TestTools.TestTypes.Unit.UnitTestElement, Microsoft.VisualStudio.QualityTools.Tips.UnitTest.ObjectModel, Version=10.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a" />
|
||||
<TestLink id="d8cbe94f-d682-20ba-659f-a9c8986ae22d" name="Test_Sftp_ListDirectory_Permission_Denied" storage="renci.sshnet.tests\bin\debug\renci.sshnet.tests.dll" type="Microsoft.VisualStudio.TestTools.TestTypes.Unit.UnitTestElement, Microsoft.VisualStudio.QualityTools.Tips.UnitTest.ObjectModel, Version=10.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a" />
|
||||
<TestLink id="8887787c-1395-1d98-842b-4a8c85efd0fa" name="Test_Sftp_ChangeDirectory_Null" storage="renci.sshnet.tests\bin\debug\renci.sshnet.tests.dll" type="Microsoft.VisualStudio.TestTools.TestTypes.Unit.UnitTestElement, Microsoft.VisualStudio.QualityTools.Tips.UnitTest.ObjectModel, Version=10.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a" />
|
||||
<TestLink id="ce1e9ed2-2cf4-e43a-54e0-54c6eda70e9b" name="Test_Sftp_DeleteDirectory_Null" storage="renci.sshnet.tests\bin\debug\renci.sshnet.tests.dll" type="Microsoft.VisualStudio.TestTools.TestTypes.Unit.UnitTestElement, Microsoft.VisualStudio.QualityTools.Tips.UnitTest.ObjectModel, Version=10.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a" />
|
||||
<TestLink id="5a37e1ff-2ba3-e44c-6850-b939ace9d25a" name="Test_Sftp_RenameFile_Null" storage="renci.sshnet.tests\bin\debug\renci.sshnet.tests.dll" type="Microsoft.VisualStudio.TestTools.TestTypes.Unit.UnitTestElement, Microsoft.VisualStudio.QualityTools.Tips.UnitTest.ObjectModel, Version=10.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a" />
|
||||
<TestLink id="ff23463d-d5d3-46bd-c184-e53689e9ef5d" name="Test_Sftp_DeleteDirectory" storage="renci.sshnet.tests\bin\debug\renci.sshnet.tests.dll" type="Microsoft.VisualStudio.TestTools.TestTypes.Unit.UnitTestElement, Microsoft.VisualStudio.QualityTools.Tips.UnitTest.ObjectModel, Version=10.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a" />
|
||||
<TestLink id="293683f6-5b0a-9c36-3360-95836ac13e3e" name="Test_Sftp_Rename_File" storage="renci.sshnet.tests\bin\debug\renci.sshnet.tests.dll" type="Microsoft.VisualStudio.TestTools.TestTypes.Unit.UnitTestElement, Microsoft.VisualStudio.QualityTools.Tips.UnitTest.ObjectModel, Version=10.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a" />
|
||||
<TestLink id="af3b3194-bfb2-9b70-efa0-27c4a025dd31" name="Test_Sftp_ListDirectory_Not_Exists" storage="renci.sshnet.tests\bin\debug\renci.sshnet.tests.dll" type="Microsoft.VisualStudio.TestTools.TestTypes.Unit.UnitTestElement, Microsoft.VisualStudio.QualityTools.Tips.UnitTest.ObjectModel, Version=10.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a" />
|
||||
<TestLink id="73191d59-b774-74ef-7cdd-feab7acd6ed5" name="Test_Sftp_CreateDirectory_Already_Exists" storage="renci.sshnet.tests\bin\debug\renci.sshnet.tests.dll" type="Microsoft.VisualStudio.TestTools.TestTypes.Unit.UnitTestElement, Microsoft.VisualStudio.QualityTools.Tips.UnitTest.ObjectModel, Version=10.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a" />
|
||||
<TestLink id="e449ea7e-c991-cced-0a0e-dbb7043b0555" name="Test_Sftp_CreateDirectory_In_Current_Location" storage="renci.sshnet.tests\bin\debug\renci.sshnet.tests.dll" type="Microsoft.VisualStudio.TestTools.TestTypes.Unit.UnitTestElement, Microsoft.VisualStudio.QualityTools.Tips.UnitTest.ObjectModel, Version=10.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a" />
|
||||
<TestLink id="dde422f9-1b3b-0885-224c-b2c1a67b82dc" name="Test_Sftp_Upload_Forbidden" storage="renci.sshnet.tests\bin\debug\renci.sshnet.tests.dll" type="Microsoft.VisualStudio.TestTools.TestTypes.Unit.UnitTestElement, Microsoft.VisualStudio.QualityTools.Tips.UnitTest.ObjectModel, Version=10.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a" />
|
||||
<TestLink id="1bd90317-f6bc-efef-7d89-bec673a74c2e" name="Test_Sftp_CreateDirectory_Null" storage="renci.sshnet.tests\bin\debug\renci.sshnet.tests.dll" type="Microsoft.VisualStudio.TestTools.TestTypes.Unit.UnitTestElement, Microsoft.VisualStudio.QualityTools.Tips.UnitTest.ObjectModel, Version=10.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a" />
|
||||
<TestLink id="7ff3a089-3ed8-8531-8278-6044b9992b80" name="Test_Sftp_Download_Forbidden" storage="renci.sshnet.tests\bin\debug\renci.sshnet.tests.dll" type="Microsoft.VisualStudio.TestTools.TestTypes.Unit.UnitTestElement, Microsoft.VisualStudio.QualityTools.Tips.UnitTest.ObjectModel, Version=10.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a" />
|
||||
<TestLink id="842c8c3f-9ebf-2949-64e4-e118d925d64e" name="Test_Get_Root_Directory" storage="renci.sshnet.tests\bin\debug\renci.sshnet.tests.dll" type="Microsoft.VisualStudio.TestTools.TestTypes.Unit.UnitTestElement, Microsoft.VisualStudio.QualityTools.Tips.UnitTest.ObjectModel, Version=10.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a" />
|
||||
<TestLink id="d0f2ec5e-3aa1-2c25-4bcb-b7378f0d0283" name="Test_Sftp_Multiple_Async_Upload_And_Download_10Files_5MB_Each" storage="renci.sshnet.tests\bin\debug\renci.sshnet.tests.dll" type="Microsoft.VisualStudio.TestTools.TestTypes.Unit.UnitTestElement, Microsoft.VisualStudio.QualityTools.Tips.UnitTest.ObjectModel, Version=10.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a" />
|
||||
<TestLink id="5e6b8258-8ab1-4d79-15bf-b5267cbb85ac" name="Test_Sftp_ListDirectory_Empty" storage="renci.sshnet.tests\bin\debug\renci.sshnet.tests.dll" type="Microsoft.VisualStudio.TestTools.TestTypes.Unit.UnitTestElement, Microsoft.VisualStudio.QualityTools.Tips.UnitTest.ObjectModel, Version=10.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a" />
|
||||
<TestLink id="ae8ea5fd-f0ba-9da5-2cdc-e0f47f3d5409" name="Test_Sftp_ListDirectory_HugeDirectory" storage="renci.sshnet.tests\bin\debug\renci.sshnet.tests.dll" type="Microsoft.VisualStudio.TestTools.TestTypes.Unit.UnitTestElement, Microsoft.VisualStudio.QualityTools.Tips.UnitTest.ObjectModel, Version=10.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a" />
|
||||
<TestLink id="aeeee14f-a9f7-aaeb-dca0-0f71f5d24bc1" name="Test_Sftp_Upload_And_Download_1MB_File" storage="renci.sshnet.tests\bin\debug\renci.sshnet.tests.dll" type="Microsoft.VisualStudio.TestTools.TestTypes.Unit.UnitTestElement, Microsoft.VisualStudio.QualityTools.Tips.UnitTest.ObjectModel, Version=10.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a" />
|
||||
<TestLink id="7ee25cf7-b1fe-f444-6d0f-7e9cd472fcae" name="Test_Sftp_ListDirectory_Null" storage="renci.sshnet.tests\bin\debug\renci.sshnet.tests.dll" type="Microsoft.VisualStudio.TestTools.TestTypes.Unit.UnitTestElement, Microsoft.VisualStudio.QualityTools.Tips.UnitTest.ObjectModel, Version=10.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a" />
|
||||
<TestLink id="767acb2f-2b0c-2227-05ef-22178c779a33" name="Test_Sftp_Change_Directory" storage="renci.sshnet.tests\bin\debug\renci.sshnet.tests.dll" type="Microsoft.VisualStudio.TestTools.TestTypes.Unit.UnitTestElement, Microsoft.VisualStudio.QualityTools.Tips.UnitTest.ObjectModel, Version=10.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a" />
|
||||
<TestLink id="d8eea890-99df-9b9f-7083-3a306dd65565" name="Test_Sftp_CreateDirectory_Invalid_Path" storage="renci.sshnet.tests\bin\debug\renci.sshnet.tests.dll" type="Microsoft.VisualStudio.TestTools.TestTypes.Unit.UnitTestElement, Microsoft.VisualStudio.QualityTools.Tips.UnitTest.ObjectModel, Version=10.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a" />
|
||||
<TestLink id="1f0eddc0-c2b2-0aba-21ca-313cf8f09aa1" name="Test_Get_File" storage="renci.sshnet.tests\bin\debug\renci.sshnet.tests.dll" type="Microsoft.VisualStudio.TestTools.TestTypes.Unit.UnitTestElement, Microsoft.VisualStudio.QualityTools.Tips.UnitTest.ObjectModel, Version=10.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a" />
|
||||
<TestLink id="ef88ac59-64c7-8ccf-47bd-f882f19c0194" name="Test_Sftp_DeleteFile_Null" storage="renci.sshnet.tests\bin\debug\renci.sshnet.tests.dll" type="Microsoft.VisualStudio.TestTools.TestTypes.Unit.UnitTestElement, Microsoft.VisualStudio.QualityTools.Tips.UnitTest.ObjectModel, Version=10.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a" />
|
||||
<TestLink id="1cf918a2-a03b-1756-2aa5-bed3122b6f2c" name="Test_Sftp_BeginUploadFile_Null" storage="renci.sshnet.tests\bin\debug\renci.sshnet.tests.dll" type="Microsoft.VisualStudio.TestTools.TestTypes.Unit.UnitTestElement, Microsoft.VisualStudio.QualityTools.Tips.UnitTest.ObjectModel, Version=10.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a" />
|
||||
<TestLink id="8595c9d0-7153-2141-b96d-b19c6e959b33" name="Test_Sftp_CreateDirectory_In_Forbidden_Directory" storage="renci.sshnet.tests\bin\debug\renci.sshnet.tests.dll" type="Microsoft.VisualStudio.TestTools.TestTypes.Unit.UnitTestElement, Microsoft.VisualStudio.QualityTools.Tips.UnitTest.ObjectModel, Version=10.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a" />
|
||||
<TestLink id="a2a0b9e4-ae8f-562d-9a9e-e8b999ce0e72" name="Test_Sftp_Ensure_Async_Delegates_Called_For_BeginFileUpload_BeginFileDownload_BeginListDirectory" storage="renci.sshnet.tests\bin\debug\renci.sshnet.tests.dll" type="Microsoft.VisualStudio.TestTools.TestTypes.Unit.UnitTestElement, Microsoft.VisualStudio.QualityTools.Tips.UnitTest.ObjectModel, Version=10.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a" />
|
||||
<TestLink id="3305f837-8225-85c8-f1e9-c36ad7e38db9" name="Test_Get_Invalid_Directory" storage="renci.sshnet.tests\bin\debug\renci.sshnet.tests.dll" type="Microsoft.VisualStudio.TestTools.TestTypes.Unit.UnitTestElement, Microsoft.VisualStudio.QualityTools.Tips.UnitTest.ObjectModel, Version=10.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a" />
|
||||
<TestLink id="1cae396c-6e6f-66d2-9f2b-2d35cfb6d8c5" name="Test_Sftp_Download_File_Not_Exists" storage="renci.sshnet.tests\bin\debug\renci.sshnet.tests.dll" type="Microsoft.VisualStudio.TestTools.TestTypes.Unit.UnitTestElement, Microsoft.VisualStudio.QualityTools.Tips.UnitTest.ObjectModel, Version=10.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a" />
|
||||
<TestLink id="566be3e3-7344-2506-a01e-b2858b86453f" name="Test_Sftp_DeleteDirectory_Which_No_Permissions" storage="renci.sshnet.tests\bin\debug\renci.sshnet.tests.dll" type="Microsoft.VisualStudio.TestTools.TestTypes.Unit.UnitTestElement, Microsoft.VisualStudio.QualityTools.Tips.UnitTest.ObjectModel, Version=10.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a" />
|
||||
<TestLink id="a3afb0a2-ca8b-d745-4584-8564f70689eb" name="Test_Sftp_DeleteDirectory_Which_Doesnt_Exists" storage="renci.sshnet.tests\bin\debug\renci.sshnet.tests.dll" type="Microsoft.VisualStudio.TestTools.TestTypes.Unit.UnitTestElement, Microsoft.VisualStudio.QualityTools.Tips.UnitTest.ObjectModel, Version=10.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a" />
|
||||
<TestLink id="69e19f40-2e27-b25b-db00-4f960242a34b" name="Test_Sftp_ListDirectory_Without_Connecting" storage="renci.sshnet.tests\bin\debug\renci.sshnet.tests.dll" type="Microsoft.VisualStudio.TestTools.TestTypes.Unit.UnitTestElement, Microsoft.VisualStudio.QualityTools.Tips.UnitTest.ObjectModel, Version=10.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a" />
|
||||
<TestLink id="abe06631-df5e-2d93-a0a9-f8e7f62a52b6" name="Test_Get_File_Null" storage="renci.sshnet.tests\bin\debug\renci.sshnet.tests.dll" type="Microsoft.VisualStudio.TestTools.TestTypes.Unit.UnitTestElement, Microsoft.VisualStudio.QualityTools.Tips.UnitTest.ObjectModel, Version=10.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a" />
|
||||
</TestLinks>
|
||||
</TestList>
|
||||
<TestList name="Lists of Tests" id="8c43106b-9dc1-4907-a29f-aa66a61bf5b6" />
|
||||
</TestLists>
|
||||
@@ -0,0 +1,38 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using Renci.SshNet.Security.Cryptography;
|
||||
|
||||
namespace Renci.SshNet
|
||||
{
|
||||
/// <summary>
|
||||
/// Holds information about key size and cipher to use
|
||||
/// </summary>
|
||||
public class CipherInfo
|
||||
{
|
||||
/// <summary>
|
||||
/// Gets the size of the key.
|
||||
/// </summary>
|
||||
/// <value>
|
||||
/// The size of the key.
|
||||
/// </value>
|
||||
public int KeySize { get; private set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets the cipher.
|
||||
/// </summary>
|
||||
public Func<byte[], byte[], BlockCipher> Cipher { get; private set; }
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="CipherInfo"/> class.
|
||||
/// </summary>
|
||||
/// <param name="keySize">Size of the key.</param>
|
||||
/// <param name="cipher">The cipher.</param>
|
||||
public CipherInfo(int keySize, Func<byte[], byte[], BlockCipher> cipher)
|
||||
{
|
||||
this.KeySize = keySize;
|
||||
this.Cipher = (key, iv) => (cipher(key.Take(this.KeySize / 8).ToArray(), iv));
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,216 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
|
||||
namespace Renci.SshNet.Common
|
||||
{
|
||||
/// <summary>
|
||||
/// Base class for DER encoded data.
|
||||
/// </summary>
|
||||
public abstract class DerData
|
||||
{
|
||||
private const byte CONSTRUCTED = 0x20;
|
||||
|
||||
private const byte BOOLEAN = 0x01;
|
||||
private const byte INTEGER = 0x02;
|
||||
private const byte BITSTRING = 0x03;
|
||||
private const byte OCTETSTRING = 0x04;
|
||||
private const byte NULL = 0x05;
|
||||
private const byte OBJECTIDENTIFIER = 0x06;
|
||||
private const byte EXTERNAL = 0x08;
|
||||
private const byte ENUMERATED = 0x0a;
|
||||
private const byte SEQUENCE = 0x10;
|
||||
private const byte SEQUENCEOF = 0x10; // for completeness
|
||||
private const byte SET = 0x11;
|
||||
private const byte SETOF = 0x11; // for completeness
|
||||
|
||||
private const byte NUMERICSTRING = 0x12;
|
||||
private const byte PRINTABLESTRING = 0x13;
|
||||
private const byte T61STRING = 0x14;
|
||||
private const byte VIDEOTEXSTRING = 0x15;
|
||||
private const byte IA5STRING = 0x16;
|
||||
private const byte UTCTIME = 0x17;
|
||||
private const byte GENERALIZEDTIME = 0x18;
|
||||
private const byte GRAPHICSTRING = 0x19;
|
||||
private const byte VISIBLESTRING = 0x1a;
|
||||
private const byte GENERALSTRING = 0x1b;
|
||||
private const byte UNIVERSALSTRING = 0x1c;
|
||||
private const byte BMPSTRING = 0x1e;
|
||||
private const byte UTF8STRING = 0x0c;
|
||||
private const byte APPLICATION = 0x40;
|
||||
private const byte TAGGED = 0x80;
|
||||
|
||||
private List<byte> _data;
|
||||
|
||||
private int _readerIndex = 0;
|
||||
|
||||
public byte[] Encode()
|
||||
{
|
||||
this._data = new List<byte>();
|
||||
|
||||
this.SaveData();
|
||||
|
||||
var length = this._data.Count();
|
||||
var lengthBytes = this.GetLength(length);
|
||||
|
||||
this._data.InsertRange(0, lengthBytes);
|
||||
this._data.Insert(0, CONSTRUCTED | SEQUENCE);
|
||||
|
||||
return this._data.ToArray();
|
||||
}
|
||||
|
||||
public void Decode(byte[] data)
|
||||
{
|
||||
this._data = new List<byte>(data);
|
||||
this._readerIndex = 0;
|
||||
var dataType = this.ReadByte();
|
||||
var length = this.ReadLength();
|
||||
|
||||
this.LoadData();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Called when type specific data need to be loaded.
|
||||
/// </summary>
|
||||
protected abstract void LoadData();
|
||||
|
||||
/// <summary>
|
||||
/// Called when type specific data need to be saved.
|
||||
/// </summary>
|
||||
protected abstract void SaveData();
|
||||
|
||||
/// <summary>
|
||||
/// Reads next mpint data type from internal buffer.
|
||||
/// </summary>
|
||||
/// <returns>mpint read.</returns>
|
||||
protected BigInteger ReadBigInt()
|
||||
{
|
||||
var type = this.ReadByte();
|
||||
if (type != INTEGER)
|
||||
throw new InvalidOperationException("Invalid data type, INTEGER(02) is expected.");
|
||||
|
||||
var length = this.ReadLength();
|
||||
|
||||
var data = this.ReadBytes(length);
|
||||
|
||||
return new BigInteger(data.Reverse().ToArray());
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Writes uint32 data into internal buffer.
|
||||
/// </summary>
|
||||
/// <param name="data">uint32 data to write.</param>
|
||||
protected void Write(UInt32 data)
|
||||
{
|
||||
var bytes = data.GetBytes();
|
||||
this._data.Add(INTEGER);
|
||||
var length = this.GetLength(bytes.Length);
|
||||
this.WriteBytes(length);
|
||||
this.WriteBytes(bytes);
|
||||
}
|
||||
|
||||
protected void Write(BigInteger data)
|
||||
{
|
||||
var bytes = data.ToByteArray().Reverse().ToList();
|
||||
this._data.Add(INTEGER);
|
||||
var length = this.GetLength(bytes.Count);
|
||||
this.WriteBytes(length);
|
||||
this.WriteBytes(bytes);
|
||||
}
|
||||
|
||||
protected void Write(DerData data)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
private byte[] GetLength(int length)
|
||||
{
|
||||
if (length > 127)
|
||||
{
|
||||
int size = 1;
|
||||
int val = length;
|
||||
|
||||
while ((val >>= 8) != 0)
|
||||
size++;
|
||||
|
||||
var data = new byte[size];
|
||||
data[0] = (byte)(size | 0x80);
|
||||
|
||||
for (int i = (size - 1) * 8, j = 1; i >= 0; i -= 8, j++)
|
||||
{
|
||||
data[j] = (byte)(length >> i);
|
||||
}
|
||||
|
||||
return data;
|
||||
}
|
||||
else
|
||||
{
|
||||
return new byte[] { (byte)length };
|
||||
}
|
||||
}
|
||||
|
||||
private int ReadLength()
|
||||
{
|
||||
int length = this.ReadByte();
|
||||
|
||||
if (length == 0x80)
|
||||
{
|
||||
throw new NotSupportedException("Indefinite-length encoding is not supported.");
|
||||
}
|
||||
|
||||
if (length > 127)
|
||||
{
|
||||
int size = length & 0x7f;
|
||||
|
||||
// Note: The invalid long form "0xff" (see X.690 8.1.3.5c) will be caught here
|
||||
if (size > 4)
|
||||
throw new InvalidOperationException(string.Format("DER length is '{0}' and cannot be more than 4 bytes.", size));
|
||||
|
||||
length = 0;
|
||||
for (int i = 0; i < size; i++)
|
||||
{
|
||||
int next = this.ReadByte();
|
||||
|
||||
length = (length << 8) + next;
|
||||
}
|
||||
|
||||
if (length < 0)
|
||||
throw new InvalidOperationException("Corrupted data - negative length found");
|
||||
|
||||
//if (length >= limit) // after all we must have read at least 1 byte
|
||||
// throw new IOException("Corrupted stream - out of bounds length found");
|
||||
}
|
||||
|
||||
return length;
|
||||
}
|
||||
|
||||
private void WriteBytes(IEnumerable<byte> data)
|
||||
{
|
||||
this._data.AddRange(data);
|
||||
}
|
||||
|
||||
private byte ReadByte()
|
||||
{
|
||||
if (this._readerIndex > this._data.Count)
|
||||
throw new InvalidOperationException("Read out of boundaries.");
|
||||
|
||||
return this._data[this._readerIndex++];
|
||||
}
|
||||
|
||||
private byte[] ReadBytes(int length)
|
||||
{
|
||||
if (this._readerIndex + length > this._data.Count)
|
||||
throw new InvalidOperationException("Read out of boundaries.");
|
||||
|
||||
var result = new byte[length];
|
||||
this._data.CopyTo(this._readerIndex, result, 0, length);
|
||||
this._readerIndex += length;
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
@@ -1,4 +1,5 @@
|
||||
using System;
|
||||
using System.Linq;
|
||||
using System.Collections.Generic;
|
||||
using System.Collections.ObjectModel;
|
||||
using Renci.SshNet.Security;
|
||||
@@ -9,10 +10,14 @@ using Renci.SshNet.Common;
|
||||
using System.Threading;
|
||||
using System.Net;
|
||||
using Renci.SshNet.Messages.Connection;
|
||||
using Renci.SshNet.Security.Cryptography.Ciphers;
|
||||
using System.Security.Cryptography;
|
||||
using Renci.SshNet.Security.Cryptography;
|
||||
using Renci.SshNet.Security.Cryptography.Ciphers.Modes;
|
||||
namespace Renci.SshNet
|
||||
{
|
||||
/// <summary>
|
||||
/// Represents remote connection infroamtion base class.
|
||||
/// Represents remote connection information base class.
|
||||
/// </summary>
|
||||
public abstract class ConnectionInfo
|
||||
{
|
||||
@@ -47,12 +52,12 @@ namespace Renci.SshNet
|
||||
/// <summary>
|
||||
/// Gets supported encryptions for this connection.
|
||||
/// </summary>
|
||||
public IDictionary<string, Type> Encryptions { get; private set; }
|
||||
public IDictionary<string, CipherInfo> Encryptions { get; private set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets supported hash algorithms for this connection.
|
||||
/// </summary>
|
||||
public IDictionary<string, Type> HmacAlgorithms { get; private set; }
|
||||
public IDictionary<string, Func<byte[], HashAlgorithm>> HmacAlgorithms { get; private set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets supported host key algorithms for this connection.
|
||||
@@ -136,35 +141,35 @@ namespace Renci.SshNet
|
||||
{"diffie-hellman-group1-sha1", typeof(KeyExchangeDiffieHellmanGroup1Sha1)},
|
||||
};
|
||||
|
||||
this.Encryptions = new Dictionary<string, Type>()
|
||||
this.Encryptions = new Dictionary<string, CipherInfo>()
|
||||
{
|
||||
{"3des-cbc", typeof(CipherTripleDes192Cbc)},
|
||||
{"aes128-cbc", typeof(CipherAes128Cbc)},
|
||||
{"aes192-cbc", typeof(CipherAes192Cbc)},
|
||||
{"aes256-cbc", typeof(CipherAes256Cbc)},
|
||||
{"blowfish-cbc", typeof(CipherBlowfish)},
|
||||
//{"twofish-cbc", typeof(...)},
|
||||
//{"twofish192-cbc", typeof(...)},
|
||||
//{"twofish128-cbc", typeof(...)},
|
||||
//{"twofish256-cbc", typeof(...)},
|
||||
//{"serpent256-cbc", typeof(CipherSerpent256CBC)},
|
||||
//{"serpent192-cbc", typeof(...)},
|
||||
//{"serpent128-cbc", typeof(...)},
|
||||
//{"arcfour128", typeof(...)},
|
||||
//{"arcfour256", typeof(...)},
|
||||
//{"arcfour", typeof(...)},
|
||||
//{"idea-cbc", typeof(...)},
|
||||
{"cast128-cbc", typeof(CipherCast128Cbc)},
|
||||
//{"rijndael-cbc@lysator.liu.se", typeof(...)},
|
||||
{"aes128-ctr", typeof(CipherAes128Ctr)},
|
||||
{"aes192-ctr", typeof(CipherAes192Ctr)},
|
||||
{"aes256-ctr", typeof(CipherAes256Ctr)},
|
||||
{"3des-cbc", new CipherInfo(192, (key, iv)=>{ return new TripleDesCipher(key, new CbcCipherMode(iv), null); }) },
|
||||
{"aes128-cbc", new CipherInfo(128, (key, iv)=>{ return new AesCipher(key, new CbcCipherMode(iv), null); }) },
|
||||
{"aes192-cbc", new CipherInfo(192, (key, iv)=>{ return new AesCipher(key, new CbcCipherMode(iv), null); }) },
|
||||
{"aes256-cbc", new CipherInfo(256, (key, iv)=>{ return new AesCipher(key, new CbcCipherMode(iv), null); }) },
|
||||
{"blowfish-cbc", new CipherInfo(128, (key, iv)=>{ return new BlowfishCipher(key, new CbcCipherMode(iv), null); }) },
|
||||
////{"twofish-cbc", typeof(...)},
|
||||
////{"twofish192-cbc", typeof(...)},
|
||||
////{"twofish128-cbc", typeof(...)},
|
||||
////{"twofish256-cbc", typeof(...)},
|
||||
////{"serpent256-cbc", typeof(CipherSerpent256CBC)},
|
||||
////{"serpent192-cbc", typeof(...)},
|
||||
////{"serpent128-cbc", typeof(...)},
|
||||
////{"arcfour128", typeof(...)},
|
||||
////{"arcfour256", typeof(...)},
|
||||
////{"arcfour", typeof(...)},
|
||||
////{"idea-cbc", typeof(...)},
|
||||
{"cast128-cbc", new CipherInfo(128, (key, iv)=>{ return new CastCipher(key, new CbcCipherMode(iv), null); }) },
|
||||
////{"rijndael-cbc@lysator.liu.se", typeof(...)},
|
||||
{"aes128-ctr", new CipherInfo(128, (key, iv)=>{ return new AesCipher(key, new CtrCipherMode(iv), null); }) },
|
||||
{"aes192-ctr", new CipherInfo(192, (key, iv)=>{ return new AesCipher(key, new CtrCipherMode(iv), null); }) },
|
||||
{"aes256-ctr", new CipherInfo(256, (key, iv)=>{ return new AesCipher(key, new CtrCipherMode(iv), null); }) },
|
||||
};
|
||||
|
||||
this.HmacAlgorithms = new Dictionary<string, Type>()
|
||||
this.HmacAlgorithms = new Dictionary<string, Func<byte[], HashAlgorithm>>()
|
||||
{
|
||||
{"hmac-md5", typeof(HMacMD5)},
|
||||
{"hmac-sha1", typeof(HMacSha1)},
|
||||
{"hmac-md5", (key) => { return new HMac<MD5Hash>(key.Take(16).ToArray());}},
|
||||
{"hmac-sha1", (key) => { return new HMac<SHA1Hash>(key.Take(20).ToArray());}},
|
||||
//{"umac-64@openssh.com", typeof(HMacSha1)},
|
||||
//{"hmac-ripemd160", typeof(HMacSha1)},
|
||||
//{"hmac-ripemd160@openssh.com", typeof(HMacSha1)},
|
||||
@@ -176,10 +181,7 @@ namespace Renci.SshNet
|
||||
this.HostKeyAlgorithms = new Dictionary<string, Type>()
|
||||
{
|
||||
{"ssh-rsa", typeof(CryptoPublicKeyRsa)},
|
||||
#if SILVERLIGHT
|
||||
#else
|
||||
{"ssh-dss", typeof(CryptoPublicKeyDss)},
|
||||
#endif
|
||||
};
|
||||
|
||||
this.AuthenticationMethods = new Dictionary<string, Type>()
|
||||
|
||||
+3
@@ -5,6 +5,9 @@ using System.Text;
|
||||
|
||||
namespace Renci.SshNet.Messages.Connection
|
||||
{
|
||||
/// <summary>
|
||||
/// Represents "eow@openssh.com" type channel request information
|
||||
/// </summary>
|
||||
public class EndOfWriteRequestInfo : RequestInfo
|
||||
{
|
||||
/// <summary>
|
||||
|
||||
@@ -10,6 +10,9 @@ using System.Security;
|
||||
using Renci.SshNet.Common;
|
||||
using System.Globalization;
|
||||
using Renci.SshNet.Security.Cryptography;
|
||||
using Renci.SshNet.Security.Cryptography.Ciphers;
|
||||
using Renci.SshNet.Security.Cryptography.Ciphers.Modes;
|
||||
using Renci.SshNet.Security.Cryptography.Ciphers.Paddings;
|
||||
|
||||
namespace Renci.SshNet
|
||||
{
|
||||
@@ -152,27 +155,30 @@ namespace Renci.SshNet
|
||||
for (int i = 0; i < binarySalt.Length; i++)
|
||||
binarySalt[i] = Convert.ToByte(salt.Substring(i * 2, 2), 16);
|
||||
|
||||
Cipher cipher = null;
|
||||
CipherInfo cipher = null;
|
||||
switch (cipherName)
|
||||
{
|
||||
case "DES-EDE3-CBC":
|
||||
cipher = new CipherTripleDes192Cbc();
|
||||
cipher = new CipherInfo(192, (key, iv) => { return new TripleDesCipher(key, new CbcCipherMode(iv), new PKCS7Padding()); });
|
||||
break;
|
||||
case "DES-EDE3-CFB":
|
||||
cipher = new CipherInfo(192, (key, iv) => { return new TripleDesCipher(key, new CfbCipherMode(iv), new PKCS7Padding()); });
|
||||
break;
|
||||
case "DES-CBC":
|
||||
// TODO: Not tested
|
||||
cipher = new CipherDes64Cbc();
|
||||
cipher = new CipherInfo(64, (key, iv) => { return new DesCipher(key, new CbcCipherMode(iv), new PKCS7Padding()); });
|
||||
break;
|
||||
case "AES-128-CBC":
|
||||
// TODO: Not tested
|
||||
cipher = new CipherAes128Cbc();
|
||||
cipher = new CipherInfo(128, (key, iv) => { return new AesCipher(key, new CbcCipherMode(iv), new PKCS7Padding()); });
|
||||
break;
|
||||
case "AES-192-CBC":
|
||||
// TODO: Not tested
|
||||
cipher = new CipherAes192Cbc();
|
||||
cipher = new CipherInfo(192, (key, iv) => { return new AesCipher(key, new CbcCipherMode(iv), new PKCS7Padding()); });
|
||||
break;
|
||||
case "AES-256-CBC":
|
||||
// TODO: Not tested
|
||||
cipher = new CipherAes256Cbc();
|
||||
cipher = new CipherInfo(256, (key, iv) => { return new AesCipher(key, new CbcCipherMode(iv), new PKCS7Padding()); });
|
||||
break;
|
||||
default:
|
||||
throw new SshException(string.Format(CultureInfo.CurrentCulture, "Unknown private key cipher \"{0}\".", cipherName));
|
||||
@@ -190,12 +196,9 @@ namespace Renci.SshNet
|
||||
case "RSA":
|
||||
this._key = new CryptoPrivateKeyRsa();
|
||||
break;
|
||||
#if SILVERLIGHT
|
||||
#else
|
||||
case "DSA":
|
||||
this._key = new CryptoPrivateKeyDss();
|
||||
break;
|
||||
#endif
|
||||
default:
|
||||
throw new NotSupportedException(string.Format(CultureInfo.CurrentCulture, "Key '{0}' is not supported.", keyName));
|
||||
}
|
||||
@@ -206,12 +209,12 @@ namespace Renci.SshNet
|
||||
/// <summary>
|
||||
/// Decrypts encrypted private key file data.
|
||||
/// </summary>
|
||||
/// <param name="cipher">Encryption cipher.</param>
|
||||
/// <param name="cipherInfo">The cipher info.</param>
|
||||
/// <param name="cipherData">Encrypted data.</param>
|
||||
/// <param name="passPhrase">Decryption pass phrase.</param>
|
||||
/// <param name="binarySalt">Decryption binary salt.</param>
|
||||
/// <returns></returns>
|
||||
public static IEnumerable<byte> DecryptKey(Cipher cipher, byte[] cipherData, string passPhrase, byte[] binarySalt)
|
||||
public static IEnumerable<byte> DecryptKey(CipherInfo cipherInfo, byte[] cipherData, string passPhrase, byte[] binarySalt)
|
||||
{
|
||||
List<byte> cipherKey = new List<byte>();
|
||||
|
||||
@@ -225,7 +228,7 @@ namespace Renci.SshNet
|
||||
|
||||
cipherKey.AddRange(hash);
|
||||
|
||||
while (cipherKey.Count < cipher.KeySize / 8)
|
||||
while (cipherKey.Count < cipherInfo.KeySize / 8)
|
||||
{
|
||||
hash = hash.Concat(initVector);
|
||||
|
||||
@@ -235,7 +238,7 @@ namespace Renci.SshNet
|
||||
}
|
||||
}
|
||||
|
||||
cipher.Init(cipherKey, binarySalt);
|
||||
var cipher = cipherInfo.Cipher(cipherKey.ToArray(), binarySalt);
|
||||
|
||||
return cipher.Decrypt(cipherData);
|
||||
}
|
||||
|
||||
@@ -64,6 +64,7 @@
|
||||
<ItemGroup>
|
||||
<Compile Include="Channels\ChannelDirectTcpip.NET40.cs" />
|
||||
<Compile Include="Channels\ChannelForwardedTcpip.NET40.cs" />
|
||||
<Compile Include="CipherInfo.cs" />
|
||||
<Compile Include="Common\ASCIIEncoding.cs" />
|
||||
<Compile Include="Common\ASCIIEncoding.NET40.cs">
|
||||
<SubType>Code</SubType>
|
||||
@@ -81,6 +82,7 @@
|
||||
<Compile Include="Common\ChannelEventArgs.cs" />
|
||||
<Compile Include="Common\ChannelOpenFailedEventArgs.cs" />
|
||||
<Compile Include="Common\ChannelRequestEventArgs.cs" />
|
||||
<Compile Include="Common\DerData.cs" />
|
||||
<Compile Include="Common\SemaphoreLight.cs">
|
||||
<SubType>Code</SubType>
|
||||
</Compile>
|
||||
@@ -108,58 +110,45 @@
|
||||
<Compile Include="Security\Algorithm.cs">
|
||||
<SubType>Code</SubType>
|
||||
</Compile>
|
||||
<Compile Include="Security\Cipher.cs">
|
||||
<SubType>Code</SubType>
|
||||
</Compile>
|
||||
<Compile Include="Security\CipherAesCbc.cs">
|
||||
<SubType>Code</SubType>
|
||||
</Compile>
|
||||
<Compile Include="Security\CipherAesCtr.cs">
|
||||
<SubType>Code</SubType>
|
||||
</Compile>
|
||||
<Compile Include="Security\CipherBlowfish.cs">
|
||||
<SubType>Code</SubType>
|
||||
</Compile>
|
||||
<Compile Include="Security\CipherCastCbc.cs">
|
||||
<SubType>Code</SubType>
|
||||
</Compile>
|
||||
<Compile Include="Security\CipherDesCbc.cs">
|
||||
<SubType>Code</SubType>
|
||||
</Compile>
|
||||
<Compile Include="Security\CipherSerpent.cs">
|
||||
<SubType>Code</SubType>
|
||||
</Compile>
|
||||
<Compile Include="Security\CipherTripleDesCbc.cs">
|
||||
<SubType>Code</SubType>
|
||||
</Compile>
|
||||
<Compile Include="Security\Cryptography\AsymmetricCipher.cs">
|
||||
<SubType>Code</SubType>
|
||||
</Compile>
|
||||
<Compile Include="Security\Cryptography\CipherDigitalSignature.cs" />
|
||||
<Compile Include="Security\Cryptography\Ciphers\AesCipher.cs" />
|
||||
<Compile Include="Security\Cryptography\Ciphers\Arc4Cipher.cs" />
|
||||
<Compile Include="Security\Cryptography\AsymmetricCipher.cs" />
|
||||
<Compile Include="Security\Cryptography\BlockCipher.cs" />
|
||||
<Compile Include="Security\Cryptography\Ciphers\BlowfishCipher.cs" />
|
||||
<Compile Include="Security\Cryptography\Ciphers\CastCipher.cs" />
|
||||
<Compile Include="Security\Cryptography\Cipher.cs" />
|
||||
<Compile Include="Security\Cryptography\Ciphers\CipherMode.cs" />
|
||||
<Compile Include="Security\Cryptography\Ciphers\CipherPadding.cs" />
|
||||
<Compile Include="Security\Cryptography\Ciphers\DesCipher.cs" />
|
||||
<Compile Include="Security\Cryptography\Ciphers\Modes\CbcCipherMode.cs" />
|
||||
<Compile Include="Security\Cryptography\Ciphers\Modes\CfbCipherMode.cs" />
|
||||
<Compile Include="Security\Cryptography\Ciphers\Modes\CtrCipherMode.cs" />
|
||||
<Compile Include="Security\Cryptography\Ciphers\Modes\OfbCipherMode.cs" />
|
||||
<Compile Include="Security\Cryptography\Ciphers\Paddings\PKCS7Padding.cs" />
|
||||
<Compile Include="Security\Cryptography\Ciphers\RsaCipher.cs" />
|
||||
<Compile Include="Security\Cryptography\Ciphers\SerpentCipher.cs" />
|
||||
<Compile Include="Security\Cryptography\DsaDigitalSignature.cs" />
|
||||
<Compile Include="Security\Cryptography\StreamCipher.cs" />
|
||||
<Compile Include="Security\Cryptography\SymmetricCipher.cs" />
|
||||
<Compile Include="Security\Cryptography\Ciphers\TripleDesCipher.cs" />
|
||||
<Compile Include="Security\Cryptography\Ciphers\TwofishCipher.cs" />
|
||||
<Compile Include="Security\Cryptography\DigitalSignature.cs">
|
||||
<SubType>Code</SubType>
|
||||
</Compile>
|
||||
<Compile Include="Security\Cryptography\HMAC.cs">
|
||||
<Compile Include="Security\Cryptography\HMac.cs">
|
||||
<SubType>Code</SubType>
|
||||
</Compile>
|
||||
<Compile Include="Security\Cryptography\MD5Hash.cs">
|
||||
<Compile Include="Security\Cryptography\Hashes\MD5Hash.cs">
|
||||
<SubType>Code</SubType>
|
||||
</Compile>
|
||||
<Compile Include="Security\Cryptography\RSACipher.cs">
|
||||
<Compile Include="Security\Cryptography\RsaDigitalSignature.cs">
|
||||
<SubType>Code</SubType>
|
||||
</Compile>
|
||||
<Compile Include="Security\Cryptography\RSADigitalSignature.cs">
|
||||
<Compile Include="Security\Cryptography\Hashes\SHA1Hash.cs">
|
||||
<SubType>Code</SubType>
|
||||
</Compile>
|
||||
<Compile Include="Security\Cryptography\RSAPrivateKey.cs">
|
||||
<SubType>Code</SubType>
|
||||
</Compile>
|
||||
<Compile Include="Security\Cryptography\RSAPublicKey.cs">
|
||||
<SubType>Code</SubType>
|
||||
</Compile>
|
||||
<Compile Include="Security\Cryptography\SHA1Hash.cs">
|
||||
<SubType>Code</SubType>
|
||||
</Compile>
|
||||
<Compile Include="Security\Cryptography\SHA256Hash.cs">
|
||||
<Compile Include="Security\Cryptography\Hashes\SHA256Hash.cs">
|
||||
<SubType>Code</SubType>
|
||||
</Compile>
|
||||
<Compile Include="Security\CryptoKey.cs">
|
||||
@@ -183,13 +172,6 @@
|
||||
<Compile Include="Security\CryptoPublicKeyRsa.cs">
|
||||
<SubType>Code</SubType>
|
||||
</Compile>
|
||||
<Compile Include="Security\HMac.cs">
|
||||
<SubType>Code</SubType>
|
||||
</Compile>
|
||||
<Compile Include="Security\HMacMD5.cs">
|
||||
<SubType>Code</SubType>
|
||||
</Compile>
|
||||
<Compile Include="Security\HMacSha1.cs" />
|
||||
<Compile Include="Security\KeyExchange.cs">
|
||||
<SubType>Code</SubType>
|
||||
</Compile>
|
||||
@@ -238,20 +220,6 @@
|
||||
<Compile Include="Messages\Connection\ChannelRequest\XonXoffRequestInfo.cs" />
|
||||
<Compile Include="Messages\MessageAttribute.cs" />
|
||||
<Compile Include="NoneConnectionInfo.cs" />
|
||||
<Compile Include="Security\Cryptography\Ciphers\AesCipher.cs" />
|
||||
<Compile Include="Security\Cryptography\Ciphers\BlowfishCipher.cs" />
|
||||
<Compile Include="Security\Cryptography\Ciphers\CastCipher.cs" />
|
||||
<Compile Include="Security\Cryptography\Ciphers\SerpentCipher.cs" />
|
||||
<Compile Include="Security\Cryptography\Ciphers\TwofishCipher.cs" />
|
||||
<Compile Include="Security\Cryptography\Modes\CfbMode.cs" />
|
||||
<Compile Include="Security\Cryptography\Modes\CipherModeEx.cs" />
|
||||
<Compile Include="Security\Cryptography\Modes\ModeBase.cs" />
|
||||
<Compile Include="Security\Cryptography\Modes\CbcMode.cs" />
|
||||
<Compile Include="Security\Cryptography\Ciphers\CipherBase.cs" />
|
||||
<Compile Include="Security\Cryptography\Ciphers\TripleDesCipher.cs" />
|
||||
<Compile Include="Security\Cryptography\Modes\CtrMode.cs" />
|
||||
<Compile Include="Security\Cryptography\Modes\OfbMode.cs" />
|
||||
<Compile Include="Security\Cryptography\Ciphers\DesCipher.cs" />
|
||||
<Compile Include="Sftp\Flags.cs" />
|
||||
<Compile Include="Sftp\SftpDataMessage.cs">
|
||||
<SubType>Code</SubType>
|
||||
@@ -411,6 +379,7 @@
|
||||
<ItemGroup>
|
||||
<Content Include="Documentation\SshClient.shfbproj" />
|
||||
</ItemGroup>
|
||||
<ItemGroup />
|
||||
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
|
||||
<!-- To modify your build process, add your task inside one of the targets below and uncomment it.
|
||||
Other similar extension points exist, see Microsoft.Common.targets.
|
||||
|
||||
@@ -102,37 +102,13 @@ namespace Renci.SshNet.Security
|
||||
/// <returns></returns>
|
||||
public override byte[] GetSignature(IEnumerable<byte> key)
|
||||
{
|
||||
var data = key.ToArray();
|
||||
//using (var sha1 = new Renci.SshNet.Security.Cryptography.SHA1Hash())
|
||||
using (var sha1 = new System.Security.Cryptography.SHA1CryptoServiceProvider())
|
||||
var ss1 = new DsaDigitalSignature(this._p, this._q, this._g, this._privateKey, null);
|
||||
var signature = ss1.CreateSignature(key.ToArray());
|
||||
return new SignatureKeyData
|
||||
{
|
||||
using (var cs = new System.Security.Cryptography.CryptoStream(System.IO.Stream.Null, sha1, System.Security.Cryptography.CryptoStreamMode.Write))
|
||||
{
|
||||
cs.Write(data, 0, data.Length);
|
||||
}
|
||||
|
||||
var dsaKeyInfo = new System.Security.Cryptography.DSAParameters();
|
||||
|
||||
dsaKeyInfo.X = this._privateKey.TrimLeadingZero().ToArray();
|
||||
dsaKeyInfo.P = this._p.TrimLeadingZero().ToArray();
|
||||
dsaKeyInfo.Q = this._q.TrimLeadingZero().ToArray();
|
||||
dsaKeyInfo.G = this._g.TrimLeadingZero().ToArray();
|
||||
|
||||
using (var DSA = new System.Security.Cryptography.DSACryptoServiceProvider())
|
||||
{
|
||||
DSA.ImportParameters(dsaKeyInfo);
|
||||
var DSAFormatter = new DSASignatureFormatter(DSA);
|
||||
DSAFormatter.SetHashAlgorithm("SHA1");
|
||||
|
||||
var signature = DSAFormatter.CreateSignature(sha1);
|
||||
|
||||
return new SignatureKeyData
|
||||
{
|
||||
AlgorithmName = this.Name,
|
||||
Signature = signature,
|
||||
}.GetBytes().ToArray();
|
||||
}
|
||||
}
|
||||
AlgorithmName = this.Name,
|
||||
Signature = signature,
|
||||
}.GetBytes().ToArray();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
||||
@@ -4,6 +4,7 @@ using System.IO;
|
||||
using System.Linq;
|
||||
using Renci.SshNet.Common;
|
||||
using Renci.SshNet.Security.Cryptography;
|
||||
using Renci.SshNet.Security.Cryptography.Ciphers;
|
||||
|
||||
namespace Renci.SshNet.Security
|
||||
{
|
||||
@@ -113,7 +114,7 @@ namespace Renci.SshNet.Security
|
||||
/// <returns></returns>
|
||||
public override byte[] GetSignature(IEnumerable<byte> key)
|
||||
{
|
||||
var signature = new RSADigitalSignature(new RSAPrivateKey(this._exponent, this._modulus, this._dValue, this._dpValue, this._qValue, this._dqValue, this._pValue, this._inverseQ));
|
||||
var signature = new RsaDigitalSignature(this._exponent, this._modulus, this._dValue, this._dpValue, this._dqValue, this._inverseQ, this._pValue, this._qValue);
|
||||
|
||||
return new SignatureKeyData
|
||||
{
|
||||
|
||||
@@ -4,13 +4,14 @@ using System.IO;
|
||||
using System.Linq;
|
||||
using System.Security.Cryptography;
|
||||
using Renci.SshNet.Common;
|
||||
using Renci.SshNet.Security.Cryptography;
|
||||
|
||||
namespace Renci.SshNet.Security
|
||||
{
|
||||
/// <summary>
|
||||
/// Represents DSS public key
|
||||
/// </summary>
|
||||
internal class CryptoPublicKeyDss : CryptoPublicKey
|
||||
public class CryptoPublicKeyDss : CryptoPublicKey
|
||||
{
|
||||
private byte[] _p;
|
||||
private byte[] _q;
|
||||
@@ -98,55 +99,34 @@ namespace Renci.SshNet.Security
|
||||
/// </returns>
|
||||
public override bool VerifySignature(IEnumerable<byte> hash, IEnumerable<byte> signature)
|
||||
{
|
||||
using (var sha1 = new SHA1CryptoServiceProvider())
|
||||
|
||||
long i = 0;
|
||||
long j = 0;
|
||||
byte[] tmp;
|
||||
var sig = signature.ToArray();
|
||||
if (sig[0] == 0 && sig[1] == 0 && sig[2] == 0)
|
||||
{
|
||||
using (var cs = new CryptoStream(System.IO.Stream.Null, sha1, CryptoStreamMode.Write))
|
||||
{
|
||||
var data = hash.ToArray();
|
||||
cs.Write(data, 0, data.Length);
|
||||
}
|
||||
long i1 = (sig[i++] << 24) & 0xff000000;
|
||||
long i2 = (sig[i++] << 16) & 0x00ff0000;
|
||||
long i3 = (sig[i++] << 8) & 0x0000ff00;
|
||||
long i4 = (sig[i++]) & 0x000000ff;
|
||||
j = i1 | i2 | i3 | i4;
|
||||
|
||||
using (var dsa = new DSACryptoServiceProvider())
|
||||
{
|
||||
dsa.ImportParameters(new DSAParameters
|
||||
{
|
||||
Y = _publicKey.TrimLeadingZero().ToArray(),
|
||||
P = _p.TrimLeadingZero().ToArray(),
|
||||
Q = _q.TrimLeadingZero().ToArray(),
|
||||
G = _g.TrimLeadingZero().ToArray(),
|
||||
});
|
||||
var dsaDeformatter = new DSASignatureDeformatter(dsa);
|
||||
dsaDeformatter.SetHashAlgorithm("SHA1");
|
||||
i += j;
|
||||
|
||||
long i = 0;
|
||||
long j = 0;
|
||||
byte[] tmp;
|
||||
i1 = (sig[i++] << 24) & 0xff000000;
|
||||
i2 = (sig[i++] << 16) & 0x00ff0000;
|
||||
i3 = (sig[i++] << 8) & 0x0000ff00;
|
||||
i4 = (sig[i++]) & 0x000000ff;
|
||||
j = i1 | i2 | i3 | i4;
|
||||
|
||||
var sig = signature.ToArray();
|
||||
if (sig[0] == 0 && sig[1] == 0 && sig[2] == 0)
|
||||
{
|
||||
long i1 = (sig[i++] << 24) & 0xff000000;
|
||||
long i2 = (sig[i++] << 16) & 0x00ff0000;
|
||||
long i3 = (sig[i++] << 8) & 0x0000ff00;
|
||||
long i4 = (sig[i++]) & 0x000000ff;
|
||||
j = i1 | i2 | i3 | i4;
|
||||
|
||||
i += j;
|
||||
|
||||
i1 = (sig[i++] << 24) & 0xff000000;
|
||||
i2 = (sig[i++] << 16) & 0x00ff0000;
|
||||
i3 = (sig[i++] << 8) & 0x0000ff00;
|
||||
i4 = (sig[i++]) & 0x000000ff;
|
||||
j = i1 | i2 | i3 | i4;
|
||||
|
||||
tmp = new byte[j];
|
||||
Array.Copy(sig, (int)i, tmp, 0, (int)j);
|
||||
sig = tmp;
|
||||
}
|
||||
|
||||
return dsaDeformatter.VerifySignature(sha1, sig);
|
||||
}
|
||||
tmp = new byte[j];
|
||||
Array.Copy(sig, (int)i, tmp, 0, (int)j);
|
||||
sig = tmp;
|
||||
}
|
||||
|
||||
var sig1 = new DsaDigitalSignature(_p, _q, _g, null, _publicKey);
|
||||
return sig1.VerifySignature(hash.ToArray(), sig);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
||||
@@ -5,13 +5,14 @@ using System.Linq;
|
||||
using System.Security.Cryptography;
|
||||
using Renci.SshNet.Common;
|
||||
using Renci.SshNet.Security.Cryptography;
|
||||
using Renci.SshNet.Security.Cryptography.Ciphers;
|
||||
|
||||
namespace Renci.SshNet.Security
|
||||
{
|
||||
/// <summary>
|
||||
/// Represents RSA public key
|
||||
/// </summary>
|
||||
internal class CryptoPublicKeyRsa : CryptoPublicKey
|
||||
public class CryptoPublicKeyRsa : CryptoPublicKey
|
||||
{
|
||||
private byte[] _modulus;
|
||||
|
||||
@@ -111,7 +112,7 @@ namespace Renci.SshNet.Security
|
||||
sig = tmp;
|
||||
}
|
||||
|
||||
var sig1 = new RSADigitalSignature(new RSAPublicKey(this._exponent, this._modulus));
|
||||
var sig1 = new RsaDigitalSignature(this._exponent, this._modulus);
|
||||
|
||||
return sig1.VerifySignature(hash.ToArray(), sig);
|
||||
|
||||
|
||||
@@ -2,27 +2,13 @@
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using Renci.SshNet.Common;
|
||||
|
||||
namespace Renci.SshNet.Security.Cryptography
|
||||
{
|
||||
/// <summary>
|
||||
/// Base class for asymmetric cipher implementation
|
||||
/// Base class for asymmetric cipher implementations.
|
||||
/// </summary>
|
||||
public abstract class AsymmetricCipher
|
||||
public abstract class AsymmetricCipher : Cipher
|
||||
{
|
||||
/// <summary>
|
||||
/// Transforms the specified input.
|
||||
/// </summary>
|
||||
/// <param name="input">The input.</param>
|
||||
/// <returns></returns>
|
||||
public abstract byte[] Transform(byte[] input);
|
||||
|
||||
/// <summary>
|
||||
/// Transforms the specified input.
|
||||
/// </summary>
|
||||
/// <param name="input">The input.</param>
|
||||
/// <returns></returns>
|
||||
public abstract BigInteger Transform(BigInteger input);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,129 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using Renci.SshNet.Security.Cryptography.Ciphers;
|
||||
|
||||
namespace Renci.SshNet.Security.Cryptography
|
||||
{
|
||||
/// <summary>
|
||||
/// Base class for block cipher implementations.
|
||||
/// </summary>
|
||||
public abstract class BlockCipher : SymmetricCipher
|
||||
{
|
||||
private CipherMode _mode;
|
||||
|
||||
private CipherPadding _padding;
|
||||
|
||||
/// <summary>
|
||||
/// Gets the size of the block in bytes.
|
||||
/// </summary>
|
||||
/// <value>
|
||||
/// The size of the block in bytes.
|
||||
/// </value>
|
||||
public abstract int BlockSize { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="BlockCipher"/> class.
|
||||
/// </summary>
|
||||
/// <param name="key">The key.</param>
|
||||
/// <param name="mode">Cipher mode.</param>
|
||||
/// <param name="padding">Cipher padding.</param>
|
||||
protected BlockCipher(byte[] key, CipherMode mode, CipherPadding padding)
|
||||
: base(key)
|
||||
{
|
||||
this._mode = mode;
|
||||
this._padding = padding;
|
||||
|
||||
this._mode.Init(this);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Encrypts the specified data.
|
||||
/// </summary>
|
||||
/// <param name="data">The data.</param>
|
||||
/// <returns>Encrypted data</returns>
|
||||
public override byte[] Encrypt(byte[] data)
|
||||
{
|
||||
var output = new byte[data.Length];
|
||||
|
||||
if (data.Length % this.BlockSize > 0)
|
||||
{
|
||||
if (this._padding == null)
|
||||
{
|
||||
throw new ArgumentException("data");
|
||||
}
|
||||
else
|
||||
{
|
||||
data = this._padding.Pad(this.BlockSize, data);
|
||||
}
|
||||
}
|
||||
|
||||
var writtenBytes = 0;
|
||||
|
||||
for (int i = 0; i < data.Length / this.BlockSize; i++)
|
||||
{
|
||||
if (this._mode == null)
|
||||
{
|
||||
writtenBytes += this.EncryptBlock(data, i * this.BlockSize, this.BlockSize, output, i * this.BlockSize);
|
||||
}
|
||||
else
|
||||
{
|
||||
writtenBytes += this._mode.EncryptBlock(data, i * this.BlockSize, this.BlockSize, output, i * this.BlockSize);
|
||||
}
|
||||
}
|
||||
|
||||
if (writtenBytes < data.Length)
|
||||
{
|
||||
throw new InvalidOperationException("Encryption error.");
|
||||
}
|
||||
|
||||
return output;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Decrypts the specified data.
|
||||
/// </summary>
|
||||
/// <param name="data">The data.</param>
|
||||
/// <returns>Decrypted data</returns>
|
||||
public override byte[] Decrypt(byte[] data)
|
||||
{
|
||||
if (data.Length % this.BlockSize > 0)
|
||||
{
|
||||
{
|
||||
if (this._padding == null)
|
||||
{
|
||||
throw new ArgumentException("data");
|
||||
}
|
||||
else
|
||||
{
|
||||
data = this._padding.Pad(this.BlockSize, data);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
var output = new byte[data.Length];
|
||||
|
||||
var writtenBytes = 0;
|
||||
for (int i = 0; i < data.Length / this.BlockSize; i++)
|
||||
{
|
||||
if (this._mode == null)
|
||||
{
|
||||
writtenBytes += this.DecryptBlock(data, i * this.BlockSize, this.BlockSize, output, i * this.BlockSize);
|
||||
}
|
||||
else
|
||||
{
|
||||
writtenBytes += this._mode.DecryptBlock(data, i * this.BlockSize, this.BlockSize, output, i * this.BlockSize);
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
if (writtenBytes < data.Length)
|
||||
{
|
||||
throw new InvalidOperationException("Encryption error.");
|
||||
}
|
||||
|
||||
return output;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,239 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
|
||||
namespace Renci.SshNet.Security.Cryptography
|
||||
{
|
||||
/// <summary>
|
||||
/// Base class for cipher implementation.
|
||||
/// </summary>
|
||||
public abstract class Cipher
|
||||
{
|
||||
/// <summary>
|
||||
/// Encrypts the specified input.
|
||||
/// </summary>
|
||||
/// <param name="input">The input.</param>
|
||||
/// <returns></returns>
|
||||
public abstract byte[] Encrypt(byte[] input);
|
||||
|
||||
/// <summary>
|
||||
/// Decrypts the specified input.
|
||||
/// </summary>
|
||||
/// <param name="input">The input.</param>
|
||||
/// <returns></returns>
|
||||
public abstract byte[] Decrypt(byte[] input);
|
||||
|
||||
#region Packing functions
|
||||
|
||||
/// <summary>
|
||||
/// Populates buffer with big endian number representation.
|
||||
/// </summary>
|
||||
/// <param name="number">The number to convert.</param>
|
||||
/// <param name="buffer">The buffer.</param>
|
||||
protected static void UInt32ToBigEndian(uint number, byte[] buffer)
|
||||
{
|
||||
buffer[0] = (byte)(number >> 24);
|
||||
buffer[1] = (byte)(number >> 16);
|
||||
buffer[2] = (byte)(number >> 8);
|
||||
buffer[3] = (byte)(number);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Populates buffer with big endian number representation.
|
||||
/// </summary>
|
||||
/// <param name="number">The number to convert.</param>
|
||||
/// <param name="buffer">The buffer.</param>
|
||||
/// <param name="offset">The buffer offset.</param>
|
||||
protected static void UInt32ToBigEndian(uint number, byte[] buffer, int offset)
|
||||
{
|
||||
buffer[offset] = (byte)(number >> 24);
|
||||
buffer[++offset] = (byte)(number >> 16);
|
||||
buffer[++offset] = (byte)(number >> 8);
|
||||
buffer[++offset] = (byte)(number);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Converts big endian bytes into number.
|
||||
/// </summary>
|
||||
/// <param name="buffer">The buffer.</param>
|
||||
/// <returns></returns>
|
||||
protected static uint BigEndianToUInt32(byte[] buffer)
|
||||
{
|
||||
uint n = (uint)buffer[0] << 24;
|
||||
n |= (uint)buffer[1] << 16;
|
||||
n |= (uint)buffer[2] << 8;
|
||||
n |= (uint)buffer[3];
|
||||
return n;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Converts big endian bytes into number.
|
||||
/// </summary>
|
||||
/// <param name="buffer">The buffer.</param>
|
||||
/// <param name="offset">The buffer offset.</param>
|
||||
/// <returns></returns>
|
||||
protected static uint BigEndianToUInt32(byte[] buffer, int offset)
|
||||
{
|
||||
uint n = (uint)buffer[offset] << 24;
|
||||
n |= (uint)buffer[++offset] << 16;
|
||||
n |= (uint)buffer[++offset] << 8;
|
||||
n |= (uint)buffer[++offset];
|
||||
return n;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Converts big endian bytes into number.
|
||||
/// </summary>
|
||||
/// <param name="buffer">The buffer.</param>
|
||||
/// <returns></returns>
|
||||
protected static ulong BigEndianToUInt64(byte[] buffer)
|
||||
{
|
||||
uint hi = BigEndianToUInt32(buffer);
|
||||
uint lo = BigEndianToUInt32(buffer, 4);
|
||||
return ((ulong)hi << 32) | (ulong)lo;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Converts big endian bytes into number.
|
||||
/// </summary>
|
||||
/// <param name="buffer">The buffer.</param>
|
||||
/// <param name="offset">The buffer offset.</param>
|
||||
/// <returns></returns>
|
||||
protected static ulong BigEndianToUInt64(byte[] buffer, int offset)
|
||||
{
|
||||
uint hi = BigEndianToUInt32(buffer, offset);
|
||||
uint lo = BigEndianToUInt32(buffer, offset + 4);
|
||||
return ((ulong)hi << 32) | (ulong)lo;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Populates buffer with big endian number representation.
|
||||
/// </summary>
|
||||
/// <param name="number">The number to convert.</param>
|
||||
/// <param name="buffer">The buffer.</param>
|
||||
protected static void UInt64ToBigEndian(ulong number, byte[] buffer)
|
||||
{
|
||||
UInt32ToBigEndian((uint)(number >> 32), buffer);
|
||||
UInt32ToBigEndian((uint)(number), buffer, 4);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Populates buffer with big endian number representation.
|
||||
/// </summary>
|
||||
/// <param name="number">The number to convert.</param>
|
||||
/// <param name="buffer">The buffer.</param>
|
||||
/// <param name="offset">The buffer offset.</param>
|
||||
protected static void UInt64ToBigEndian(ulong number, byte[] buffer, int offset)
|
||||
{
|
||||
UInt32ToBigEndian((uint)(number >> 32), buffer, offset);
|
||||
UInt32ToBigEndian((uint)(number), buffer, offset + 4);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Populates buffer with little endian number representation.
|
||||
/// </summary>
|
||||
/// <param name="number">The number to convert.</param>
|
||||
/// <param name="buffer">The buffer.</param>
|
||||
protected static void UInt32ToLittleEndian(uint number, byte[] buffer)
|
||||
{
|
||||
buffer[0] = (byte)(number);
|
||||
buffer[1] = (byte)(number >> 8);
|
||||
buffer[2] = (byte)(number >> 16);
|
||||
buffer[3] = (byte)(number >> 24);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Populates buffer with little endian number representation.
|
||||
/// </summary>
|
||||
/// <param name="number">The number to convert.</param>
|
||||
/// <param name="buffer">The buffer.</param>
|
||||
/// <param name="offset">The buffer offset.</param>
|
||||
protected static void UInt32ToLittleEndian(uint number, byte[] buffer, int offset)
|
||||
{
|
||||
buffer[offset] = (byte)(number);
|
||||
buffer[++offset] = (byte)(number >> 8);
|
||||
buffer[++offset] = (byte)(number >> 16);
|
||||
buffer[++offset] = (byte)(number >> 24);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Converts little endian bytes into number.
|
||||
/// </summary>
|
||||
/// <param name="buffer">The buffer.</param>
|
||||
/// <returns></returns>
|
||||
protected static uint LittleEndianToUInt32(byte[] buffer)
|
||||
{
|
||||
uint n = (uint)buffer[0];
|
||||
n |= (uint)buffer[1] << 8;
|
||||
n |= (uint)buffer[2] << 16;
|
||||
n |= (uint)buffer[3] << 24;
|
||||
return n;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Converts little endian bytes into number.
|
||||
/// </summary>
|
||||
/// <param name="buffer">The buffer.</param>
|
||||
/// <param name="offset">The buffer offset.</param>
|
||||
/// <returns></returns>
|
||||
protected static uint LittleEndianToUInt32(byte[] buffer, int offset)
|
||||
{
|
||||
uint n = (uint)buffer[offset];
|
||||
n |= (uint)buffer[++offset] << 8;
|
||||
n |= (uint)buffer[++offset] << 16;
|
||||
n |= (uint)buffer[++offset] << 24;
|
||||
return n;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Converts little endian bytes into number.
|
||||
/// </summary>
|
||||
/// <param name="buffer">The buffer.</param>
|
||||
/// <returns></returns>
|
||||
protected static ulong LittleEndianToUInt64(byte[] buffer)
|
||||
{
|
||||
uint lo = LittleEndianToUInt32(buffer);
|
||||
uint hi = LittleEndianToUInt32(buffer, 4);
|
||||
return ((ulong)hi << 32) | (ulong)lo;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Converts little endian bytes into number.
|
||||
/// </summary>
|
||||
/// <param name="buffer">The buffer.</param>
|
||||
/// <param name="offset">The buffer offset.</param>
|
||||
/// <returns></returns>
|
||||
protected static ulong LittleEndianToUInt64(byte[] buffer, int offset)
|
||||
{
|
||||
uint lo = LittleEndianToUInt32(buffer, offset);
|
||||
uint hi = LittleEndianToUInt32(buffer, offset + 4);
|
||||
return ((ulong)hi << 32) | (ulong)lo;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Populates buffer with little endian number representation.
|
||||
/// </summary>
|
||||
/// <param name="number">The number to convert.</param>
|
||||
/// <param name="buffer">The buffer.</param>
|
||||
protected static void UInt64ToLittleEndian(ulong number, byte[] buffer)
|
||||
{
|
||||
UInt32ToLittleEndian((uint)(number), buffer);
|
||||
UInt32ToLittleEndian((uint)(number >> 32), buffer, 4);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Populates buffer with little endian number representation.
|
||||
/// </summary>
|
||||
/// <param name="number">The number to convert.</param>
|
||||
/// <param name="buffer">The buffer.</param>
|
||||
/// <param name="offset">The buffer offset.</param>
|
||||
protected static void UInt64ToLittleEndian(ulong number, byte[] buffer, int offset)
|
||||
{
|
||||
UInt32ToLittleEndian((uint)(number), buffer, offset);
|
||||
UInt32ToLittleEndian((uint)(number >> 32), buffer, offset + 4);
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,124 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Security.Cryptography;
|
||||
|
||||
namespace Renci.SshNet.Security.Cryptography
|
||||
{
|
||||
/// <summary>
|
||||
/// Implements digital signature where where asymmetric cipher is used,
|
||||
/// </summary>
|
||||
public class CipherDigitalSignature : DigitalSignature
|
||||
{
|
||||
private HashAlgorithm _hash;
|
||||
|
||||
private AsymmetricCipher _cipher;
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="CipherDigitalSignature"/> class.
|
||||
/// </summary>
|
||||
/// <param name="hash">The hash.</param>
|
||||
/// <param name="cipher">The cipher.</param>
|
||||
public CipherDigitalSignature(HashAlgorithm hash, AsymmetricCipher cipher)
|
||||
{
|
||||
this._hash = hash;
|
||||
this._cipher = cipher;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Verifies the signature.
|
||||
/// </summary>
|
||||
/// <param name="input">The input.</param>
|
||||
/// <param name="signature">The signature.</param>
|
||||
/// <returns></returns>
|
||||
public override bool VerifySignature(byte[] input, byte[] signature)
|
||||
{
|
||||
var sig = this._cipher.Decrypt(signature);
|
||||
|
||||
// TODO: Ensure that only 1 or 2 types are supported
|
||||
var position = 1;
|
||||
while (position < sig.Length && sig[position] != 0)
|
||||
position++;
|
||||
position++;
|
||||
|
||||
|
||||
var sig1 = new byte[sig.Length - position];
|
||||
|
||||
Array.Copy(sig, position, sig1, 0, sig1.Length);
|
||||
|
||||
var hashData = this.Hash(input);
|
||||
|
||||
var expected = DerEncode(hashData);
|
||||
|
||||
if (expected.Count != sig1.Length)
|
||||
return false;
|
||||
|
||||
for (int i = 0; i < expected.Count; i++)
|
||||
{
|
||||
if (expected[i] != sig1[i])
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Creates the signature.
|
||||
/// </summary>
|
||||
/// <param name="input">The input.</param>
|
||||
/// <returns></returns>
|
||||
public override byte[] CreateSignature(byte[] input)
|
||||
{
|
||||
// Calculate hash value
|
||||
var hashData = this.Hash(input);
|
||||
|
||||
// Calculate DER string
|
||||
|
||||
// Resolve algorithm identifier
|
||||
var dd = DerEncode(hashData);
|
||||
|
||||
// Calculate signature
|
||||
var rsaInputBlockSize = new byte[255];
|
||||
rsaInputBlockSize[0] = 0x01;
|
||||
for (int i = 1; i < rsaInputBlockSize.Length - dd.Count - 1; i++)
|
||||
{
|
||||
rsaInputBlockSize[i] = 0xFF;
|
||||
}
|
||||
|
||||
Array.Copy(dd.ToArray(), 0, rsaInputBlockSize, rsaInputBlockSize.Length - dd.Count, dd.Count);
|
||||
|
||||
return this._cipher.Encrypt(rsaInputBlockSize).TrimLeadingZero().ToArray();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Hashes the specified input.
|
||||
/// </summary>
|
||||
/// <param name="input">The input.</param>
|
||||
/// <returns></returns>
|
||||
protected byte[] Hash(byte[] input)
|
||||
{
|
||||
return this._hash.ComputeHash(input);
|
||||
}
|
||||
|
||||
protected static List<byte> DerEncode(byte[] hashData)
|
||||
{
|
||||
// TODO: Replace with algorithm code
|
||||
var algorithm = new byte[] { 6, 5, 43, 14, 3, 2, 26 };
|
||||
var algorithmParams = new byte[] { 5, 0 };
|
||||
|
||||
var dd = new List<byte>(algorithm);
|
||||
dd.AddRange(algorithmParams);
|
||||
dd.Insert(0, (byte)dd.Count);
|
||||
dd.Insert(0, 48);
|
||||
|
||||
dd.Add(4);
|
||||
dd.Add((byte)hashData.Length);
|
||||
dd.AddRange(hashData);
|
||||
|
||||
dd.Insert(0, (byte)dd.Count);
|
||||
dd.Insert(0, 48);
|
||||
return dd;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -3,115 +3,26 @@ using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
|
||||
namespace Renci.SshNet.Security.Cryptography
|
||||
namespace Renci.SshNet.Security.Cryptography.Ciphers
|
||||
{
|
||||
internal class AesCipher : CipherBase
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
public class AesCipher : BlockCipher
|
||||
{
|
||||
private int ROUNDS;
|
||||
|
||||
private byte[] _key;
|
||||
|
||||
private uint[,] _encryptionKey;
|
||||
private uint[,] EncryptionKey
|
||||
{
|
||||
get
|
||||
{
|
||||
if (this._encryptionKey == null)
|
||||
{
|
||||
this._encryptionKey = this.GenerateWorkingKey(true, this._key);
|
||||
}
|
||||
return this._encryptionKey;
|
||||
}
|
||||
}
|
||||
|
||||
private uint[,] _decryptionKey;
|
||||
private uint[,] DecryptionKey
|
||||
{
|
||||
get
|
||||
{
|
||||
if (this._decryptionKey == null)
|
||||
{
|
||||
this._decryptionKey = this.GenerateWorkingKey(false, this._key);
|
||||
}
|
||||
return this._decryptionKey;
|
||||
}
|
||||
}
|
||||
|
||||
private uint C0, C1, C2, C3;
|
||||
|
||||
/// <summary>
|
||||
/// Gets the size of the block.
|
||||
/// </summary>
|
||||
/// <value>
|
||||
/// The size of the block.
|
||||
/// </value>
|
||||
public override int BlockSize { get { return 16; } } // 128 bit block size
|
||||
|
||||
/* multiply four bytes in GF(2^8) by 'x' {02} in parallel */
|
||||
|
||||
private const uint m1 = 0x80808080;
|
||||
|
||||
private const uint m2 = 0x7f7f7f7f;
|
||||
|
||||
private const uint m3 = 0x0000001b;
|
||||
|
||||
private int _rounds;
|
||||
|
||||
public AesCipher(byte[] key, byte[] iv)
|
||||
: base(key, iv)
|
||||
{
|
||||
this._key = key;
|
||||
}
|
||||
private uint[,] _encryptionKey;
|
||||
|
||||
public override int EncryptBlock(byte[] inputBuffer, int inputOffset, int inputCount, byte[] outputBuffer, int outputOffset)
|
||||
{
|
||||
if (this.EncryptionKey == null)
|
||||
{
|
||||
throw new InvalidOperationException("AES engine not initialized");
|
||||
}
|
||||
private uint[,] _decryptionKey;
|
||||
|
||||
if ((inputOffset + (32 / 2)) > inputBuffer.Length)
|
||||
{
|
||||
throw new IndexOutOfRangeException("input buffer too short");
|
||||
}
|
||||
|
||||
if ((outputOffset + (32 / 2)) > outputBuffer.Length)
|
||||
{
|
||||
throw new IndexOutOfRangeException("output buffer too short");
|
||||
}
|
||||
|
||||
this.UnPackBlock(inputBuffer, inputOffset);
|
||||
|
||||
this.EncryptBlock(this.EncryptionKey);
|
||||
|
||||
this.PackBlock(outputBuffer, outputOffset);
|
||||
|
||||
return this.BlockSize;
|
||||
}
|
||||
|
||||
public override int DecryptBlock(byte[] inputBuffer, int inputOffset, int inputCount, byte[] outputBuffer, int outputOffset)
|
||||
{
|
||||
if (this.DecryptionKey == null)
|
||||
{
|
||||
throw new InvalidOperationException("AES engine not initialized");
|
||||
}
|
||||
|
||||
if ((inputOffset + (32 / 2)) > inputBuffer.Length)
|
||||
{
|
||||
throw new IndexOutOfRangeException("input buffer too short");
|
||||
}
|
||||
|
||||
if ((outputOffset + (32 / 2)) > outputBuffer.Length)
|
||||
{
|
||||
throw new IndexOutOfRangeException("output buffer too short");
|
||||
}
|
||||
|
||||
this.UnPackBlock(inputBuffer, inputOffset);
|
||||
|
||||
this.DecryptBlock(this.DecryptionKey);
|
||||
|
||||
this.PackBlock(outputBuffer, outputOffset);
|
||||
|
||||
return this.BlockSize;
|
||||
}
|
||||
private uint C0, C1, C2, C3;
|
||||
|
||||
#region Static Definition Tables
|
||||
|
||||
@@ -646,6 +557,167 @@ namespace Renci.SshNet.Security.Cryptography
|
||||
|
||||
#endregion
|
||||
|
||||
/// <summary>
|
||||
/// Gets the size of the block in bytes.
|
||||
/// </summary>
|
||||
/// <value>
|
||||
/// The size of the block in bytes.
|
||||
/// </value>
|
||||
public override int BlockSize
|
||||
{
|
||||
get { return 16; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="AesCipher"/> class.
|
||||
/// </summary>
|
||||
/// <param name="key">The key.</param>
|
||||
/// <param name="mode">The mode.</param>
|
||||
/// <param name="padding">The padding.</param>
|
||||
public AesCipher(byte[] key, CipherMode mode, CipherPadding padding)
|
||||
: base(key, mode, padding)
|
||||
{
|
||||
this._encryptionKey = this.GenerateWorkingKey(true, key);
|
||||
this._decryptionKey = this.GenerateWorkingKey(false, key);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Encrypts the specified region of the input byte array and copies the encrypted data to the specified region of the output byte array.
|
||||
/// </summary>
|
||||
/// <param name="inputBuffer">The input data to encrypt.</param>
|
||||
/// <param name="inputOffset">The offset into the input byte array from which to begin using data.</param>
|
||||
/// <param name="inputCount">The number of bytes in the input byte array to use as data.</param>
|
||||
/// <param name="outputBuffer">The output to which to write encrypted data.</param>
|
||||
/// <param name="outputOffset">The offset into the output byte array from which to begin writing data.</param>
|
||||
/// <returns>
|
||||
/// The number of bytes encrypted.
|
||||
/// </returns>
|
||||
public override int EncryptBlock(byte[] inputBuffer, int inputOffset, int inputCount, byte[] outputBuffer, int outputOffset)
|
||||
{
|
||||
if ((inputOffset + (32 / 2)) > inputBuffer.Length)
|
||||
{
|
||||
throw new IndexOutOfRangeException("input buffer too short");
|
||||
}
|
||||
|
||||
if ((outputOffset + (32 / 2)) > outputBuffer.Length)
|
||||
{
|
||||
throw new IndexOutOfRangeException("output buffer too short");
|
||||
}
|
||||
|
||||
this.UnPackBlock(inputBuffer, inputOffset);
|
||||
|
||||
this.EncryptBlock(this._encryptionKey);
|
||||
|
||||
this.PackBlock(outputBuffer, outputOffset);
|
||||
|
||||
return this.BlockSize;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Decrypts the specified region of the input byte array and copies the decrypted data to the specified region of the output byte array.
|
||||
/// </summary>
|
||||
/// <param name="inputBuffer">The input data to decrypt.</param>
|
||||
/// <param name="inputOffset">The offset into the input byte array from which to begin using data.</param>
|
||||
/// <param name="inputCount">The number of bytes in the input byte array to use as data.</param>
|
||||
/// <param name="outputBuffer">The output to which to write decrypted data.</param>
|
||||
/// <param name="outputOffset">The offset into the output byte array from which to begin writing data.</param>
|
||||
/// <returns>
|
||||
/// The number of bytes decrypted.
|
||||
/// </returns>
|
||||
public override int DecryptBlock(byte[] inputBuffer, int inputOffset, int inputCount, byte[] outputBuffer, int outputOffset)
|
||||
{
|
||||
if ((inputOffset + (32 / 2)) > inputBuffer.Length)
|
||||
{
|
||||
throw new IndexOutOfRangeException("input buffer too short");
|
||||
}
|
||||
|
||||
if ((outputOffset + (32 / 2)) > outputBuffer.Length)
|
||||
{
|
||||
throw new IndexOutOfRangeException("output buffer too short");
|
||||
}
|
||||
|
||||
this.UnPackBlock(inputBuffer, inputOffset);
|
||||
|
||||
this.DecryptBlock(this._decryptionKey);
|
||||
|
||||
this.PackBlock(outputBuffer, outputOffset);
|
||||
|
||||
return this.BlockSize;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Validates the size of the key.
|
||||
/// </summary>
|
||||
/// <param name="keySize">Size of the key.</param>
|
||||
/// <returns>
|
||||
/// true if keySize is valid; otherwise false
|
||||
/// </returns>
|
||||
protected override bool ValidateKeySize(int keySize)
|
||||
{
|
||||
if (keySize == 256 ||
|
||||
keySize == 192 ||
|
||||
keySize == 128)
|
||||
return true;
|
||||
else
|
||||
return false;
|
||||
}
|
||||
|
||||
private uint[,] GenerateWorkingKey(bool isEncryption, byte[] key)
|
||||
{
|
||||
int KC = key.Length / 4; // key length in words
|
||||
|
||||
if (((KC != 4) && (KC != 6) && (KC != 8)) || ((KC * 4) != key.Length))
|
||||
throw new ArgumentException("Key length not 128/192/256 bits.");
|
||||
|
||||
_rounds = KC + 6; // This is not always true for the generalized Rijndael that allows larger block sizes
|
||||
uint[,] W = new uint[_rounds + 1, 4]; // 4 words in a block
|
||||
|
||||
//
|
||||
// copy the key into the round key array
|
||||
//
|
||||
|
||||
int t = 0;
|
||||
|
||||
for (int i = 0; i < key.Length; t++)
|
||||
{
|
||||
W[t >> 2, t & 3] = LittleEndianToUInt32(key, i);
|
||||
i += 4;
|
||||
}
|
||||
|
||||
//
|
||||
// while not enough round key material calculated
|
||||
// calculate new values
|
||||
//
|
||||
int k = (_rounds + 1) << 2;
|
||||
for (int i = KC; (i < k); i++)
|
||||
{
|
||||
uint temp = W[(i - 1) >> 2, (i - 1) & 3];
|
||||
if ((i % KC) == 0)
|
||||
{
|
||||
temp = SubWord(Shift(temp, 8)) ^ rcon[(i / KC) - 1];
|
||||
}
|
||||
else if ((KC > 6) && ((i % KC) == 4))
|
||||
{
|
||||
temp = SubWord(temp);
|
||||
}
|
||||
|
||||
W[i >> 2, i & 3] = W[(i - KC) >> 2, (i - KC) & 3] ^ temp;
|
||||
}
|
||||
|
||||
if (!isEncryption)
|
||||
{
|
||||
for (int j = 1; j < _rounds; j++)
|
||||
{
|
||||
for (int i = 0; i < 4; i++)
|
||||
{
|
||||
W[j, i] = InvMcol(W[j, i]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return W;
|
||||
}
|
||||
|
||||
private uint Shift(uint r, int shift)
|
||||
{
|
||||
return (r >> shift) | (r << (32 - shift));
|
||||
@@ -684,87 +756,20 @@ namespace Renci.SshNet.Security.Cryptography
|
||||
| (((uint)S[(x >> 24) & 255]) << 24);
|
||||
}
|
||||
|
||||
/**
|
||||
* Calculate the necessary round keys
|
||||
* The number of calculations depends on key size and block size
|
||||
* AES specified a fixed block size of 128 bits and key sizes 128/192/256 bits
|
||||
* This code is written assuming those are the only possible values
|
||||
*/
|
||||
private uint[,] GenerateWorkingKey(bool isEncryption, byte[] key)
|
||||
{
|
||||
int KC = key.Length / 4; // key length in words
|
||||
|
||||
if (((KC != 4) && (KC != 6) && (KC != 8)) || ((KC * 4) != key.Length))
|
||||
throw new ArgumentException("Key length not 128/192/256 bits.");
|
||||
|
||||
ROUNDS = KC + 6; // This is not always true for the generalized Rijndael that allows larger block sizes
|
||||
uint[,] W = new uint[ROUNDS + 1, 4]; // 4 words in a block
|
||||
|
||||
//
|
||||
// copy the key into the round key array
|
||||
//
|
||||
|
||||
int t = 0;
|
||||
|
||||
for (int i = 0; i < key.Length; t++)
|
||||
{
|
||||
W[t >> 2, t & 3] = CipherBase.LittleEndianToUInt32(key, i);
|
||||
i += 4;
|
||||
}
|
||||
|
||||
//
|
||||
// while not enough round key material calculated
|
||||
// calculate new values
|
||||
//
|
||||
int k = (ROUNDS + 1) << 2;
|
||||
for (int i = KC; (i < k); i++)
|
||||
{
|
||||
uint temp = W[(i - 1) >> 2, (i - 1) & 3];
|
||||
if ((i % KC) == 0)
|
||||
{
|
||||
temp = SubWord(Shift(temp, 8)) ^ rcon[(i / KC) - 1];
|
||||
}
|
||||
else if ((KC > 6) && ((i % KC) == 4))
|
||||
{
|
||||
temp = SubWord(temp);
|
||||
}
|
||||
|
||||
W[i >> 2, i & 3] = W[(i - KC) >> 2, (i - KC) & 3] ^ temp;
|
||||
}
|
||||
|
||||
if (!isEncryption)
|
||||
{
|
||||
for (int j = 1; j < ROUNDS; j++)
|
||||
{
|
||||
for (int i = 0; i < 4; i++)
|
||||
{
|
||||
W[j, i] = InvMcol(W[j, i]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return W;
|
||||
}
|
||||
|
||||
private bool IsPartialBlockOkay
|
||||
{
|
||||
get { return false; }
|
||||
}
|
||||
|
||||
private void UnPackBlock(byte[] bytes, int off)
|
||||
{
|
||||
C0 = CipherBase.LittleEndianToUInt32(bytes, off);
|
||||
C1 = CipherBase.LittleEndianToUInt32(bytes, off + 4);
|
||||
C2 = CipherBase.LittleEndianToUInt32(bytes, off + 8);
|
||||
C3 = CipherBase.LittleEndianToUInt32(bytes, off + 12);
|
||||
C0 = LittleEndianToUInt32(bytes, off);
|
||||
C1 = LittleEndianToUInt32(bytes, off + 4);
|
||||
C2 = LittleEndianToUInt32(bytes, off + 8);
|
||||
C3 = LittleEndianToUInt32(bytes, off + 12);
|
||||
}
|
||||
|
||||
private void PackBlock(byte[] bytes, int off)
|
||||
{
|
||||
CipherBase.UInt32ToLittleEndian(C0, bytes, off);
|
||||
CipherBase.UInt32ToLittleEndian(C1, bytes, off + 4);
|
||||
CipherBase.UInt32ToLittleEndian(C2, bytes, off + 8);
|
||||
CipherBase.UInt32ToLittleEndian(C3, bytes, off + 12);
|
||||
UInt32ToLittleEndian(C0, bytes, off);
|
||||
UInt32ToLittleEndian(C1, bytes, off + 4);
|
||||
UInt32ToLittleEndian(C2, bytes, off + 8);
|
||||
UInt32ToLittleEndian(C3, bytes, off + 12);
|
||||
}
|
||||
|
||||
private void EncryptBlock(uint[,] KW)
|
||||
@@ -777,7 +782,7 @@ namespace Renci.SshNet.Security.Cryptography
|
||||
C2 ^= KW[0, 2];
|
||||
C3 ^= KW[0, 3];
|
||||
|
||||
for (r = 1; r < ROUNDS - 1; )
|
||||
for (r = 1; r < _rounds - 1; )
|
||||
{
|
||||
r0 = T0[C0 & 255] ^ T1[(C1 >> 8) & 255] ^ T2[(C2 >> 16) & 255] ^ T3[C3 >> 24] ^ KW[r, 0];
|
||||
r1 = T0[C1 & 255] ^ T1[(C2 >> 8) & 255] ^ T2[(C3 >> 16) & 255] ^ T3[C0 >> 24] ^ KW[r, 1];
|
||||
@@ -807,12 +812,12 @@ namespace Renci.SshNet.Security.Cryptography
|
||||
int r;
|
||||
uint r0, r1, r2, r3;
|
||||
|
||||
C0 ^= KW[ROUNDS, 0];
|
||||
C1 ^= KW[ROUNDS, 1];
|
||||
C2 ^= KW[ROUNDS, 2];
|
||||
C3 ^= KW[ROUNDS, 3];
|
||||
C0 ^= KW[_rounds, 0];
|
||||
C1 ^= KW[_rounds, 1];
|
||||
C2 ^= KW[_rounds, 2];
|
||||
C3 ^= KW[_rounds, 3];
|
||||
|
||||
for (r = ROUNDS - 1; r > 1; )
|
||||
for (r = _rounds - 1; r > 1; )
|
||||
{
|
||||
r0 = Tinv0[C0 & 255] ^ Tinv1[(C3 >> 8) & 255] ^ Tinv2[(C2 >> 16) & 255] ^ Tinv3[C1 >> 24] ^ KW[r, 0];
|
||||
r1 = Tinv0[C1 & 255] ^ Tinv1[(C0 >> 8) & 255] ^ Tinv2[(C3 >> 16) & 255] ^ Tinv3[C2 >> 24] ^ KW[r, 1];
|
||||
@@ -836,5 +841,6 @@ namespace Renci.SshNet.Security.Cryptography
|
||||
C2 = (uint)Si[r2 & 255] ^ (((uint)Si[(r1 >> 8) & 255]) << 8) ^ (((uint)Si[(r0 >> 16) & 255]) << 16) ^ (((uint)Si[r3 >> 24]) << 24) ^ KW[0, 2];
|
||||
C3 = (uint)Si[r3 & 255] ^ (((uint)Si[(r2 >> 8) & 255]) << 8) ^ (((uint)Si[(r1 >> 16) & 255]) << 16) ^ (((uint)Si[r0 >> 24]) << 24) ^ KW[0, 3];
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,87 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
|
||||
namespace Renci.SshNet.Security.Cryptography.Ciphers
|
||||
{
|
||||
/// <summary>
|
||||
/// Implements ARCH4 cipher algorithm
|
||||
/// </summary>
|
||||
public class Arc4Cipher : StreamCipher
|
||||
{
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="Arc4Cipher"/> class.
|
||||
/// </summary>
|
||||
/// <param name="key">The key.</param>
|
||||
public Arc4Cipher(byte[] key)
|
||||
: base(key)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Encrypts the specified region of the input byte array and copies the encrypted data to the specified region of the output byte array.
|
||||
/// </summary>
|
||||
/// <param name="inputBuffer">The input data to encrypt.</param>
|
||||
/// <param name="inputOffset">The offset into the input byte array from which to begin using data.</param>
|
||||
/// <param name="inputCount">The number of bytes in the input byte array to use as data.</param>
|
||||
/// <param name="outputBuffer">The output to which to write encrypted data.</param>
|
||||
/// <param name="outputOffset">The offset into the output byte array from which to begin writing data.</param>
|
||||
/// <returns>
|
||||
/// The number of bytes encrypted.
|
||||
/// </returns>
|
||||
public override int EncryptBlock(byte[] inputBuffer, int inputOffset, int inputCount, byte[] outputBuffer, int outputOffset)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Decrypts the specified region of the input byte array and copies the decrypted data to the specified region of the output byte array.
|
||||
/// </summary>
|
||||
/// <param name="inputBuffer">The input data to decrypt.</param>
|
||||
/// <param name="inputOffset">The offset into the input byte array from which to begin using data.</param>
|
||||
/// <param name="inputCount">The number of bytes in the input byte array to use as data.</param>
|
||||
/// <param name="outputBuffer">The output to which to write decrypted data.</param>
|
||||
/// <param name="outputOffset">The offset into the output byte array from which to begin writing data.</param>
|
||||
/// <returns>
|
||||
/// The number of bytes decrypted.
|
||||
/// </returns>
|
||||
public override int DecryptBlock(byte[] inputBuffer, int inputOffset, int inputCount, byte[] outputBuffer, int outputOffset)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Encrypts the specified input.
|
||||
/// </summary>
|
||||
/// <param name="input">The input.</param>
|
||||
/// <returns></returns>
|
||||
public override byte[] Encrypt(byte[] input)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Decrypts the specified input.
|
||||
/// </summary>
|
||||
/// <param name="input">The input.</param>
|
||||
/// <returns></returns>
|
||||
public override byte[] Decrypt(byte[] input)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Validates the size of the key.
|
||||
/// </summary>
|
||||
/// <param name="keySize">Size of the key.</param>
|
||||
/// <returns>
|
||||
/// true if keySize is valid; otherwise false
|
||||
/// </returns>
|
||||
protected override bool ValidateKeySize(int keySize)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -3,13 +3,16 @@ using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
|
||||
namespace Renci.SshNet.Security.Cryptography
|
||||
namespace Renci.SshNet.Security.Cryptography.Ciphers
|
||||
{
|
||||
internal class BlowfishCipher : CipherBase
|
||||
{
|
||||
#region Static reference tables
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
public class BlowfishCipher : BlockCipher
|
||||
{
|
||||
#region Static reference tables
|
||||
|
||||
private readonly static uint[] KP =
|
||||
private readonly static uint[] KP =
|
||||
{
|
||||
0x243F6A88, 0x85A308D3, 0x13198A2E, 0x03707344,
|
||||
0xA4093822, 0x299F31D0, 0x082EFA98, 0xEC4E6C89,
|
||||
@@ -17,7 +20,7 @@ namespace Renci.SshNet.Security.Cryptography
|
||||
0xC0AC29B7, 0xC97C50DD, 0x3F84D5B5, 0xB5470917,
|
||||
0x9216D5D9, 0x8979FB1B
|
||||
},
|
||||
KS0 =
|
||||
KS0 =
|
||||
{
|
||||
0xD1310BA6, 0x98DFB5AC, 0x2FFD72DB, 0xD01ADFB7,
|
||||
0xB8E1AFED, 0x6A267E96, 0xBA7C9045, 0xF12C7F99,
|
||||
@@ -84,7 +87,7 @@ namespace Renci.SshNet.Security.Cryptography
|
||||
0xB6636521, 0xE7B9F9B6, 0xFF34052E, 0xC5855664,
|
||||
0x53B02D5D, 0xA99F8FA1, 0x08BA4799, 0x6E85076A
|
||||
},
|
||||
KS1 =
|
||||
KS1 =
|
||||
{
|
||||
0x4B7A70E9, 0xB5B32944, 0xDB75092E, 0xC4192623,
|
||||
0xAD6EA6B0, 0x49A7DF7D, 0x9CEE60B8, 0x8FEDB266,
|
||||
@@ -151,7 +154,7 @@ namespace Renci.SshNet.Security.Cryptography
|
||||
0xC5C43465, 0x713E38D8, 0x3D28F89E, 0xF16DFF20,
|
||||
0x153E21E7, 0x8FB03D4A, 0xE6E39F2B, 0xDB83ADF7
|
||||
},
|
||||
KS2 =
|
||||
KS2 =
|
||||
{
|
||||
0xE93D5A68, 0x948140F7, 0xF64C261C, 0x94692934,
|
||||
0x411520F7, 0x7602D4F7, 0xBCF46B2E, 0xD4A20068,
|
||||
@@ -218,7 +221,7 @@ namespace Renci.SshNet.Security.Cryptography
|
||||
0x6FD5C7E7, 0x56E14EC4, 0x362ABFCE, 0xDDC6C837,
|
||||
0xD79A3234, 0x92638212, 0x670EFA8E, 0x406000E0
|
||||
},
|
||||
KS3 =
|
||||
KS3 =
|
||||
{
|
||||
0x3A39CE37, 0xD3FAF5CF, 0xABC27737, 0x5AC52D1B,
|
||||
0x5CB0679E, 0x4FA33742, 0xD3822740, 0x99BC9BBE,
|
||||
@@ -286,188 +289,239 @@ namespace Renci.SshNet.Security.Cryptography
|
||||
0xB74E6132, 0xCE77E25B, 0x578FDFE3, 0x3AC372E6
|
||||
};
|
||||
|
||||
#endregion
|
||||
#endregion
|
||||
|
||||
private static readonly int ROUNDS = 16;
|
||||
private static readonly int SBOX_SK = 256;
|
||||
private static readonly int P_SZ = ROUNDS + 2;
|
||||
private static readonly int ROUNDS = 16;
|
||||
private static readonly int SBOX_SK = 256;
|
||||
private static readonly int P_SZ = ROUNDS + 2;
|
||||
|
||||
private readonly uint[] S0, S1, S2, S3; // the s-boxes
|
||||
private readonly uint[] P; // the p-array
|
||||
private readonly uint[] S0, S1, S2, S3; // the s-boxes
|
||||
private readonly uint[] P; // the p-array
|
||||
|
||||
public BlowfishCipher(byte[] key, byte[] iv)
|
||||
: base(key, iv)
|
||||
{
|
||||
S0 = new uint[SBOX_SK];
|
||||
S1 = new uint[SBOX_SK];
|
||||
S2 = new uint[SBOX_SK];
|
||||
S3 = new uint[SBOX_SK];
|
||||
P = new uint[P_SZ];
|
||||
/// <summary>
|
||||
/// Gets the size of the block in bytes.
|
||||
/// </summary>
|
||||
/// <value>
|
||||
/// The size of the block in bytes.
|
||||
/// </value>
|
||||
public override int BlockSize
|
||||
{
|
||||
get { return 8; }
|
||||
}
|
||||
|
||||
this.SetKey(key);
|
||||
}
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="BlowfishCipher"/> class.
|
||||
/// </summary>
|
||||
/// <param name="key">The key.</param>
|
||||
/// <param name="mode">The mode.</param>
|
||||
/// <param name="padding">The padding.</param>
|
||||
public BlowfishCipher(byte[] key, CipherMode mode, CipherPadding padding)
|
||||
: base(key, mode, padding)
|
||||
{
|
||||
// TODO: Refactor this algorithm
|
||||
|
||||
public override int BlockSize
|
||||
{
|
||||
get { return 8; }
|
||||
}
|
||||
S0 = new uint[SBOX_SK];
|
||||
S1 = new uint[SBOX_SK];
|
||||
S2 = new uint[SBOX_SK];
|
||||
S3 = new uint[SBOX_SK];
|
||||
P = new uint[P_SZ];
|
||||
|
||||
public override int EncryptBlock(byte[] inputBuffer, int inputOffset, int inputCount, byte[] outputBuffer, int outputOffset)
|
||||
{
|
||||
if (inputCount != this.BlockSize)
|
||||
throw new ArgumentException("inputCount");
|
||||
this.SetKey(key);
|
||||
}
|
||||
|
||||
uint xl = CipherBase.BigEndianToUInt32(inputBuffer, inputOffset);
|
||||
uint xr = CipherBase.BigEndianToUInt32(inputBuffer, inputOffset + 4);
|
||||
/// <summary>
|
||||
/// Encrypts the specified region of the input byte array and copies the encrypted data to the specified region of the output byte array.
|
||||
/// </summary>
|
||||
/// <param name="inputBuffer">The input data to encrypt.</param>
|
||||
/// <param name="inputOffset">The offset into the input byte array from which to begin using data.</param>
|
||||
/// <param name="inputCount">The number of bytes in the input byte array to use as data.</param>
|
||||
/// <param name="outputBuffer">The output to which to write encrypted data.</param>
|
||||
/// <param name="outputOffset">The offset into the output byte array from which to begin writing data.</param>
|
||||
/// <returns>
|
||||
/// The number of bytes encrypted.
|
||||
/// </returns>
|
||||
public override int EncryptBlock(byte[] inputBuffer, int inputOffset, int inputCount, byte[] outputBuffer, int outputOffset)
|
||||
{
|
||||
if (inputCount != this.BlockSize)
|
||||
throw new ArgumentException("inputCount");
|
||||
|
||||
xl ^= P[0];
|
||||
uint xl = BigEndianToUInt32(inputBuffer, inputOffset);
|
||||
uint xr = BigEndianToUInt32(inputBuffer, inputOffset + 4);
|
||||
|
||||
for (int i = 1; i < ROUNDS; i += 2)
|
||||
{
|
||||
xr ^= F(xl) ^ P[i];
|
||||
xl ^= F(xr) ^ P[i + 1];
|
||||
}
|
||||
xl ^= P[0];
|
||||
|
||||
xr ^= P[ROUNDS + 1];
|
||||
for (int i = 1; i < ROUNDS; i += 2)
|
||||
{
|
||||
xr ^= F(xl) ^ P[i];
|
||||
xl ^= F(xr) ^ P[i + 1];
|
||||
}
|
||||
|
||||
CipherBase.UInt32ToBigEndian(xr, outputBuffer, outputOffset);
|
||||
CipherBase.UInt32ToBigEndian(xl, outputBuffer, outputOffset + 4);
|
||||
|
||||
return this.BlockSize;
|
||||
}
|
||||
xr ^= P[ROUNDS + 1];
|
||||
|
||||
public override int DecryptBlock(byte[] inputBuffer, int inputOffset, int inputCount, byte[] outputBuffer, int outputOffset)
|
||||
{
|
||||
if (inputCount != this.BlockSize)
|
||||
throw new ArgumentException("inputCount");
|
||||
UInt32ToBigEndian(xr, outputBuffer, outputOffset);
|
||||
UInt32ToBigEndian(xl, outputBuffer, outputOffset + 4);
|
||||
|
||||
uint xl = CipherBase.BigEndianToUInt32(inputBuffer, inputOffset);
|
||||
uint xr = CipherBase.BigEndianToUInt32(inputBuffer, inputOffset + 4);
|
||||
return this.BlockSize;
|
||||
}
|
||||
|
||||
xl ^= P[ROUNDS + 1];
|
||||
/// <summary>
|
||||
/// Decrypts the specified region of the input byte array and copies the decrypted data to the specified region of the output byte array.
|
||||
/// </summary>
|
||||
/// <param name="inputBuffer">The input data to decrypt.</param>
|
||||
/// <param name="inputOffset">The offset into the input byte array from which to begin using data.</param>
|
||||
/// <param name="inputCount">The number of bytes in the input byte array to use as data.</param>
|
||||
/// <param name="outputBuffer">The output to which to write decrypted data.</param>
|
||||
/// <param name="outputOffset">The offset into the output byte array from which to begin writing data.</param>
|
||||
/// <returns>
|
||||
/// The number of bytes decrypted.
|
||||
/// </returns>
|
||||
public override int DecryptBlock(byte[] inputBuffer, int inputOffset, int inputCount, byte[] outputBuffer, int outputOffset)
|
||||
{
|
||||
if (inputCount != this.BlockSize)
|
||||
throw new ArgumentException("inputCount");
|
||||
|
||||
for (int i = ROUNDS; i > 0; i -= 2)
|
||||
{
|
||||
xr ^= F(xl) ^ P[i];
|
||||
xl ^= F(xr) ^ P[i - 1];
|
||||
}
|
||||
uint xl = BigEndianToUInt32(inputBuffer, inputOffset);
|
||||
uint xr = BigEndianToUInt32(inputBuffer, inputOffset + 4);
|
||||
|
||||
xr ^= P[0];
|
||||
xl ^= P[ROUNDS + 1];
|
||||
|
||||
CipherBase.UInt32ToBigEndian(xr, outputBuffer, outputOffset);
|
||||
CipherBase.UInt32ToBigEndian(xl, outputBuffer, outputOffset + 4);
|
||||
for (int i = ROUNDS; i > 0; i -= 2)
|
||||
{
|
||||
xr ^= F(xl) ^ P[i];
|
||||
xl ^= F(xr) ^ P[i - 1];
|
||||
}
|
||||
|
||||
return this.BlockSize;
|
||||
}
|
||||
xr ^= P[0];
|
||||
|
||||
private uint F(uint x)
|
||||
{
|
||||
return (((S0[x >> 24] + S1[(x >> 16) & 0xff]) ^ S2[(x >> 8) & 0xff]) + S3[x & 0xff]);
|
||||
}
|
||||
UInt32ToBigEndian(xr, outputBuffer, outputOffset);
|
||||
UInt32ToBigEndian(xl, outputBuffer, outputOffset + 4);
|
||||
|
||||
return this.BlockSize;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// apply the encryption cycle to each value pair in the table.
|
||||
/// Validates the size of the key.
|
||||
/// </summary>
|
||||
/// <param name="xl">The xl.</param>
|
||||
/// <param name="xr">The xr.</param>
|
||||
/// <param name="table">The table.</param>
|
||||
private void ProcessTable(uint xl, uint xr, uint[] table)
|
||||
{
|
||||
int size = table.Length;
|
||||
/// <param name="keySize">Size of the key.</param>
|
||||
/// <returns>
|
||||
/// true if keySize is valid; otherwise false
|
||||
/// </returns>
|
||||
protected override bool ValidateKeySize(int keySize)
|
||||
{
|
||||
if (keySize >= 1 && keySize <= 448)
|
||||
return true;
|
||||
else
|
||||
return false;
|
||||
}
|
||||
|
||||
for (int s = 0; s < size; s += 2)
|
||||
{
|
||||
xl ^= P[0];
|
||||
private uint F(uint x)
|
||||
{
|
||||
return (((S0[x >> 24] + S1[(x >> 16) & 0xff]) ^ S2[(x >> 8) & 0xff]) + S3[x & 0xff]);
|
||||
}
|
||||
|
||||
for (int i = 1; i < ROUNDS; i += 2)
|
||||
{
|
||||
xr ^= F(xl) ^ P[i];
|
||||
xl ^= F(xr) ^ P[i + 1];
|
||||
}
|
||||
/// <summary>
|
||||
/// apply the encryption cycle to each value pair in the table.
|
||||
/// </summary>
|
||||
/// <param name="xl">The xl.</param>
|
||||
/// <param name="xr">The xr.</param>
|
||||
/// <param name="table">The table.</param>
|
||||
private void ProcessTable(uint xl, uint xr, uint[] table)
|
||||
{
|
||||
int size = table.Length;
|
||||
|
||||
xr ^= P[ROUNDS + 1];
|
||||
for (int s = 0; s < size; s += 2)
|
||||
{
|
||||
xl ^= P[0];
|
||||
|
||||
table[s] = xr;
|
||||
table[s + 1] = xl;
|
||||
for (int i = 1; i < ROUNDS; i += 2)
|
||||
{
|
||||
xr ^= F(xl) ^ P[i];
|
||||
xl ^= F(xr) ^ P[i + 1];
|
||||
}
|
||||
|
||||
xr = xl; // end of cycle swap
|
||||
xl = table[s];
|
||||
}
|
||||
}
|
||||
xr ^= P[ROUNDS + 1];
|
||||
|
||||
private void SetKey(byte[] key)
|
||||
{
|
||||
/*
|
||||
* - comments are from _Applied Crypto_, Schneier, p338
|
||||
* please be careful comparing the two, AC numbers the
|
||||
* arrays from 1, the enclosed code from 0.
|
||||
*
|
||||
* (1)
|
||||
* Initialise the S-boxes and the P-array, with a fixed string
|
||||
* This string contains the hexadecimal digits of pi (3.141...)
|
||||
*/
|
||||
Array.Copy(KS0, 0, S0, 0, SBOX_SK);
|
||||
Array.Copy(KS1, 0, S1, 0, SBOX_SK);
|
||||
Array.Copy(KS2, 0, S2, 0, SBOX_SK);
|
||||
Array.Copy(KS3, 0, S3, 0, SBOX_SK);
|
||||
table[s] = xr;
|
||||
table[s + 1] = xl;
|
||||
|
||||
Array.Copy(KP, 0, P, 0, P_SZ);
|
||||
xr = xl; // end of cycle swap
|
||||
xl = table[s];
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* (2)
|
||||
* Now, XOR P[0] with the first 32 bits of the key, XOR P[1] with the
|
||||
* second 32-bits of the key, and so on for all bits of the key
|
||||
* (up to P[17]). Repeatedly cycle through the key bits until the
|
||||
* entire P-array has been XOR-ed with the key bits
|
||||
*/
|
||||
int keyLength = key.Length;
|
||||
int keyIndex = 0;
|
||||
private void SetKey(byte[] key)
|
||||
{
|
||||
/*
|
||||
* - comments are from _Applied Crypto_, Schneier, p338
|
||||
* please be careful comparing the two, AC numbers the
|
||||
* arrays from 1, the enclosed code from 0.
|
||||
*
|
||||
* (1)
|
||||
* Initialise the S-boxes and the P-array, with a fixed string
|
||||
* This string contains the hexadecimal digits of pi (3.141...)
|
||||
*/
|
||||
Array.Copy(KS0, 0, S0, 0, SBOX_SK);
|
||||
Array.Copy(KS1, 0, S1, 0, SBOX_SK);
|
||||
Array.Copy(KS2, 0, S2, 0, SBOX_SK);
|
||||
Array.Copy(KS3, 0, S3, 0, SBOX_SK);
|
||||
|
||||
for (int i = 0; i < P_SZ; i++)
|
||||
{
|
||||
// Get the 32 bits of the key, in 4 * 8 bit chunks
|
||||
uint data = 0x0000000;
|
||||
for (int j = 0; j < 4; j++)
|
||||
{
|
||||
// create a 32 bit block
|
||||
data = (data << 8) | (uint)key[keyIndex++];
|
||||
Array.Copy(KP, 0, P, 0, P_SZ);
|
||||
|
||||
// wrap when we get to the end of the key
|
||||
if (keyIndex >= keyLength)
|
||||
{
|
||||
keyIndex = 0;
|
||||
}
|
||||
}
|
||||
// XOR the newly created 32 bit chunk onto the P-array
|
||||
P[i] ^= data;
|
||||
}
|
||||
/*
|
||||
* (2)
|
||||
* Now, XOR P[0] with the first 32 bits of the key, XOR P[1] with the
|
||||
* second 32-bits of the key, and so on for all bits of the key
|
||||
* (up to P[17]). Repeatedly cycle through the key bits until the
|
||||
* entire P-array has been XOR-ed with the key bits
|
||||
*/
|
||||
int keyLength = key.Length;
|
||||
int keyIndex = 0;
|
||||
|
||||
/*
|
||||
* (3)
|
||||
* Encrypt the all-zero string with the Blowfish algorithm, using
|
||||
* the subkeys described in (1) and (2)
|
||||
*
|
||||
* (4)
|
||||
* Replace P1 and P2 with the output of step (3)
|
||||
*
|
||||
* (5)
|
||||
* Encrypt the output of step(3) using the Blowfish algorithm,
|
||||
* with the modified subkeys.
|
||||
*
|
||||
* (6)
|
||||
* Replace P3 and P4 with the output of step (5)
|
||||
*
|
||||
* (7)
|
||||
* Continue the process, replacing all elements of the P-array
|
||||
* and then all four S-boxes in order, with the output of the
|
||||
* continuously changing Blowfish algorithm
|
||||
*/
|
||||
for (int i = 0; i < P_SZ; i++)
|
||||
{
|
||||
// Get the 32 bits of the key, in 4 * 8 bit chunks
|
||||
uint data = 0x0000000;
|
||||
for (int j = 0; j < 4; j++)
|
||||
{
|
||||
// create a 32 bit block
|
||||
data = (data << 8) | (uint)key[keyIndex++];
|
||||
|
||||
ProcessTable(0, 0, P);
|
||||
ProcessTable(P[P_SZ - 2], P[P_SZ - 1], S0);
|
||||
ProcessTable(S0[SBOX_SK - 2], S0[SBOX_SK - 1], S1);
|
||||
ProcessTable(S1[SBOX_SK - 2], S1[SBOX_SK - 1], S2);
|
||||
ProcessTable(S2[SBOX_SK - 2], S2[SBOX_SK - 1], S3);
|
||||
}
|
||||
}
|
||||
// wrap when we get to the end of the key
|
||||
if (keyIndex >= keyLength)
|
||||
{
|
||||
keyIndex = 0;
|
||||
}
|
||||
}
|
||||
// XOR the newly created 32 bit chunk onto the P-array
|
||||
P[i] ^= data;
|
||||
}
|
||||
|
||||
/*
|
||||
* (3)
|
||||
* Encrypt the all-zero string with the Blowfish algorithm, using
|
||||
* the subkeys described in (1) and (2)
|
||||
*
|
||||
* (4)
|
||||
* Replace P1 and P2 with the output of step (3)
|
||||
*
|
||||
* (5)
|
||||
* Encrypt the output of step(3) using the Blowfish algorithm,
|
||||
* with the modified subkeys.
|
||||
*
|
||||
* (6)
|
||||
* Replace P3 and P4 with the output of step (5)
|
||||
*
|
||||
* (7)
|
||||
* Continue the process, replacing all elements of the P-array
|
||||
* and then all four S-boxes in order, with the output of the
|
||||
* continuously changing Blowfish algorithm
|
||||
*/
|
||||
|
||||
ProcessTable(0, 0, P);
|
||||
ProcessTable(P[P_SZ - 2], P[P_SZ - 1], S0);
|
||||
ProcessTable(S0[SBOX_SK - 2], S0[SBOX_SK - 1], S1);
|
||||
ProcessTable(S1[SBOX_SK - 2], S1[SBOX_SK - 1], S2);
|
||||
ProcessTable(S2[SBOX_SK - 2], S2[SBOX_SK - 1], S3);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -3,11 +3,13 @@ using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
|
||||
namespace Renci.SshNet.Security.Cryptography
|
||||
namespace Renci.SshNet.Security.Cryptography.Ciphers
|
||||
{
|
||||
internal class CastCipher : CipherBase
|
||||
/// <summary>
|
||||
/// Implements CAST cipher algorithm
|
||||
/// </summary>
|
||||
public class CastCipher : BlockCipher
|
||||
{
|
||||
|
||||
internal static readonly int MAX_ROUNDS = 16;
|
||||
internal static readonly int RED_ROUNDS = 12;
|
||||
|
||||
@@ -16,54 +18,104 @@ namespace Renci.SshNet.Security.Cryptography
|
||||
|
||||
private int _rounds = MAX_ROUNDS;
|
||||
|
||||
/// <summary>
|
||||
/// Gets the size of the block in bytes.
|
||||
/// </summary>
|
||||
/// <value>
|
||||
/// The size of the block in bytes.
|
||||
/// </value>
|
||||
public override int BlockSize
|
||||
{
|
||||
get { return 8; }
|
||||
}
|
||||
|
||||
public CastCipher(byte[] key, byte[] iv)
|
||||
: base(key, iv)
|
||||
{
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="CastCipher"/> class.
|
||||
/// </summary>
|
||||
/// <param name="key">The key.</param>
|
||||
/// <param name="mode">The mode.</param>
|
||||
/// <param name="padding">The padding.</param>
|
||||
public CastCipher(byte[] key, CipherMode mode, CipherPadding padding)
|
||||
: base(key, mode, padding)
|
||||
{
|
||||
// TODO: Refactor this algorithm
|
||||
this.SetKey(key);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Encrypts the specified region of the input byte array and copies the encrypted data to the specified region of the output byte array.
|
||||
/// </summary>
|
||||
/// <param name="inputBuffer">The input data to encrypt.</param>
|
||||
/// <param name="inputOffset">The offset into the input byte array from which to begin using data.</param>
|
||||
/// <param name="inputCount">The number of bytes in the input byte array to use as data.</param>
|
||||
/// <param name="outputBuffer">The output to which to write encrypted data.</param>
|
||||
/// <param name="outputOffset">The offset into the output byte array from which to begin writing data.</param>
|
||||
/// <returns>
|
||||
/// The number of bytes encrypted.
|
||||
/// </returns>
|
||||
public override int EncryptBlock(byte[] inputBuffer, int inputOffset, int inputCount, byte[] outputBuffer, int outputOffset)
|
||||
{
|
||||
// process the input block
|
||||
// batch the units up into a 32 bit chunk and go for it
|
||||
// the array is in bytes, the increment is 8x8 bits = 64
|
||||
|
||||
uint L0 = CipherBase.BigEndianToUInt32(inputBuffer, inputOffset);
|
||||
uint R0 = CipherBase.BigEndianToUInt32(inputBuffer, inputOffset + 4);
|
||||
uint L0 = BigEndianToUInt32(inputBuffer, inputOffset);
|
||||
uint R0 = BigEndianToUInt32(inputBuffer, inputOffset + 4);
|
||||
|
||||
uint[] result = new uint[2];
|
||||
CAST_Encipher(L0, R0, result);
|
||||
CastEncipher(L0, R0, result);
|
||||
|
||||
// now stuff them into the destination block
|
||||
CipherBase.UInt32ToBigEndian(result[0], outputBuffer, outputOffset);
|
||||
CipherBase.UInt32ToBigEndian(result[1], outputBuffer, outputOffset + 4);
|
||||
UInt32ToBigEndian(result[0], outputBuffer, outputOffset);
|
||||
UInt32ToBigEndian(result[1], outputBuffer, outputOffset + 4);
|
||||
|
||||
return this.BlockSize;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Decrypts the specified region of the input byte array and copies the decrypted data to the specified region of the output byte array.
|
||||
/// </summary>
|
||||
/// <param name="inputBuffer">The input data to decrypt.</param>
|
||||
/// <param name="inputOffset">The offset into the input byte array from which to begin using data.</param>
|
||||
/// <param name="inputCount">The number of bytes in the input byte array to use as data.</param>
|
||||
/// <param name="outputBuffer">The output to which to write decrypted data.</param>
|
||||
/// <param name="outputOffset">The offset into the output byte array from which to begin writing data.</param>
|
||||
/// <returns>
|
||||
/// The number of bytes decrypted.
|
||||
/// </returns>
|
||||
public override int DecryptBlock(byte[] inputBuffer, int inputOffset, int inputCount, byte[] outputBuffer, int outputOffset)
|
||||
{
|
||||
// process the input block
|
||||
// batch the units up into a 32 bit chunk and go for it
|
||||
// the array is in bytes, the increment is 8x8 bits = 64
|
||||
uint L16 = CipherBase.BigEndianToUInt32(inputBuffer, inputOffset);
|
||||
uint R16 = CipherBase.BigEndianToUInt32(inputBuffer, inputOffset + 4);
|
||||
uint L16 = BigEndianToUInt32(inputBuffer, inputOffset);
|
||||
uint R16 = BigEndianToUInt32(inputBuffer, inputOffset + 4);
|
||||
|
||||
uint[] result = new uint[2];
|
||||
CAST_Decipher(L16, R16, result);
|
||||
CastDecipher(L16, R16, result);
|
||||
|
||||
// now stuff them into the destination block
|
||||
CipherBase.UInt32ToBigEndian(result[0], outputBuffer, outputOffset);
|
||||
CipherBase.UInt32ToBigEndian(result[1], outputBuffer, outputOffset + 4);
|
||||
UInt32ToBigEndian(result[0], outputBuffer, outputOffset);
|
||||
UInt32ToBigEndian(result[1], outputBuffer, outputOffset + 4);
|
||||
|
||||
return this.BlockSize;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Validates the size of the key.
|
||||
/// </summary>
|
||||
/// <param name="keySize">Size of the key.</param>
|
||||
/// <returns>
|
||||
/// true if keySize is valid; otherwise false
|
||||
/// </returns>
|
||||
protected override bool ValidateKeySize(int keySize)
|
||||
{
|
||||
if (keySize >= 40 && keySize <= 128 && keySize % 8 == 0)
|
||||
return true;
|
||||
else
|
||||
return false;
|
||||
}
|
||||
|
||||
#region Static Definition Tables
|
||||
|
||||
internal static readonly uint[] S1 =
|
||||
@@ -101,7 +153,7 @@ namespace Renci.SshNet.Security.Cryptography
|
||||
0xbd91e046, 0x9a56456e, 0xdc39200c, 0x20c8c571, 0x962bda1c, 0xe1e696ff, 0xb141ab08, 0x7cca89b9,
|
||||
0x1a69e783, 0x02cc4843, 0xa2f7c579, 0x429ef47d, 0x427b169c, 0x5ac9f049, 0xdd8f0f00, 0x5c8165bf
|
||||
},
|
||||
S2 =
|
||||
S2 =
|
||||
{
|
||||
0x1f201094, 0xef0ba75b, 0x69e3cf7e, 0x393f4380, 0xfe61cf7a, 0xeec5207a, 0x55889c94, 0x72fc0651,
|
||||
0xada7ef79, 0x4e1d7235, 0xd55a63ce, 0xde0436ba, 0x99c430ef, 0x5f0c0794, 0x18dcdb7d, 0xa1d6eff3,
|
||||
@@ -136,7 +188,7 @@ namespace Renci.SshNet.Security.Cryptography
|
||||
0x8f5ea2b3, 0xfc184642, 0x0a036b7a, 0x4fb089bd, 0x649da589, 0xa345415e, 0x5c038323, 0x3e5d3bb9,
|
||||
0x43d79572, 0x7e6dd07c, 0x06dfdf1e, 0x6c6cc4ef, 0x7160a539, 0x73bfbe70, 0x83877605, 0x4523ecf1
|
||||
},
|
||||
S3 =
|
||||
S3 =
|
||||
{
|
||||
0x8defc240, 0x25fa5d9f, 0xeb903dbf, 0xe810c907, 0x47607fff, 0x369fe44b, 0x8c1fc644, 0xaececa90,
|
||||
0xbeb1f9bf, 0xeefbcaea, 0xe8cf1950, 0x51df07ae, 0x920e8806, 0xf0ad0548, 0xe13c8d83, 0x927010d5,
|
||||
@@ -171,7 +223,7 @@ namespace Renci.SshNet.Security.Cryptography
|
||||
0x282f9350, 0x8334b362, 0xd91d1120, 0x2b6d8da0, 0x642b1e31, 0x9c305a00, 0x52bce688, 0x1b03588a,
|
||||
0xf7baefd5, 0x4142ed9c, 0xa4315c11, 0x83323ec5, 0xdfef4636, 0xa133c501, 0xe9d3531c, 0xee353783
|
||||
},
|
||||
S4 =
|
||||
S4 =
|
||||
{
|
||||
0x9db30420, 0x1fb6e9de, 0xa7be7bef, 0xd273a298, 0x4a4f7bdb, 0x64ad8c57, 0x85510443, 0xfa020ed1,
|
||||
0x7e287aff, 0xe60fb663, 0x095f35a1, 0x79ebf120, 0xfd059d43, 0x6497b7b1, 0xf3641f63, 0x241e4adf,
|
||||
@@ -206,7 +258,7 @@ namespace Renci.SshNet.Security.Cryptography
|
||||
0x8644213e, 0xb7dc59d0, 0x7965291f, 0xccd6fd43, 0x41823979, 0x932bcdf6, 0xb657c34d, 0x4edfd282,
|
||||
0x7ae5290c, 0x3cb9536b, 0x851e20fe, 0x9833557e, 0x13ecf0b0, 0xd3ffb372, 0x3f85c5c1, 0x0aef7ed2
|
||||
},
|
||||
S5 =
|
||||
S5 =
|
||||
{
|
||||
0x7ec90c04, 0x2c6e74b9, 0x9b0e66df, 0xa6337911, 0xb86a7fff, 0x1dd358f5, 0x44dd9d44, 0x1731167f,
|
||||
0x08fbf1fa, 0xe7f511cc, 0xd2051b00, 0x735aba00, 0x2ab722d8, 0x386381cb, 0xacf6243a, 0x69befd7a,
|
||||
@@ -241,7 +293,7 @@ namespace Renci.SshNet.Security.Cryptography
|
||||
0xd6cd2595, 0x68ff1ebf, 0x7555442c, 0xf19f06be, 0xf9e0659a, 0xeeb9491d, 0x34010718, 0xbb30cab8,
|
||||
0xe822fe15, 0x88570983, 0x750e6249, 0xda627e55, 0x5e76ffa8, 0xb1534546, 0x6d47de08, 0xefe9e7d4
|
||||
},
|
||||
S6 =
|
||||
S6 =
|
||||
{
|
||||
0xf6fa8f9d, 0x2cac6ce1, 0x4ca34867, 0xe2337f7c, 0x95db08e7, 0x016843b4, 0xeced5cbc, 0x325553ac,
|
||||
0xbf9f0960, 0xdfa1e2ed, 0x83f0579d, 0x63ed86b9, 0x1ab6a6b8, 0xde5ebe39, 0xf38ff732, 0x8989b138,
|
||||
@@ -276,7 +328,7 @@ namespace Renci.SshNet.Security.Cryptography
|
||||
0x3b4cbf9f, 0x4a5de3ab, 0xe6051d35, 0xa0e1d855, 0xd36b4cf1, 0xf544edeb, 0xb0e93524, 0xbebb8fbd,
|
||||
0xa2d762cf, 0x49c92f54, 0x38b5f331, 0x7128a454, 0x48392905, 0xa65b1db8, 0x851c97bd, 0xd675cf2f
|
||||
},
|
||||
S7 =
|
||||
S7 =
|
||||
{
|
||||
0x85e04019, 0x332bf567, 0x662dbfff, 0xcfc65693, 0x2a8d7f6f, 0xab9bc912, 0xde6008a1, 0x2028da1f,
|
||||
0x0227bce7, 0x4d642916, 0x18fac300, 0x50f18b82, 0x2cb2cb11, 0xb232e75c, 0x4b3695f2, 0xb28707de,
|
||||
@@ -311,7 +363,7 @@ namespace Renci.SshNet.Security.Cryptography
|
||||
0x91da55f4, 0x40a230f3, 0xd1988f35, 0xb6e318d2, 0x3ffa50bc, 0x3d40f021, 0xc3c0bdae, 0x4958c24c,
|
||||
0x518f36b2, 0x84b1d370, 0x0fedce83, 0x878ddada, 0xf2a279c7, 0x94e01be8, 0x90716f4b, 0x954b8aa3
|
||||
},
|
||||
S8 =
|
||||
S8 =
|
||||
{
|
||||
0xe216300d, 0xbbddfffc, 0xa7ebdabd, 0x35648095, 0x7789f8b7, 0xe6c1121b, 0x0e241600, 0x052ce8b5,
|
||||
0x11a9cfb0, 0xe5952f11, 0xece7990a, 0x9386d174, 0x2a42931c, 0x76e38111, 0xb12def3a, 0x37ddddfc,
|
||||
@@ -371,14 +423,14 @@ namespace Renci.SshNet.Security.Cryptography
|
||||
_rounds = RED_ROUNDS;
|
||||
}
|
||||
|
||||
int [] z = new int[16];
|
||||
int [] x = new int[16];
|
||||
int[] z = new int[16];
|
||||
int[] x = new int[16];
|
||||
|
||||
uint z03, z47, z8B, zCF;
|
||||
uint x03, x47, x8B, xCF;
|
||||
|
||||
/* copy the key into x */
|
||||
for (int i=0; i< key.Length; i++)
|
||||
for (int i = 0; i < key.Length; i++)
|
||||
{
|
||||
x[i] = (int)(key[i] & 0xff);
|
||||
}
|
||||
@@ -393,138 +445,138 @@ namespace Renci.SshNet.Security.Cryptography
|
||||
x8B = IntsTo32bits(x, 0x8);
|
||||
xCF = IntsTo32bits(x, 0xC);
|
||||
|
||||
z03 = x03 ^S5[x[0xD]] ^S6[x[0xF]] ^S7[x[0xC]] ^S8[x[0xE]] ^S7[x[0x8]];
|
||||
z03 = x03 ^ S5[x[0xD]] ^ S6[x[0xF]] ^ S7[x[0xC]] ^ S8[x[0xE]] ^ S7[x[0x8]];
|
||||
|
||||
Bits32ToInts(z03, z, 0x0);
|
||||
z47 = x8B ^S5[z[0x0]] ^S6[z[0x2]] ^S7[z[0x1]] ^S8[z[0x3]] ^S8[x[0xA]];
|
||||
z47 = x8B ^ S5[z[0x0]] ^ S6[z[0x2]] ^ S7[z[0x1]] ^ S8[z[0x3]] ^ S8[x[0xA]];
|
||||
Bits32ToInts(z47, z, 0x4);
|
||||
z8B = xCF ^S5[z[0x7]] ^S6[z[0x6]] ^S7[z[0x5]] ^S8[z[0x4]] ^S5[x[0x9]];
|
||||
z8B = xCF ^ S5[z[0x7]] ^ S6[z[0x6]] ^ S7[z[0x5]] ^ S8[z[0x4]] ^ S5[x[0x9]];
|
||||
Bits32ToInts(z8B, z, 0x8);
|
||||
zCF = x47 ^S5[z[0xA]] ^S6[z[0x9]] ^S7[z[0xB]] ^S8[z[0x8]] ^S6[x[0xB]];
|
||||
zCF = x47 ^ S5[z[0xA]] ^ S6[z[0x9]] ^ S7[z[0xB]] ^ S8[z[0x8]] ^ S6[x[0xB]];
|
||||
Bits32ToInts(zCF, z, 0xC);
|
||||
_Km[ 1]= S5[z[0x8]] ^ S6[z[0x9]] ^ S7[z[0x7]] ^ S8[z[0x6]] ^ S5[z[0x2]];
|
||||
_Km[ 2]= S5[z[0xA]] ^ S6[z[0xB]] ^ S7[z[0x5]] ^ S8[z[0x4]] ^ S6[z[0x6]];
|
||||
_Km[ 3]= S5[z[0xC]] ^ S6[z[0xD]] ^ S7[z[0x3]] ^ S8[z[0x2]] ^ S7[z[0x9]];
|
||||
_Km[ 4]= S5[z[0xE]] ^ S6[z[0xF]] ^ S7[z[0x1]] ^ S8[z[0x0]] ^ S8[z[0xC]];
|
||||
_Km[1] = S5[z[0x8]] ^ S6[z[0x9]] ^ S7[z[0x7]] ^ S8[z[0x6]] ^ S5[z[0x2]];
|
||||
_Km[2] = S5[z[0xA]] ^ S6[z[0xB]] ^ S7[z[0x5]] ^ S8[z[0x4]] ^ S6[z[0x6]];
|
||||
_Km[3] = S5[z[0xC]] ^ S6[z[0xD]] ^ S7[z[0x3]] ^ S8[z[0x2]] ^ S7[z[0x9]];
|
||||
_Km[4] = S5[z[0xE]] ^ S6[z[0xF]] ^ S7[z[0x1]] ^ S8[z[0x0]] ^ S8[z[0xC]];
|
||||
|
||||
z03 = IntsTo32bits(z, 0x0);
|
||||
z47 = IntsTo32bits(z, 0x4);
|
||||
z8B = IntsTo32bits(z, 0x8);
|
||||
zCF = IntsTo32bits(z, 0xC);
|
||||
x03 = z8B ^S5[z[0x5]] ^S6[z[0x7]] ^S7[z[0x4]] ^S8[z[0x6]] ^S7[z[0x0]];
|
||||
x03 = z8B ^ S5[z[0x5]] ^ S6[z[0x7]] ^ S7[z[0x4]] ^ S8[z[0x6]] ^ S7[z[0x0]];
|
||||
Bits32ToInts(x03, x, 0x0);
|
||||
x47 = z03 ^S5[x[0x0]] ^S6[x[0x2]] ^S7[x[0x1]] ^S8[x[0x3]] ^S8[z[0x2]];
|
||||
x47 = z03 ^ S5[x[0x0]] ^ S6[x[0x2]] ^ S7[x[0x1]] ^ S8[x[0x3]] ^ S8[z[0x2]];
|
||||
Bits32ToInts(x47, x, 0x4);
|
||||
x8B = z47 ^S5[x[0x7]] ^S6[x[0x6]] ^S7[x[0x5]] ^S8[x[0x4]] ^S5[z[0x1]];
|
||||
x8B = z47 ^ S5[x[0x7]] ^ S6[x[0x6]] ^ S7[x[0x5]] ^ S8[x[0x4]] ^ S5[z[0x1]];
|
||||
Bits32ToInts(x8B, x, 0x8);
|
||||
xCF = zCF ^S5[x[0xA]] ^S6[x[0x9]] ^S7[x[0xB]] ^S8[x[0x8]] ^S6[z[0x3]];
|
||||
xCF = zCF ^ S5[x[0xA]] ^ S6[x[0x9]] ^ S7[x[0xB]] ^ S8[x[0x8]] ^ S6[z[0x3]];
|
||||
Bits32ToInts(xCF, x, 0xC);
|
||||
_Km[ 5]= S5[x[0x3]] ^ S6[x[0x2]] ^ S7[x[0xC]] ^ S8[x[0xD]] ^ S5[x[0x8]];
|
||||
_Km[ 6]= S5[x[0x1]] ^ S6[x[0x0]] ^ S7[x[0xE]] ^ S8[x[0xF]] ^ S6[x[0xD]];
|
||||
_Km[ 7]= S5[x[0x7]] ^ S6[x[0x6]] ^ S7[x[0x8]] ^ S8[x[0x9]] ^ S7[x[0x3]];
|
||||
_Km[ 8]= S5[x[0x5]] ^ S6[x[0x4]] ^ S7[x[0xA]] ^ S8[x[0xB]] ^ S8[x[0x7]];
|
||||
_Km[5] = S5[x[0x3]] ^ S6[x[0x2]] ^ S7[x[0xC]] ^ S8[x[0xD]] ^ S5[x[0x8]];
|
||||
_Km[6] = S5[x[0x1]] ^ S6[x[0x0]] ^ S7[x[0xE]] ^ S8[x[0xF]] ^ S6[x[0xD]];
|
||||
_Km[7] = S5[x[0x7]] ^ S6[x[0x6]] ^ S7[x[0x8]] ^ S8[x[0x9]] ^ S7[x[0x3]];
|
||||
_Km[8] = S5[x[0x5]] ^ S6[x[0x4]] ^ S7[x[0xA]] ^ S8[x[0xB]] ^ S8[x[0x7]];
|
||||
|
||||
x03 = IntsTo32bits(x, 0x0);
|
||||
x47 = IntsTo32bits(x, 0x4);
|
||||
x8B = IntsTo32bits(x, 0x8);
|
||||
xCF = IntsTo32bits(x, 0xC);
|
||||
z03 = x03 ^S5[x[0xD]] ^S6[x[0xF]] ^S7[x[0xC]] ^S8[x[0xE]] ^S7[x[0x8]];
|
||||
z03 = x03 ^ S5[x[0xD]] ^ S6[x[0xF]] ^ S7[x[0xC]] ^ S8[x[0xE]] ^ S7[x[0x8]];
|
||||
Bits32ToInts(z03, z, 0x0);
|
||||
z47 = x8B ^S5[z[0x0]] ^S6[z[0x2]] ^S7[z[0x1]] ^S8[z[0x3]] ^S8[x[0xA]];
|
||||
z47 = x8B ^ S5[z[0x0]] ^ S6[z[0x2]] ^ S7[z[0x1]] ^ S8[z[0x3]] ^ S8[x[0xA]];
|
||||
Bits32ToInts(z47, z, 0x4);
|
||||
z8B = xCF ^S5[z[0x7]] ^S6[z[0x6]] ^S7[z[0x5]] ^S8[z[0x4]] ^S5[x[0x9]];
|
||||
z8B = xCF ^ S5[z[0x7]] ^ S6[z[0x6]] ^ S7[z[0x5]] ^ S8[z[0x4]] ^ S5[x[0x9]];
|
||||
Bits32ToInts(z8B, z, 0x8);
|
||||
zCF = x47 ^S5[z[0xA]] ^S6[z[0x9]] ^S7[z[0xB]] ^S8[z[0x8]] ^S6[x[0xB]];
|
||||
zCF = x47 ^ S5[z[0xA]] ^ S6[z[0x9]] ^ S7[z[0xB]] ^ S8[z[0x8]] ^ S6[x[0xB]];
|
||||
Bits32ToInts(zCF, z, 0xC);
|
||||
_Km[ 9]= S5[z[0x3]] ^ S6[z[0x2]] ^ S7[z[0xC]] ^ S8[z[0xD]] ^ S5[z[0x9]];
|
||||
_Km[10]= S5[z[0x1]] ^ S6[z[0x0]] ^ S7[z[0xE]] ^ S8[z[0xF]] ^ S6[z[0xc]];
|
||||
_Km[11]= S5[z[0x7]] ^ S6[z[0x6]] ^ S7[z[0x8]] ^ S8[z[0x9]] ^ S7[z[0x2]];
|
||||
_Km[12]= S5[z[0x5]] ^ S6[z[0x4]] ^ S7[z[0xA]] ^ S8[z[0xB]] ^ S8[z[0x6]];
|
||||
_Km[9] = S5[z[0x3]] ^ S6[z[0x2]] ^ S7[z[0xC]] ^ S8[z[0xD]] ^ S5[z[0x9]];
|
||||
_Km[10] = S5[z[0x1]] ^ S6[z[0x0]] ^ S7[z[0xE]] ^ S8[z[0xF]] ^ S6[z[0xc]];
|
||||
_Km[11] = S5[z[0x7]] ^ S6[z[0x6]] ^ S7[z[0x8]] ^ S8[z[0x9]] ^ S7[z[0x2]];
|
||||
_Km[12] = S5[z[0x5]] ^ S6[z[0x4]] ^ S7[z[0xA]] ^ S8[z[0xB]] ^ S8[z[0x6]];
|
||||
|
||||
z03 = IntsTo32bits(z, 0x0);
|
||||
z47 = IntsTo32bits(z, 0x4);
|
||||
z8B = IntsTo32bits(z, 0x8);
|
||||
zCF = IntsTo32bits(z, 0xC);
|
||||
x03 = z8B ^S5[z[0x5]] ^S6[z[0x7]] ^S7[z[0x4]] ^S8[z[0x6]] ^S7[z[0x0]];
|
||||
x03 = z8B ^ S5[z[0x5]] ^ S6[z[0x7]] ^ S7[z[0x4]] ^ S8[z[0x6]] ^ S7[z[0x0]];
|
||||
Bits32ToInts(x03, x, 0x0);
|
||||
x47 = z03 ^S5[x[0x0]] ^S6[x[0x2]] ^S7[x[0x1]] ^S8[x[0x3]] ^S8[z[0x2]];
|
||||
x47 = z03 ^ S5[x[0x0]] ^ S6[x[0x2]] ^ S7[x[0x1]] ^ S8[x[0x3]] ^ S8[z[0x2]];
|
||||
Bits32ToInts(x47, x, 0x4);
|
||||
x8B = z47 ^S5[x[0x7]] ^S6[x[0x6]] ^S7[x[0x5]] ^S8[x[0x4]] ^S5[z[0x1]];
|
||||
x8B = z47 ^ S5[x[0x7]] ^ S6[x[0x6]] ^ S7[x[0x5]] ^ S8[x[0x4]] ^ S5[z[0x1]];
|
||||
Bits32ToInts(x8B, x, 0x8);
|
||||
xCF = zCF ^S5[x[0xA]] ^S6[x[0x9]] ^S7[x[0xB]] ^S8[x[0x8]] ^S6[z[0x3]];
|
||||
xCF = zCF ^ S5[x[0xA]] ^ S6[x[0x9]] ^ S7[x[0xB]] ^ S8[x[0x8]] ^ S6[z[0x3]];
|
||||
Bits32ToInts(xCF, x, 0xC);
|
||||
_Km[13]= S5[x[0x8]] ^ S6[x[0x9]] ^ S7[x[0x7]] ^ S8[x[0x6]] ^ S5[x[0x3]];
|
||||
_Km[14]= S5[x[0xA]] ^ S6[x[0xB]] ^ S7[x[0x5]] ^ S8[x[0x4]] ^ S6[x[0x7]];
|
||||
_Km[15]= S5[x[0xC]] ^ S6[x[0xD]] ^ S7[x[0x3]] ^ S8[x[0x2]] ^ S7[x[0x8]];
|
||||
_Km[16]= S5[x[0xE]] ^ S6[x[0xF]] ^ S7[x[0x1]] ^ S8[x[0x0]] ^ S8[x[0xD]];
|
||||
_Km[13] = S5[x[0x8]] ^ S6[x[0x9]] ^ S7[x[0x7]] ^ S8[x[0x6]] ^ S5[x[0x3]];
|
||||
_Km[14] = S5[x[0xA]] ^ S6[x[0xB]] ^ S7[x[0x5]] ^ S8[x[0x4]] ^ S6[x[0x7]];
|
||||
_Km[15] = S5[x[0xC]] ^ S6[x[0xD]] ^ S7[x[0x3]] ^ S8[x[0x2]] ^ S7[x[0x8]];
|
||||
_Km[16] = S5[x[0xE]] ^ S6[x[0xF]] ^ S7[x[0x1]] ^ S8[x[0x0]] ^ S8[x[0xD]];
|
||||
|
||||
x03 = IntsTo32bits(x, 0x0);
|
||||
x47 = IntsTo32bits(x, 0x4);
|
||||
x8B = IntsTo32bits(x, 0x8);
|
||||
xCF = IntsTo32bits(x, 0xC);
|
||||
z03 = x03 ^S5[x[0xD]] ^S6[x[0xF]] ^S7[x[0xC]] ^S8[x[0xE]] ^S7[x[0x8]];
|
||||
z03 = x03 ^ S5[x[0xD]] ^ S6[x[0xF]] ^ S7[x[0xC]] ^ S8[x[0xE]] ^ S7[x[0x8]];
|
||||
Bits32ToInts(z03, z, 0x0);
|
||||
z47 = x8B ^S5[z[0x0]] ^S6[z[0x2]] ^S7[z[0x1]] ^S8[z[0x3]] ^S8[x[0xA]];
|
||||
z47 = x8B ^ S5[z[0x0]] ^ S6[z[0x2]] ^ S7[z[0x1]] ^ S8[z[0x3]] ^ S8[x[0xA]];
|
||||
Bits32ToInts(z47, z, 0x4);
|
||||
z8B = xCF ^S5[z[0x7]] ^S6[z[0x6]] ^S7[z[0x5]] ^S8[z[0x4]] ^S5[x[0x9]];
|
||||
z8B = xCF ^ S5[z[0x7]] ^ S6[z[0x6]] ^ S7[z[0x5]] ^ S8[z[0x4]] ^ S5[x[0x9]];
|
||||
Bits32ToInts(z8B, z, 0x8);
|
||||
zCF = x47 ^S5[z[0xA]] ^S6[z[0x9]] ^S7[z[0xB]] ^S8[z[0x8]] ^S6[x[0xB]];
|
||||
zCF = x47 ^ S5[z[0xA]] ^ S6[z[0x9]] ^ S7[z[0xB]] ^ S8[z[0x8]] ^ S6[x[0xB]];
|
||||
Bits32ToInts(zCF, z, 0xC);
|
||||
_Kr[ 1]=(int)((S5[z[0x8]]^S6[z[0x9]]^S7[z[0x7]]^S8[z[0x6]] ^ S5[z[0x2]])&0x1f);
|
||||
_Kr[ 2]=(int)((S5[z[0xA]]^S6[z[0xB]]^S7[z[0x5]]^S8[z[0x4]] ^ S6[z[0x6]])&0x1f);
|
||||
_Kr[ 3]=(int)((S5[z[0xC]]^S6[z[0xD]]^S7[z[0x3]]^S8[z[0x2]] ^ S7[z[0x9]])&0x1f);
|
||||
_Kr[ 4]=(int)((S5[z[0xE]]^S6[z[0xF]]^S7[z[0x1]]^S8[z[0x0]] ^ S8[z[0xC]])&0x1f);
|
||||
_Kr[1] = (int)((S5[z[0x8]] ^ S6[z[0x9]] ^ S7[z[0x7]] ^ S8[z[0x6]] ^ S5[z[0x2]]) & 0x1f);
|
||||
_Kr[2] = (int)((S5[z[0xA]] ^ S6[z[0xB]] ^ S7[z[0x5]] ^ S8[z[0x4]] ^ S6[z[0x6]]) & 0x1f);
|
||||
_Kr[3] = (int)((S5[z[0xC]] ^ S6[z[0xD]] ^ S7[z[0x3]] ^ S8[z[0x2]] ^ S7[z[0x9]]) & 0x1f);
|
||||
_Kr[4] = (int)((S5[z[0xE]] ^ S6[z[0xF]] ^ S7[z[0x1]] ^ S8[z[0x0]] ^ S8[z[0xC]]) & 0x1f);
|
||||
|
||||
z03 = IntsTo32bits(z, 0x0);
|
||||
z47 = IntsTo32bits(z, 0x4);
|
||||
z8B = IntsTo32bits(z, 0x8);
|
||||
zCF = IntsTo32bits(z, 0xC);
|
||||
x03 = z8B ^S5[z[0x5]] ^S6[z[0x7]] ^S7[z[0x4]] ^S8[z[0x6]] ^S7[z[0x0]];
|
||||
x03 = z8B ^ S5[z[0x5]] ^ S6[z[0x7]] ^ S7[z[0x4]] ^ S8[z[0x6]] ^ S7[z[0x0]];
|
||||
Bits32ToInts(x03, x, 0x0);
|
||||
x47 = z03 ^S5[x[0x0]] ^S6[x[0x2]] ^S7[x[0x1]] ^S8[x[0x3]] ^S8[z[0x2]];
|
||||
x47 = z03 ^ S5[x[0x0]] ^ S6[x[0x2]] ^ S7[x[0x1]] ^ S8[x[0x3]] ^ S8[z[0x2]];
|
||||
Bits32ToInts(x47, x, 0x4);
|
||||
x8B = z47 ^S5[x[0x7]] ^S6[x[0x6]] ^S7[x[0x5]] ^S8[x[0x4]] ^S5[z[0x1]];
|
||||
x8B = z47 ^ S5[x[0x7]] ^ S6[x[0x6]] ^ S7[x[0x5]] ^ S8[x[0x4]] ^ S5[z[0x1]];
|
||||
Bits32ToInts(x8B, x, 0x8);
|
||||
xCF = zCF ^S5[x[0xA]] ^S6[x[0x9]] ^S7[x[0xB]] ^S8[x[0x8]] ^S6[z[0x3]];
|
||||
xCF = zCF ^ S5[x[0xA]] ^ S6[x[0x9]] ^ S7[x[0xB]] ^ S8[x[0x8]] ^ S6[z[0x3]];
|
||||
Bits32ToInts(xCF, x, 0xC);
|
||||
_Kr[ 5]=(int)((S5[x[0x3]]^S6[x[0x2]]^S7[x[0xC]]^S8[x[0xD]]^S5[x[0x8]])&0x1f);
|
||||
_Kr[ 6]=(int)((S5[x[0x1]]^S6[x[0x0]]^S7[x[0xE]]^S8[x[0xF]]^S6[x[0xD]])&0x1f);
|
||||
_Kr[ 7]=(int)((S5[x[0x7]]^S6[x[0x6]]^S7[x[0x8]]^S8[x[0x9]]^S7[x[0x3]])&0x1f);
|
||||
_Kr[ 8]=(int)((S5[x[0x5]]^S6[x[0x4]]^S7[x[0xA]]^S8[x[0xB]]^S8[x[0x7]])&0x1f);
|
||||
_Kr[5] = (int)((S5[x[0x3]] ^ S6[x[0x2]] ^ S7[x[0xC]] ^ S8[x[0xD]] ^ S5[x[0x8]]) & 0x1f);
|
||||
_Kr[6] = (int)((S5[x[0x1]] ^ S6[x[0x0]] ^ S7[x[0xE]] ^ S8[x[0xF]] ^ S6[x[0xD]]) & 0x1f);
|
||||
_Kr[7] = (int)((S5[x[0x7]] ^ S6[x[0x6]] ^ S7[x[0x8]] ^ S8[x[0x9]] ^ S7[x[0x3]]) & 0x1f);
|
||||
_Kr[8] = (int)((S5[x[0x5]] ^ S6[x[0x4]] ^ S7[x[0xA]] ^ S8[x[0xB]] ^ S8[x[0x7]]) & 0x1f);
|
||||
|
||||
x03 = IntsTo32bits(x, 0x0);
|
||||
x47 = IntsTo32bits(x, 0x4);
|
||||
x8B = IntsTo32bits(x, 0x8);
|
||||
xCF = IntsTo32bits(x, 0xC);
|
||||
z03 = x03 ^S5[x[0xD]] ^S6[x[0xF]] ^S7[x[0xC]] ^S8[x[0xE]] ^S7[x[0x8]];
|
||||
z03 = x03 ^ S5[x[0xD]] ^ S6[x[0xF]] ^ S7[x[0xC]] ^ S8[x[0xE]] ^ S7[x[0x8]];
|
||||
Bits32ToInts(z03, z, 0x0);
|
||||
z47 = x8B ^S5[z[0x0]] ^S6[z[0x2]] ^S7[z[0x1]] ^S8[z[0x3]] ^S8[x[0xA]];
|
||||
z47 = x8B ^ S5[z[0x0]] ^ S6[z[0x2]] ^ S7[z[0x1]] ^ S8[z[0x3]] ^ S8[x[0xA]];
|
||||
Bits32ToInts(z47, z, 0x4);
|
||||
z8B = xCF ^S5[z[0x7]] ^S6[z[0x6]] ^S7[z[0x5]] ^S8[z[0x4]] ^S5[x[0x9]];
|
||||
z8B = xCF ^ S5[z[0x7]] ^ S6[z[0x6]] ^ S7[z[0x5]] ^ S8[z[0x4]] ^ S5[x[0x9]];
|
||||
Bits32ToInts(z8B, z, 0x8);
|
||||
zCF = x47 ^S5[z[0xA]] ^S6[z[0x9]] ^S7[z[0xB]] ^S8[z[0x8]] ^S6[x[0xB]];
|
||||
zCF = x47 ^ S5[z[0xA]] ^ S6[z[0x9]] ^ S7[z[0xB]] ^ S8[z[0x8]] ^ S6[x[0xB]];
|
||||
Bits32ToInts(zCF, z, 0xC);
|
||||
_Kr[ 9]=(int)((S5[z[0x3]]^S6[z[0x2]]^S7[z[0xC]]^S8[z[0xD]]^S5[z[0x9]])&0x1f);
|
||||
_Kr[10]=(int)((S5[z[0x1]]^S6[z[0x0]]^S7[z[0xE]]^S8[z[0xF]]^S6[z[0xc]])&0x1f);
|
||||
_Kr[11]=(int)((S5[z[0x7]]^S6[z[0x6]]^S7[z[0x8]]^S8[z[0x9]]^S7[z[0x2]])&0x1f);
|
||||
_Kr[12]=(int)((S5[z[0x5]]^S6[z[0x4]]^S7[z[0xA]]^S8[z[0xB]]^S8[z[0x6]])&0x1f);
|
||||
_Kr[9] = (int)((S5[z[0x3]] ^ S6[z[0x2]] ^ S7[z[0xC]] ^ S8[z[0xD]] ^ S5[z[0x9]]) & 0x1f);
|
||||
_Kr[10] = (int)((S5[z[0x1]] ^ S6[z[0x0]] ^ S7[z[0xE]] ^ S8[z[0xF]] ^ S6[z[0xc]]) & 0x1f);
|
||||
_Kr[11] = (int)((S5[z[0x7]] ^ S6[z[0x6]] ^ S7[z[0x8]] ^ S8[z[0x9]] ^ S7[z[0x2]]) & 0x1f);
|
||||
_Kr[12] = (int)((S5[z[0x5]] ^ S6[z[0x4]] ^ S7[z[0xA]] ^ S8[z[0xB]] ^ S8[z[0x6]]) & 0x1f);
|
||||
|
||||
z03 = IntsTo32bits(z, 0x0);
|
||||
z47 = IntsTo32bits(z, 0x4);
|
||||
z8B = IntsTo32bits(z, 0x8);
|
||||
zCF = IntsTo32bits(z, 0xC);
|
||||
x03 = z8B ^S5[z[0x5]] ^S6[z[0x7]] ^S7[z[0x4]] ^S8[z[0x6]] ^S7[z[0x0]];
|
||||
x03 = z8B ^ S5[z[0x5]] ^ S6[z[0x7]] ^ S7[z[0x4]] ^ S8[z[0x6]] ^ S7[z[0x0]];
|
||||
Bits32ToInts(x03, x, 0x0);
|
||||
x47 = z03 ^S5[x[0x0]] ^S6[x[0x2]] ^S7[x[0x1]] ^S8[x[0x3]] ^S8[z[0x2]];
|
||||
x47 = z03 ^ S5[x[0x0]] ^ S6[x[0x2]] ^ S7[x[0x1]] ^ S8[x[0x3]] ^ S8[z[0x2]];
|
||||
Bits32ToInts(x47, x, 0x4);
|
||||
x8B = z47 ^S5[x[0x7]] ^S6[x[0x6]] ^S7[x[0x5]] ^S8[x[0x4]] ^S5[z[0x1]];
|
||||
x8B = z47 ^ S5[x[0x7]] ^ S6[x[0x6]] ^ S7[x[0x5]] ^ S8[x[0x4]] ^ S5[z[0x1]];
|
||||
Bits32ToInts(x8B, x, 0x8);
|
||||
xCF = zCF ^S5[x[0xA]] ^S6[x[0x9]] ^S7[x[0xB]] ^S8[x[0x8]] ^S6[z[0x3]];
|
||||
xCF = zCF ^ S5[x[0xA]] ^ S6[x[0x9]] ^ S7[x[0xB]] ^ S8[x[0x8]] ^ S6[z[0x3]];
|
||||
Bits32ToInts(xCF, x, 0xC);
|
||||
_Kr[13]=(int)((S5[x[0x8]]^S6[x[0x9]]^S7[x[0x7]]^S8[x[0x6]]^S5[x[0x3]])&0x1f);
|
||||
_Kr[14]=(int)((S5[x[0xA]]^S6[x[0xB]]^S7[x[0x5]]^S8[x[0x4]]^S6[x[0x7]])&0x1f);
|
||||
_Kr[15]=(int)((S5[x[0xC]]^S6[x[0xD]]^S7[x[0x3]]^S8[x[0x2]]^S7[x[0x8]])&0x1f);
|
||||
_Kr[16]=(int)((S5[x[0xE]]^S6[x[0xF]]^S7[x[0x1]]^S8[x[0x0]]^S8[x[0xD]])&0x1f);
|
||||
_Kr[13] = (int)((S5[x[0x8]] ^ S6[x[0x9]] ^ S7[x[0x7]] ^ S8[x[0x6]] ^ S5[x[0x3]]) & 0x1f);
|
||||
_Kr[14] = (int)((S5[x[0xA]] ^ S6[x[0xB]] ^ S7[x[0x5]] ^ S8[x[0x4]] ^ S6[x[0x7]]) & 0x1f);
|
||||
_Kr[15] = (int)((S5[x[0xC]] ^ S6[x[0xD]] ^ S7[x[0x3]] ^ S8[x[0x2]] ^ S7[x[0x8]]) & 0x1f);
|
||||
_Kr[16] = (int)((S5[x[0xE]] ^ S6[x[0xF]] ^ S7[x[0x1]] ^ S8[x[0x0]] ^ S8[x[0xD]]) & 0x1f);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -536,11 +588,11 @@ namespace Renci.SshNet.Security.Cryptography
|
||||
* @param Kri the rotation value to be used
|
||||
*
|
||||
*/
|
||||
internal static uint F1(uint D, uint Kmi, int Kri)
|
||||
private static uint F1(uint D, uint Kmi, int Kri)
|
||||
{
|
||||
uint I = Kmi + D;
|
||||
I = I << Kri | (I >> (32-Kri));
|
||||
return ((S1[(I>>24)&0xff]^S2[(I>>16)&0xff])-S3[(I>>8)&0xff])+S4[I&0xff];
|
||||
I = I << Kri | (I >> (32 - Kri));
|
||||
return ((S1[(I >> 24) & 0xff] ^ S2[(I >> 16) & 0xff]) - S3[(I >> 8) & 0xff]) + S4[I & 0xff];
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -552,11 +604,11 @@ namespace Renci.SshNet.Security.Cryptography
|
||||
* @param Kri the rotation value to be used
|
||||
*
|
||||
*/
|
||||
internal static uint F2(uint D, uint Kmi, int Kri)
|
||||
private static uint F2(uint D, uint Kmi, int Kri)
|
||||
{
|
||||
uint I = Kmi ^ D;
|
||||
I = I << Kri | (I >> (32-Kri));
|
||||
return ((S1[(I>>24)&0xff]-S2[(I>>16)&0xff])+S3[(I>>8)&0xff])^S4[I&0xff];
|
||||
I = I << Kri | (I >> (32 - Kri));
|
||||
return ((S1[(I >> 24) & 0xff] - S2[(I >> 16) & 0xff]) + S3[(I >> 8) & 0xff]) ^ S4[I & 0xff];
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -568,11 +620,11 @@ namespace Renci.SshNet.Security.Cryptography
|
||||
* @param Kri the rotation value to be used
|
||||
*
|
||||
*/
|
||||
internal static uint F3(uint D, uint Kmi, int Kri)
|
||||
private static uint F3(uint D, uint Kmi, int Kri)
|
||||
{
|
||||
uint I = Kmi - D;
|
||||
I = I << Kri | (I >> (32-Kri));
|
||||
return ((S1[(I>>24)&0xff]+S2[(I>>16)&0xff])^S3[(I>>8)&0xff])-S4[I&0xff];
|
||||
I = I << Kri | (I >> (32 - Kri));
|
||||
return ((S1[(I >> 24) & 0xff] + S2[(I >> 16) & 0xff]) ^ S3[(I >> 8) & 0xff]) - S4[I & 0xff];
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -581,7 +633,7 @@ namespace Renci.SshNet.Security.Cryptography
|
||||
* @param L0 the LH-32bits of the plaintext block
|
||||
* @param R0 the RH-32bits of the plaintext block
|
||||
*/
|
||||
internal void CAST_Encipher(uint L0, uint R0, uint[] result)
|
||||
private void CastEncipher(uint L0, uint R0, uint[] result)
|
||||
{
|
||||
uint Lp = L0; // the previous value, equiv to L[i-1]
|
||||
uint Rp = R0; // equivalent to R[i-1]
|
||||
@@ -592,7 +644,7 @@ namespace Renci.SshNet.Security.Cryptography
|
||||
*/
|
||||
uint Li = L0, Ri = R0;
|
||||
|
||||
for (int i = 1; i<=_rounds ; i++)
|
||||
for (int i = 1; i <= _rounds; i++)
|
||||
{
|
||||
Lp = Li;
|
||||
Rp = Ri;
|
||||
@@ -600,24 +652,24 @@ namespace Renci.SshNet.Security.Cryptography
|
||||
Li = Rp;
|
||||
switch (i)
|
||||
{
|
||||
case 1:
|
||||
case 4:
|
||||
case 7:
|
||||
case 1:
|
||||
case 4:
|
||||
case 7:
|
||||
case 10:
|
||||
case 13:
|
||||
case 16:
|
||||
Ri = Lp ^ F1(Rp, _Km[i], _Kr[i]);
|
||||
break;
|
||||
case 2:
|
||||
case 5:
|
||||
case 8:
|
||||
case 2:
|
||||
case 5:
|
||||
case 8:
|
||||
case 11:
|
||||
case 14:
|
||||
Ri = Lp ^ F2(Rp, _Km[i], _Kr[i]);
|
||||
break;
|
||||
case 3:
|
||||
case 6:
|
||||
case 9:
|
||||
case 3:
|
||||
case 6:
|
||||
case 9:
|
||||
case 12:
|
||||
case 15:
|
||||
Ri = Lp ^ F3(Rp, _Km[i], _Kr[i]);
|
||||
@@ -631,7 +683,7 @@ namespace Renci.SshNet.Security.Cryptography
|
||||
return;
|
||||
}
|
||||
|
||||
internal void CAST_Decipher(uint L16, uint R16, uint[] result)
|
||||
private void CastDecipher(uint L16, uint R16, uint[] result)
|
||||
{
|
||||
uint Lp = L16; // the previous value, equiv to L[i-1]
|
||||
uint Rp = R16; // equivalent to R[i-1]
|
||||
@@ -650,24 +702,24 @@ namespace Renci.SshNet.Security.Cryptography
|
||||
Li = Rp;
|
||||
switch (i)
|
||||
{
|
||||
case 1:
|
||||
case 4:
|
||||
case 7:
|
||||
case 1:
|
||||
case 4:
|
||||
case 7:
|
||||
case 10:
|
||||
case 13:
|
||||
case 16:
|
||||
Ri = Lp ^ F1(Rp, _Km[i], _Kr[i]);
|
||||
break;
|
||||
case 2:
|
||||
case 5:
|
||||
case 8:
|
||||
case 2:
|
||||
case 5:
|
||||
case 8:
|
||||
case 11:
|
||||
case 14:
|
||||
Ri = Lp ^ F2(Rp, _Km[i], _Kr[i]);
|
||||
break;
|
||||
case 3:
|
||||
case 6:
|
||||
case 9:
|
||||
case 3:
|
||||
case 6:
|
||||
case 9:
|
||||
case 12:
|
||||
case 15:
|
||||
Ri = Lp ^ F3(Rp, _Km[i], _Kr[i]);
|
||||
@@ -681,20 +733,21 @@ namespace Renci.SshNet.Security.Cryptography
|
||||
return;
|
||||
}
|
||||
|
||||
internal static void Bits32ToInts(uint inData, int[] b, int offset)
|
||||
private static void Bits32ToInts(uint inData, int[] b, int offset)
|
||||
{
|
||||
b[offset + 3] = (int) (inData & 0xff);
|
||||
b[offset + 2] = (int) ((inData >> 8) & 0xff);
|
||||
b[offset + 1] = (int) ((inData >> 16) & 0xff);
|
||||
b[offset] = (int) ((inData >> 24) & 0xff);
|
||||
b[offset + 3] = (int)(inData & 0xff);
|
||||
b[offset + 2] = (int)((inData >> 8) & 0xff);
|
||||
b[offset + 1] = (int)((inData >> 16) & 0xff);
|
||||
b[offset] = (int)((inData >> 24) & 0xff);
|
||||
}
|
||||
|
||||
internal static uint IntsTo32bits(int[] b, int i)
|
||||
private static uint IntsTo32bits(int[] b, int i)
|
||||
{
|
||||
return (uint)(((b[i] & 0xff) << 24) |
|
||||
((b[i+1] & 0xff) << 16) |
|
||||
((b[i+2] & 0xff) << 8) |
|
||||
((b[i+3] & 0xff)));
|
||||
return (uint)(((b[i] & 0xff) << 24) |
|
||||
((b[i + 1] & 0xff) << 16) |
|
||||
((b[i + 2] & 0xff) << 8) |
|
||||
((b[i + 3] & 0xff)));
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,68 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
|
||||
namespace Renci.SshNet.Security.Cryptography.Ciphers
|
||||
{
|
||||
/// <summary>
|
||||
/// Base class for cipher mode implementations
|
||||
/// </summary>
|
||||
public abstract class CipherMode
|
||||
{
|
||||
/// <summary>
|
||||
/// Gets the cipher.
|
||||
/// </summary>
|
||||
protected BlockCipher Cipher { get; private set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets the IV vector.
|
||||
/// </summary>
|
||||
protected byte[] IV { get; private set; }
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="CipherMode"/> class.
|
||||
/// </summary>
|
||||
/// <param name="iv">The iv.</param>
|
||||
protected CipherMode(byte[] iv)
|
||||
{
|
||||
this.IV = iv;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Inits the specified cipher.
|
||||
/// </summary>
|
||||
/// <param name="cipher">The cipher.</param>
|
||||
internal void Init(BlockCipher cipher)
|
||||
{
|
||||
this.Cipher = cipher;
|
||||
this.IV = this.IV.Take(cipher.BlockSize).ToArray();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Encrypts the specified region of the input byte array and copies the encrypted data to the specified region of the output byte array.
|
||||
/// </summary>
|
||||
/// <param name="inputBuffer">The input data to encrypt.</param>
|
||||
/// <param name="inputOffset">The offset into the input byte array from which to begin using data.</param>
|
||||
/// <param name="inputCount">The number of bytes in the input byte array to use as data.</param>
|
||||
/// <param name="outputBuffer">The output to which to write encrypted data.</param>
|
||||
/// <param name="outputOffset">The offset into the output byte array from which to begin writing data.</param>
|
||||
/// <returns>
|
||||
/// The number of bytes encrypted.
|
||||
/// </returns>
|
||||
public abstract int EncryptBlock(byte[] inputBuffer, int inputOffset, int inputCount, byte[] outputBuffer, int outputOffset);
|
||||
|
||||
/// <summary>
|
||||
/// Decrypts the specified region of the input byte array and copies the decrypted data to the specified region of the output byte array.
|
||||
/// </summary>
|
||||
/// <param name="inputBuffer">The input data to decrypt.</param>
|
||||
/// <param name="inputOffset">The offset into the input byte array from which to begin using data.</param>
|
||||
/// <param name="inputCount">The number of bytes in the input byte array to use as data.</param>
|
||||
/// <param name="outputBuffer">The output to which to write decrypted data.</param>
|
||||
/// <param name="outputOffset">The offset into the output byte array from which to begin writing data.</param>
|
||||
/// <returns>
|
||||
/// The number of bytes decrypted.
|
||||
/// </returns>
|
||||
public abstract int DecryptBlock(byte[] inputBuffer, int inputOffset, int inputCount, byte[] outputBuffer, int outputOffset);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,21 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
|
||||
namespace Renci.SshNet.Security.Cryptography.Ciphers
|
||||
{
|
||||
/// <summary>
|
||||
/// Base class for cipher padding implementations
|
||||
/// </summary>
|
||||
public abstract class CipherPadding
|
||||
{
|
||||
/// <summary>
|
||||
/// Pads specified input to match block size.
|
||||
/// </summary>
|
||||
/// <param name="blockSize">Size of the block.</param>
|
||||
/// <param name="input">The input.</param>
|
||||
/// <returns></returns>
|
||||
public abstract byte[] Pad(int blockSize, byte[] input);
|
||||
}
|
||||
}
|
||||
@@ -2,47 +2,27 @@
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Security.Cryptography;
|
||||
|
||||
namespace Renci.SshNet.Security.Cryptography
|
||||
namespace Renci.SshNet.Security.Cryptography.Ciphers
|
||||
{
|
||||
/// <summary>
|
||||
/// Represents the class for the DES algorithm.
|
||||
/// </summary>
|
||||
public class DesCipher : CipherBase
|
||||
/// <summary>
|
||||
/// Implements DES cipher algorithm.
|
||||
/// </summary>
|
||||
public class DesCipher : BlockCipher
|
||||
{
|
||||
private int[] _encryptionKey;
|
||||
private readonly int[] _encryptionKey;
|
||||
|
||||
private readonly int[] _decryptionKey;
|
||||
|
||||
/// <summary>
|
||||
/// Gets the encryption key.
|
||||
/// Gets the size of the block in bytes.
|
||||
/// </summary>
|
||||
protected int[] EncryptionKey
|
||||
/// <value>
|
||||
/// The size of the block in bytes.
|
||||
/// </value>
|
||||
public override int BlockSize
|
||||
{
|
||||
get
|
||||
{
|
||||
if (this._encryptionKey == null)
|
||||
{
|
||||
this._encryptionKey = DesCipher.GenerateWorkingKey(true, this.Key);
|
||||
}
|
||||
|
||||
return this._encryptionKey;
|
||||
}
|
||||
}
|
||||
|
||||
private int[] _decryptionKey;
|
||||
/// <summary>
|
||||
/// Gets the decryption key.
|
||||
/// </summary>
|
||||
protected int[] DecryptionKey
|
||||
{
|
||||
get
|
||||
{
|
||||
if (this._decryptionKey == null)
|
||||
{
|
||||
this._decryptionKey = DesCipher.GenerateWorkingKey(true, this.Key);
|
||||
}
|
||||
|
||||
return this._decryptionKey;
|
||||
}
|
||||
get { return 8; }
|
||||
}
|
||||
|
||||
#region Static tables
|
||||
@@ -249,25 +229,17 @@ namespace Renci.SshNet.Security.Cryptography
|
||||
|
||||
#endregion
|
||||
|
||||
/// <summary>
|
||||
/// Gets the size of the block.
|
||||
/// </summary>
|
||||
/// <value>
|
||||
/// The size of the block.
|
||||
/// </value>
|
||||
public override int BlockSize
|
||||
{
|
||||
get { return 8; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="DesCipher"/> class.
|
||||
/// </summary>
|
||||
/// <param name="key">The key.</param>
|
||||
/// <param name="iv">The iv.</param>
|
||||
public DesCipher(byte[] key, byte[] iv)
|
||||
: base(key, iv)
|
||||
/// <param name="mode">The mode.</param>
|
||||
/// <param name="padding">The padding.</param>
|
||||
public DesCipher(byte[] key, CipherMode mode, CipherPadding padding)
|
||||
: base(key, mode, padding)
|
||||
{
|
||||
this._encryptionKey = GenerateWorkingKey(true, key);
|
||||
this._decryptionKey = GenerateWorkingKey(false, key);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -289,7 +261,7 @@ namespace Renci.SshNet.Security.Cryptography
|
||||
if ((outputOffset + this.BlockSize) > outputBuffer.Length)
|
||||
throw new IndexOutOfRangeException("output buffer too short");
|
||||
|
||||
DesCipher.DesFunc(this.EncryptionKey, inputBuffer, inputOffset, outputBuffer, outputOffset);
|
||||
DesCipher.DesFunc(this._encryptionKey, inputBuffer, inputOffset, outputBuffer, outputOffset);
|
||||
|
||||
return this.BlockSize;
|
||||
}
|
||||
@@ -313,9 +285,25 @@ namespace Renci.SshNet.Security.Cryptography
|
||||
if ((outputOffset + this.BlockSize) > outputBuffer.Length)
|
||||
throw new IndexOutOfRangeException("output buffer too short");
|
||||
|
||||
DesCipher.DesFunc(this.DecryptionKey, inputBuffer, inputOffset, outputBuffer, outputOffset);
|
||||
DesCipher.DesFunc(this._decryptionKey, inputBuffer, inputOffset, outputBuffer, outputOffset);
|
||||
|
||||
return this.BlockSize;
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Validates the size of the key.
|
||||
/// </summary>
|
||||
/// <param name="keySize">Size of the key.</param>
|
||||
/// <returns>
|
||||
/// true if keySize is valid; otherwise false
|
||||
/// </returns>
|
||||
protected override bool ValidateKeySize(int keySize)
|
||||
{
|
||||
if (keySize == 56)
|
||||
return true;
|
||||
else
|
||||
return false;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -427,8 +415,8 @@ namespace Renci.SshNet.Security.Cryptography
|
||||
/// <param name="outOff">The out off.</param>
|
||||
protected static void DesFunc(int[] wKey, byte[] input, int inOff, byte[] outBytes, int outOff)
|
||||
{
|
||||
uint left = CipherBase.BigEndianToUInt32(input, inOff);
|
||||
uint right = CipherBase.BigEndianToUInt32(input, inOff + 4);
|
||||
uint left = BigEndianToUInt32(input, inOff);
|
||||
uint right = BigEndianToUInt32(input, inOff + 4);
|
||||
uint work;
|
||||
|
||||
work = ((left >> 4) ^ right) & 0x0f0f0f0f;
|
||||
@@ -497,10 +485,8 @@ namespace Renci.SshNet.Security.Cryptography
|
||||
left ^= work;
|
||||
right ^= (work << 4);
|
||||
|
||||
CipherBase.UInt32ToBigEndian(right, outBytes, outOff);
|
||||
CipherBase.UInt32ToBigEndian(left, outBytes, outOff + 4);
|
||||
UInt32ToBigEndian(right, outBytes, outOff);
|
||||
UInt32ToBigEndian(left, outBytes, outOff + 4);
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
+24
-47
@@ -4,40 +4,20 @@ using System.Linq;
|
||||
using System.Text;
|
||||
using System.Globalization;
|
||||
|
||||
namespace Renci.SshNet.Security.Cryptography
|
||||
namespace Renci.SshNet.Security.Cryptography.Ciphers.Modes
|
||||
{
|
||||
/// <summary>
|
||||
/// Represents the class for the CBC Block Cipher.
|
||||
/// Implements CBC cipher mode
|
||||
/// </summary>
|
||||
public class CbcMode : ModeBase
|
||||
public class CbcCipherMode : CipherMode
|
||||
{
|
||||
private byte[] _iv;
|
||||
|
||||
private byte[] _nextIV;
|
||||
|
||||
private int _blockSize;
|
||||
|
||||
/// <summary>
|
||||
/// Gets the size of the block.
|
||||
/// Initializes a new instance of the <see cref="CbcCipherMode"/> class.
|
||||
/// </summary>
|
||||
/// <value>
|
||||
/// The size of the block.
|
||||
/// </value>
|
||||
public override int BlockSize
|
||||
/// <param name="iv">The iv.</param>
|
||||
public CbcCipherMode(byte[] iv)
|
||||
: base(iv)
|
||||
{
|
||||
get { return this._blockSize; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="CbcMode"/> class.
|
||||
/// </summary>
|
||||
/// <param name="cipher">The cipher.</param>
|
||||
public CbcMode(CipherBase cipher)
|
||||
: base(cipher)
|
||||
{
|
||||
this._blockSize = cipher.BlockSize;
|
||||
this._iv = cipher.IV.Take(this._blockSize).ToArray();
|
||||
this._nextIV = new byte[this._iv.Length];
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -53,25 +33,25 @@ namespace Renci.SshNet.Security.Cryptography
|
||||
/// </returns>
|
||||
public override int EncryptBlock(byte[] inputBuffer, int inputOffset, int inputCount, byte[] outputBuffer, int outputOffset)
|
||||
{
|
||||
if (inputBuffer.Length - inputOffset < this._blockSize)
|
||||
if (inputBuffer.Length - inputOffset < this.Cipher.BlockSize)
|
||||
throw new ArgumentException("Invalid input buffer");
|
||||
|
||||
if (outputBuffer.Length - outputOffset < this._blockSize)
|
||||
if (outputBuffer.Length - outputOffset < this.Cipher.BlockSize)
|
||||
throw new ArgumentException("Invalid output buffer");
|
||||
|
||||
if (inputCount != this._blockSize)
|
||||
throw new ArgumentException(string.Format(CultureInfo.CurrentCulture, "inputCount must be {0}.", this._blockSize));
|
||||
if (inputCount != this.Cipher.BlockSize)
|
||||
throw new ArgumentException(string.Format(CultureInfo.CurrentCulture, "inputCount must be {0}.", this.Cipher.BlockSize));
|
||||
|
||||
for (int i = 0; i < this._blockSize; i++)
|
||||
for (int i = 0; i < this.Cipher.BlockSize; i++)
|
||||
{
|
||||
this._iv[i] ^= inputBuffer[inputOffset + i];
|
||||
this.IV[i] ^= inputBuffer[inputOffset + i];
|
||||
}
|
||||
|
||||
this.Cipher.EncryptBlock(this._iv, 0, inputCount, outputBuffer, outputOffset);
|
||||
this.Cipher.EncryptBlock(this.IV, 0, inputCount, outputBuffer, outputOffset);
|
||||
|
||||
Array.Copy(outputBuffer, outputOffset, this._iv, 0, this._iv.Length);
|
||||
Array.Copy(outputBuffer, outputOffset, this.IV, 0, this.IV.Length);
|
||||
|
||||
return this._blockSize;
|
||||
return this.Cipher.BlockSize;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -87,28 +67,25 @@ namespace Renci.SshNet.Security.Cryptography
|
||||
/// </returns>
|
||||
public override int DecryptBlock(byte[] inputBuffer, int inputOffset, int inputCount, byte[] outputBuffer, int outputOffset)
|
||||
{
|
||||
if (inputBuffer.Length - inputOffset < this._blockSize)
|
||||
if (inputBuffer.Length - inputOffset < this.Cipher.BlockSize)
|
||||
throw new ArgumentException("Invalid input buffer");
|
||||
|
||||
if (outputBuffer.Length - outputOffset < this._blockSize)
|
||||
if (outputBuffer.Length - outputOffset < this.Cipher.BlockSize)
|
||||
throw new ArgumentException("Invalid output buffer");
|
||||
|
||||
if (inputCount != this._blockSize)
|
||||
throw new ArgumentException(string.Format(CultureInfo.CurrentCulture, "inputCount must be {0}.", this._blockSize));
|
||||
|
||||
Array.Copy(inputBuffer, inputOffset, this._nextIV, 0, this._nextIV.Length);
|
||||
if (inputCount != this.Cipher.BlockSize)
|
||||
throw new ArgumentException(string.Format(CultureInfo.CurrentCulture, "inputCount must be {0}.", this.Cipher.BlockSize));
|
||||
|
||||
this.Cipher.DecryptBlock(inputBuffer, inputOffset, inputCount, outputBuffer, outputOffset);
|
||||
|
||||
for (int i = 0; i < this._blockSize; i++)
|
||||
for (int i = 0; i < this.Cipher.BlockSize; i++)
|
||||
{
|
||||
outputBuffer[outputOffset + i] ^= this._iv[i];
|
||||
outputBuffer[outputOffset + i] ^= this.IV[i];
|
||||
}
|
||||
|
||||
Array.Copy(this._nextIV, 0, this._iv, 0, this._nextIV.Length);
|
||||
Array.Copy(inputBuffer, inputOffset, this.IV, 0, this.IV.Length);
|
||||
|
||||
return this._blockSize;
|
||||
return this.Cipher.BlockSize;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
+27
-44
@@ -4,40 +4,23 @@ using System.Linq;
|
||||
using System.Text;
|
||||
using System.Globalization;
|
||||
|
||||
namespace Renci.SshNet.Security.Cryptography
|
||||
namespace Renci.SshNet.Security.Cryptography.Ciphers.Modes
|
||||
{
|
||||
/// <summary>
|
||||
/// Represents the class for the OFB Block Cipher.
|
||||
/// Implements CFB cipher mode
|
||||
/// </summary>
|
||||
public class OfbMode : ModeBase
|
||||
public class CfbCipherMode : CipherMode
|
||||
{
|
||||
private readonly byte[] _iv;
|
||||
|
||||
private readonly byte[] _ivOutput;
|
||||
|
||||
private int _blockSize;
|
||||
|
||||
/// <summary>
|
||||
/// Gets the size of the block.
|
||||
/// Initializes a new instance of the <see cref="CfbCipherMode"/> class.
|
||||
/// </summary>
|
||||
/// <value>
|
||||
/// The size of the block.
|
||||
/// </value>
|
||||
public override int BlockSize
|
||||
/// <param name="iv">The iv.</param>
|
||||
public CfbCipherMode(byte[] iv)
|
||||
: base(iv)
|
||||
{
|
||||
get { return this._blockSize; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="OfbMode"/> class.
|
||||
/// </summary>
|
||||
/// <param name="cipher">The cipher.</param>
|
||||
public OfbMode(CipherBase cipher)
|
||||
: base(cipher)
|
||||
{
|
||||
this._blockSize = cipher.BlockSize;
|
||||
this._iv = cipher.IV.ToArray();
|
||||
this._ivOutput = new byte[this._iv.Length];
|
||||
this._ivOutput = new byte[iv.Length];
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -53,26 +36,26 @@ namespace Renci.SshNet.Security.Cryptography
|
||||
/// </returns>
|
||||
public override int EncryptBlock(byte[] inputBuffer, int inputOffset, int inputCount, byte[] outputBuffer, int outputOffset)
|
||||
{
|
||||
if (inputBuffer.Length - inputOffset < this._blockSize)
|
||||
if (inputBuffer.Length - inputOffset < this.Cipher.BlockSize)
|
||||
throw new ArgumentException("Invalid input buffer");
|
||||
|
||||
if (outputBuffer.Length - outputOffset < this._blockSize)
|
||||
if (outputBuffer.Length - outputOffset < this.Cipher.BlockSize)
|
||||
throw new ArgumentException("Invalid output buffer");
|
||||
|
||||
if (inputCount != this._blockSize)
|
||||
throw new ArgumentException(string.Format(CultureInfo.CurrentCulture, "inputCount must be {0}.", this._blockSize));
|
||||
if (inputCount != this.Cipher.BlockSize)
|
||||
throw new ArgumentException(string.Format(CultureInfo.CurrentCulture, "inputCount must be {0}.", this.Cipher.BlockSize));
|
||||
|
||||
this.Cipher.EncryptBlock(this._iv, 0, this._iv.Length, this._ivOutput, 0);
|
||||
this.Cipher.EncryptBlock(this.IV, 0, this.IV.Length, this._ivOutput, 0);
|
||||
|
||||
for (int i = 0; i < this._blockSize; i++)
|
||||
for (int i = 0; i < this.Cipher.BlockSize; i++)
|
||||
{
|
||||
outputBuffer[outputOffset + i] = (byte)(this._ivOutput[i] ^ inputBuffer[inputOffset + i]);
|
||||
}
|
||||
|
||||
Array.Copy(this._iv, this._blockSize, this._iv, 0, this._iv.Length - this._blockSize);
|
||||
Array.Copy(outputBuffer, outputOffset, this._iv, this._iv.Length - this._blockSize, this._blockSize);
|
||||
Array.Copy(this.IV, this.Cipher.BlockSize, this.IV, 0, this.IV.Length - this.Cipher.BlockSize);
|
||||
Array.Copy(outputBuffer, outputOffset, this.IV, this.IV.Length - this.Cipher.BlockSize, this.Cipher.BlockSize);
|
||||
|
||||
return this._blockSize;
|
||||
return this.Cipher.BlockSize;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -88,26 +71,26 @@ namespace Renci.SshNet.Security.Cryptography
|
||||
/// </returns>
|
||||
public override int DecryptBlock(byte[] inputBuffer, int inputOffset, int inputCount, byte[] outputBuffer, int outputOffset)
|
||||
{
|
||||
if (inputBuffer.Length - inputOffset < this._blockSize)
|
||||
if (inputBuffer.Length - inputOffset < this.Cipher.BlockSize)
|
||||
throw new ArgumentException("Invalid input buffer");
|
||||
|
||||
if (outputBuffer.Length - outputOffset < this._blockSize)
|
||||
if (outputBuffer.Length - outputOffset < this.Cipher.BlockSize)
|
||||
throw new ArgumentException("Invalid output buffer");
|
||||
|
||||
if (inputCount != this._blockSize)
|
||||
throw new ArgumentException(string.Format(CultureInfo.CurrentCulture, "inputCount must be {0}.", this._blockSize));
|
||||
if (inputCount != this.Cipher.BlockSize)
|
||||
throw new ArgumentException(string.Format(CultureInfo.CurrentCulture, "inputCount must be {0}.", this.Cipher.BlockSize));
|
||||
|
||||
this.Cipher.EncryptBlock(this._iv, 0, this._iv.Length, this._ivOutput, 0);
|
||||
this.Cipher.EncryptBlock(this.IV, 0, this.IV.Length, this._ivOutput, 0);
|
||||
|
||||
for (int i = 0; i < this._blockSize; i++)
|
||||
Array.Copy(this.IV, this.Cipher.BlockSize, this.IV, 0, this.IV.Length - this.Cipher.BlockSize);
|
||||
Array.Copy(inputBuffer, inputOffset, this.IV, this.IV.Length - this.Cipher.BlockSize, this.Cipher.BlockSize);
|
||||
|
||||
for (int i = 0; i < this.Cipher.BlockSize; i++)
|
||||
{
|
||||
outputBuffer[outputOffset + i] = (byte)(this._ivOutput[i] ^ inputBuffer[inputOffset + i]);
|
||||
}
|
||||
|
||||
Array.Copy(this._iv, this._blockSize, this._iv, 0, this._iv.Length - this._blockSize);
|
||||
Array.Copy(outputBuffer, outputOffset, this._iv, this._iv.Length - this._blockSize, this._blockSize);
|
||||
|
||||
return this._blockSize;
|
||||
return this.Cipher.BlockSize;
|
||||
}
|
||||
}
|
||||
}
|
||||
+27
-45
@@ -2,43 +2,25 @@
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Diagnostics;
|
||||
using System.Globalization;
|
||||
|
||||
namespace Renci.SshNet.Security.Cryptography
|
||||
namespace Renci.SshNet.Security.Cryptography.Ciphers.Modes
|
||||
{
|
||||
/// <summary>
|
||||
/// Represents the class for the CFB Block Cipher.
|
||||
/// Implements CTR cipher mode
|
||||
/// </summary>
|
||||
public class CfbMode : ModeBase
|
||||
public class CtrCipherMode : CipherMode
|
||||
{
|
||||
private readonly byte[] _iv;
|
||||
|
||||
private readonly byte[] _ivOutput;
|
||||
|
||||
private int _blockSize;
|
||||
|
||||
/// <summary>
|
||||
/// Gets the size of the block.
|
||||
/// Initializes a new instance of the <see cref="CtrCipherMode"/> class.
|
||||
/// </summary>
|
||||
/// <value>
|
||||
/// The size of the block.
|
||||
/// </value>
|
||||
public override int BlockSize
|
||||
/// <param name="iv">The iv.</param>
|
||||
public CtrCipherMode(byte[] iv)
|
||||
: base(iv)
|
||||
{
|
||||
get { return this._blockSize; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="CfbMode"/> class.
|
||||
/// </summary>
|
||||
/// <param name="cipher">The cipher.</param>
|
||||
public CfbMode(CipherBase cipher)
|
||||
: base(cipher)
|
||||
{
|
||||
this._blockSize = cipher.BlockSize;
|
||||
this._iv = cipher.IV.ToArray();
|
||||
this._ivOutput = new byte[this._iv.Length];
|
||||
this._ivOutput = new byte[iv.Length];
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -54,26 +36,26 @@ namespace Renci.SshNet.Security.Cryptography
|
||||
/// </returns>
|
||||
public override int EncryptBlock(byte[] inputBuffer, int inputOffset, int inputCount, byte[] outputBuffer, int outputOffset)
|
||||
{
|
||||
if (inputBuffer.Length - inputOffset < this._blockSize)
|
||||
if (inputBuffer.Length - inputOffset < this.Cipher.BlockSize)
|
||||
throw new ArgumentException("Invalid input buffer");
|
||||
|
||||
if (outputBuffer.Length - outputOffset < this._blockSize)
|
||||
if (outputBuffer.Length - outputOffset < this.Cipher.BlockSize)
|
||||
throw new ArgumentException("Invalid output buffer");
|
||||
|
||||
if (inputCount != this._blockSize)
|
||||
throw new ArgumentException(string.Format(CultureInfo.CurrentCulture, "inputCount must be {0}.", this._blockSize));
|
||||
if (inputCount != this.Cipher.BlockSize)
|
||||
throw new ArgumentException(string.Format(CultureInfo.CurrentCulture, "inputCount must be {0}.", this.Cipher.BlockSize));
|
||||
|
||||
this.Cipher.EncryptBlock(this._iv, 0, this._iv.Length, this._ivOutput, 0);
|
||||
this.Cipher.EncryptBlock(this.IV, 0, this.IV.Length, this._ivOutput, 0);
|
||||
|
||||
for (int i = 0; i < this._blockSize; i++)
|
||||
for (int i = 0; i < this.Cipher.BlockSize; i++)
|
||||
{
|
||||
outputBuffer[outputOffset + i] = (byte)(this._ivOutput[i] ^ inputBuffer[inputOffset + i]);
|
||||
}
|
||||
|
||||
Array.Copy(this._iv, this._blockSize, this._iv, 0, this._iv.Length - this._blockSize);
|
||||
Array.Copy(outputBuffer, outputOffset, this._iv, this._iv.Length - this._blockSize, this._blockSize);
|
||||
int j = this.IV.Length;
|
||||
while (--j >= 0 && ++this.IV[j] == 0) ;
|
||||
|
||||
return this._blockSize;
|
||||
return this.Cipher.BlockSize;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -89,26 +71,26 @@ namespace Renci.SshNet.Security.Cryptography
|
||||
/// </returns>
|
||||
public override int DecryptBlock(byte[] inputBuffer, int inputOffset, int inputCount, byte[] outputBuffer, int outputOffset)
|
||||
{
|
||||
if (inputBuffer.Length - inputOffset < this._blockSize)
|
||||
if (inputBuffer.Length - inputOffset < this.Cipher.BlockSize)
|
||||
throw new ArgumentException("Invalid input buffer");
|
||||
|
||||
if (outputBuffer.Length - outputOffset < this._blockSize)
|
||||
if (outputBuffer.Length - outputOffset < this.Cipher.BlockSize)
|
||||
throw new ArgumentException("Invalid output buffer");
|
||||
|
||||
if (inputCount != this._blockSize)
|
||||
throw new ArgumentException(string.Format(CultureInfo.CurrentCulture, "inputCount must be {0}.", this._blockSize));
|
||||
if (inputCount != this.Cipher.BlockSize)
|
||||
throw new ArgumentException(string.Format(CultureInfo.CurrentCulture, "inputCount must be {0}.", this.Cipher.BlockSize));
|
||||
|
||||
this.Cipher.EncryptBlock(this._iv, 0, this._iv.Length, this._ivOutput, 0);
|
||||
this.Cipher.EncryptBlock(this.IV, 0, this.IV.Length, this._ivOutput, 0);
|
||||
|
||||
Array.Copy(this._iv, this._blockSize, this._iv, 0, this._iv.Length - this._blockSize);
|
||||
Array.Copy(inputBuffer, inputOffset, this._iv, this._iv.Length - this._blockSize, this._blockSize);
|
||||
|
||||
for (int i = 0; i < this._blockSize; i++)
|
||||
for (int i = 0; i < this.Cipher.BlockSize; i++)
|
||||
{
|
||||
outputBuffer[outputOffset + i] = (byte)(this._ivOutput[i] ^ inputBuffer[inputOffset + i]);
|
||||
}
|
||||
|
||||
return this._blockSize;
|
||||
int j = this.IV.Length;
|
||||
while (--j >= 0 && ++this.IV[j] == 0) ;
|
||||
|
||||
return this.Cipher.BlockSize;
|
||||
}
|
||||
}
|
||||
}
|
||||
+29
-43
@@ -2,42 +2,26 @@
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using Renci.SshNet.Security.Cryptography.Ciphers;
|
||||
using System.Globalization;
|
||||
|
||||
namespace Renci.SshNet.Security.Cryptography
|
||||
namespace Renci.SshNet.Security.Cryptography.Ciphers.Modes
|
||||
{
|
||||
/// <summary>
|
||||
/// Represents the class for the CTR Block Cipher.
|
||||
/// Implements OFB cipher mode
|
||||
/// </summary>
|
||||
public class CtrMode : ModeBase
|
||||
public class OfbCipherMode : CipherMode
|
||||
{
|
||||
private readonly byte[] _iv;
|
||||
|
||||
private readonly byte[] _ivOutput;
|
||||
|
||||
private int _blockSize;
|
||||
|
||||
/// <summary>
|
||||
/// Gets the size of the block.
|
||||
/// Initializes a new instance of the <see cref="OfbCipherMode"/> class.
|
||||
/// </summary>
|
||||
/// <value>
|
||||
/// The size of the block.
|
||||
/// </value>
|
||||
public override int BlockSize
|
||||
/// <param name="iv">The iv.</param>
|
||||
public OfbCipherMode(byte[] iv)
|
||||
: base(iv)
|
||||
{
|
||||
get { return this._blockSize; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="CtrMode"/> class.
|
||||
/// </summary>
|
||||
/// <param name="cipher">The cipher.</param>
|
||||
public CtrMode(CipherBase cipher)
|
||||
: base(cipher)
|
||||
{
|
||||
this._blockSize = cipher.BlockSize;
|
||||
this._iv = cipher.IV.ToArray();
|
||||
this._ivOutput = new byte[this._iv.Length];
|
||||
this._ivOutput = new byte[iv.Length];
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -53,26 +37,26 @@ namespace Renci.SshNet.Security.Cryptography
|
||||
/// </returns>
|
||||
public override int EncryptBlock(byte[] inputBuffer, int inputOffset, int inputCount, byte[] outputBuffer, int outputOffset)
|
||||
{
|
||||
if (inputBuffer.Length - inputOffset < this._blockSize)
|
||||
if (inputBuffer.Length - inputOffset < this.Cipher.BlockSize)
|
||||
throw new ArgumentException("Invalid input buffer");
|
||||
|
||||
if (outputBuffer.Length - outputOffset < this._blockSize)
|
||||
if (outputBuffer.Length - outputOffset < this.Cipher.BlockSize)
|
||||
throw new ArgumentException("Invalid output buffer");
|
||||
|
||||
if (inputCount != this._blockSize)
|
||||
throw new ArgumentException(string.Format(CultureInfo.CurrentCulture, "inputCount must be {0}.", this._blockSize));
|
||||
if (inputCount != this.Cipher.BlockSize)
|
||||
throw new ArgumentException(string.Format(CultureInfo.CurrentCulture, "inputCount must be {0}.", this.Cipher.BlockSize));
|
||||
|
||||
this.Cipher.EncryptBlock(this._iv, 0, this._iv.Length, this._ivOutput, 0);
|
||||
this.Cipher.EncryptBlock(this.IV, 0, this.IV.Length, this._ivOutput, 0);
|
||||
|
||||
for (int i = 0; i < this._blockSize; i++)
|
||||
for (int i = 0; i < this.Cipher.BlockSize; i++)
|
||||
{
|
||||
outputBuffer[outputOffset + i] = (byte)(this._ivOutput[i] ^ inputBuffer[inputOffset + i]);
|
||||
}
|
||||
|
||||
int j = this._iv.Length;
|
||||
while (--j >= 0 && ++this._iv[j] == 0) ;
|
||||
Array.Copy(this.IV, this.Cipher.BlockSize, this.IV, 0, this.IV.Length - this.Cipher.BlockSize);
|
||||
Array.Copy(outputBuffer, outputOffset, this.IV, this.IV.Length - this.Cipher.BlockSize, this.Cipher.BlockSize);
|
||||
|
||||
return this._blockSize;
|
||||
return this.Cipher.BlockSize;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -88,26 +72,28 @@ namespace Renci.SshNet.Security.Cryptography
|
||||
/// </returns>
|
||||
public override int DecryptBlock(byte[] inputBuffer, int inputOffset, int inputCount, byte[] outputBuffer, int outputOffset)
|
||||
{
|
||||
if (inputBuffer.Length - inputOffset < this._blockSize)
|
||||
if (inputBuffer.Length - inputOffset < this.Cipher.BlockSize)
|
||||
throw new ArgumentException("Invalid input buffer");
|
||||
|
||||
if (outputBuffer.Length - outputOffset < this._blockSize)
|
||||
if (outputBuffer.Length - outputOffset < this.Cipher.BlockSize)
|
||||
throw new ArgumentException("Invalid output buffer");
|
||||
|
||||
if (inputCount != this._blockSize)
|
||||
throw new ArgumentException(string.Format(CultureInfo.CurrentCulture, "inputCount must be {0}.", this._blockSize));
|
||||
if (inputCount != this.Cipher.BlockSize)
|
||||
throw new ArgumentException(string.Format(CultureInfo.CurrentCulture, "inputCount must be {0}.", this.Cipher.BlockSize));
|
||||
|
||||
this.Cipher.EncryptBlock(this._iv, 0, this._iv.Length, this._ivOutput, 0);
|
||||
this.Cipher.EncryptBlock(this.IV, 0, this.IV.Length, this._ivOutput, 0);
|
||||
|
||||
for (int i = 0; i < this._blockSize; i++)
|
||||
for (int i = 0; i < this.Cipher.BlockSize; i++)
|
||||
{
|
||||
outputBuffer[outputOffset + i] = (byte)(this._ivOutput[i] ^ inputBuffer[inputOffset + i]);
|
||||
}
|
||||
|
||||
int j = this._iv.Length;
|
||||
while (--j >= 0 && ++this._iv[j] == 0) ;
|
||||
Array.Copy(this.IV, this.Cipher.BlockSize, this.IV, 0, this.IV.Length - this.Cipher.BlockSize);
|
||||
Array.Copy(outputBuffer, outputOffset, this.IV, this.IV.Length - this.Cipher.BlockSize, this.Cipher.BlockSize);
|
||||
|
||||
return this._blockSize;
|
||||
return this.Cipher.BlockSize;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,33 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
|
||||
namespace Renci.SshNet.Security.Cryptography.Ciphers.Paddings
|
||||
{
|
||||
/// <summary>
|
||||
/// Implements PKCS7 cipher padding
|
||||
/// </summary>
|
||||
public class PKCS7Padding : CipherPadding
|
||||
{
|
||||
/// <summary>
|
||||
/// Transforms the specified input.
|
||||
/// </summary>
|
||||
/// <param name="blockSize"></param>
|
||||
/// <param name="input">The input.</param>
|
||||
/// <returns></returns>
|
||||
public override byte[] Pad(int blockSize, byte[] input)
|
||||
{
|
||||
var numOfPaddedBytes = blockSize - (input.Length % blockSize);
|
||||
|
||||
var output = new byte[input.Length + numOfPaddedBytes];
|
||||
Array.Copy(input, output, input.Length);
|
||||
for (int i = 0; i < numOfPaddedBytes; i++)
|
||||
{
|
||||
output[input.Length + i] = output[input.Length - 1];
|
||||
}
|
||||
|
||||
return output;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,140 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Security.Cryptography;
|
||||
using Renci.SshNet.Common;
|
||||
|
||||
namespace Renci.SshNet.Security.Cryptography.Ciphers
|
||||
{
|
||||
/// <summary>
|
||||
/// Implements RSA cipher algorithm.
|
||||
/// </summary>
|
||||
public class RsaCipher : AsymmetricCipher
|
||||
{
|
||||
private static RNGCryptoServiceProvider _randomizer = new System.Security.Cryptography.RNGCryptoServiceProvider();
|
||||
|
||||
private bool _isPrivate;
|
||||
|
||||
private BigInteger _exponent;
|
||||
|
||||
private BigInteger _modulus;
|
||||
private BigInteger _d;
|
||||
private BigInteger _dp;
|
||||
private BigInteger _dq;
|
||||
private BigInteger _inverseQ;
|
||||
private BigInteger _p;
|
||||
private BigInteger _q;
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="RsaCipher"/> class.
|
||||
/// </summary>
|
||||
/// <param name="exponent">The exponent.</param>
|
||||
/// <param name="modulus">The modulus.</param>
|
||||
public RsaCipher(BigInteger exponent, BigInteger modulus)
|
||||
{
|
||||
//if (key == null)
|
||||
// throw new ArgumentNullException("key");
|
||||
//this._publicKey = key;
|
||||
this._exponent = exponent;
|
||||
this._modulus = modulus;
|
||||
this._isPrivate = false;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="RsaCipher"/> class.
|
||||
/// </summary>
|
||||
/// <param name="exponent">The exponent.</param>
|
||||
/// <param name="modulus">The modulus.</param>
|
||||
/// <param name="d">The d.</param>
|
||||
/// <param name="dp">The dp.</param>
|
||||
/// <param name="dq">The dq.</param>
|
||||
/// <param name="inverseQ">The inverse Q.</param>
|
||||
/// <param name="p">The p.</param>
|
||||
/// <param name="q">The q.</param>
|
||||
public RsaCipher(BigInteger exponent, BigInteger modulus, BigInteger d, BigInteger dp, BigInteger dq, BigInteger inverseQ, BigInteger p, BigInteger q)
|
||||
{
|
||||
//if (key == null)
|
||||
// throw new ArgumentNullException("key");
|
||||
//this._privateKey = key;
|
||||
this._exponent = exponent;
|
||||
this._modulus = modulus;
|
||||
this._d = d;
|
||||
this._dp = dp;
|
||||
this._dq = dq;
|
||||
this._inverseQ = inverseQ;
|
||||
this._p = p;
|
||||
this._q = q;
|
||||
this._isPrivate = true;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Encrypts the specified data.
|
||||
/// </summary>
|
||||
/// <param name="data">The data.</param>
|
||||
/// <returns></returns>
|
||||
public override byte[] Encrypt(byte[] data)
|
||||
{
|
||||
return this.Transform(data);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Decrypts the specified data.
|
||||
/// </summary>
|
||||
/// <param name="data">The data.</param>
|
||||
/// <returns></returns>
|
||||
public override byte[] Decrypt(byte[] data)
|
||||
{
|
||||
return this.Transform(data);
|
||||
}
|
||||
|
||||
private byte[] Transform(byte[] data)
|
||||
{
|
||||
var bytes = new List<byte>(data.Reverse());
|
||||
bytes.Add(0);
|
||||
|
||||
var input = new BigInteger(bytes.ToArray());
|
||||
|
||||
BigInteger result;
|
||||
|
||||
if (this._isPrivate)
|
||||
{
|
||||
BigInteger random = BigInteger.One;
|
||||
|
||||
var max = this._modulus - 1;
|
||||
|
||||
while (random <= BigInteger.One || random >= max)
|
||||
{
|
||||
var bytesArray = new byte[256];
|
||||
_randomizer.GetBytes(bytesArray);
|
||||
|
||||
bytesArray[bytesArray.Length - 1] = (byte)(bytesArray[bytesArray.Length - 1] & 0x7F); // Ensure not a negative value
|
||||
random = new BigInteger(bytesArray.Reverse().ToArray());
|
||||
}
|
||||
|
||||
BigInteger blindedInput = BigInteger.PositiveMod((BigInteger.ModPow(random, this._exponent, this._modulus) * input), this._modulus);
|
||||
|
||||
// mP = ((input Mod p) ^ dP)) Mod p
|
||||
var mP = BigInteger.ModPow((blindedInput % this._p), this._dp, this._p);
|
||||
|
||||
// mQ = ((input Mod q) ^ dQ)) Mod q
|
||||
var mQ = BigInteger.ModPow((blindedInput % this._q), this._dq, this._q);
|
||||
|
||||
var h = BigInteger.PositiveMod(((mP - mQ) * this._inverseQ), this._p);
|
||||
|
||||
var m = h * this._q + mQ;
|
||||
|
||||
BigInteger rInv = BigInteger.ModInverse(random, this._modulus);
|
||||
|
||||
result = BigInteger.PositiveMod((m * rInv), this._modulus);
|
||||
}
|
||||
else
|
||||
{
|
||||
result = BigInteger.ModPow(input, this._exponent, this._modulus);
|
||||
}
|
||||
|
||||
return result.ToByteArray().Reverse().ToArray();
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
File diff suppressed because it is too large
Load Diff
@@ -2,12 +2,11 @@
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Security.Cryptography;
|
||||
|
||||
namespace Renci.SshNet.Security.Cryptography
|
||||
namespace Renci.SshNet.Security.Cryptography.Ciphers
|
||||
{
|
||||
/// <summary>
|
||||
/// Represents the class for the 3DES algorithm.
|
||||
/// Implements 3DES cipher algorithm.
|
||||
/// </summary>
|
||||
public class TripleDesCipher : DesCipher
|
||||
{
|
||||
@@ -23,9 +22,10 @@ namespace Renci.SshNet.Security.Cryptography
|
||||
/// Initializes a new instance of the <see cref="TripleDesCipher"/> class.
|
||||
/// </summary>
|
||||
/// <param name="key">The key.</param>
|
||||
/// <param name="iv">The iv.</param>
|
||||
public TripleDesCipher(byte[] key, byte[] iv)
|
||||
: base(key, iv)
|
||||
/// <param name="mode">The mode.</param>
|
||||
/// <param name="padding">The padding.</param>
|
||||
public TripleDesCipher(byte[] key, CipherMode mode, CipherPadding padding)
|
||||
: base(key, mode, padding)
|
||||
{
|
||||
var part1 = new byte[8];
|
||||
var part2 = new byte[8];
|
||||
@@ -39,7 +39,7 @@ namespace Renci.SshNet.Security.Cryptography
|
||||
this._encryptionKey2 = GenerateWorkingKey(false, part2);
|
||||
this._decryptionKey2 = GenerateWorkingKey(true, part2);
|
||||
|
||||
if (this.Key.Length == 24)
|
||||
if (key.Length == 24)
|
||||
{
|
||||
var part3 = new byte[8];
|
||||
Array.Copy(key, 16, part3, 0, 8);
|
||||
@@ -52,6 +52,7 @@ namespace Renci.SshNet.Security.Cryptography
|
||||
this._encryptionKey3 = this._encryptionKey1;
|
||||
this._decryptionKey3 = this._decryptionKey1;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -109,5 +110,20 @@ namespace Renci.SshNet.Security.Cryptography
|
||||
|
||||
return this.BlockSize;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Validates the size of the key.
|
||||
/// </summary>
|
||||
/// <param name="keySize">Size of the key.</param>
|
||||
/// <returns>
|
||||
/// true if keySize is valid; otherwise false
|
||||
/// </returns>
|
||||
protected override bool ValidateKeySize(int keySize)
|
||||
{
|
||||
if (keySize == 128 || keySize == 128 + 64)
|
||||
return true;
|
||||
else
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -5,16 +5,33 @@ using System.Text;
|
||||
|
||||
namespace Renci.SshNet.Security.Cryptography.Ciphers
|
||||
{
|
||||
internal class TwofishCipher : CipherBase
|
||||
{
|
||||
/// <summary>
|
||||
/// Implements Twofish cipher algorithm
|
||||
/// </summary>
|
||||
public class TwofishCipher : BlockCipher
|
||||
{
|
||||
/// <summary>
|
||||
/// Gets the size of the block in bytes.
|
||||
/// </summary>
|
||||
/// <value>
|
||||
/// The size of the block in bytes.
|
||||
/// </value>
|
||||
public override int BlockSize
|
||||
{
|
||||
get { return 16; }
|
||||
}
|
||||
|
||||
public TwofishCipher(byte[] key, byte[] iv)
|
||||
: base(key, iv)
|
||||
{
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="TwofishCipher"/> class.
|
||||
/// </summary>
|
||||
/// <param name="key">The key.</param>
|
||||
/// <param name="mode">The mode.</param>
|
||||
/// <param name="padding">The padding.</param>
|
||||
public TwofishCipher(byte[] key, CipherMode mode, CipherPadding padding)
|
||||
: base(key, mode, padding)
|
||||
{
|
||||
// TODO: Refactor this algorithm
|
||||
|
||||
// calculate the MDS matrix
|
||||
int[] m1 = new int[2];
|
||||
int[] mX = new int[2];
|
||||
@@ -48,9 +65,19 @@ namespace Renci.SshNet.Security.Cryptography.Ciphers
|
||||
|
||||
this.k64Cnt = (key.Length / 8); // pre-padded ?
|
||||
this.SetKey(key);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Encrypts the specified region of the input byte array and copies the encrypted data to the specified region of the output byte array.
|
||||
/// </summary>
|
||||
/// <param name="inputBuffer">The input data to encrypt.</param>
|
||||
/// <param name="inputOffset">The offset into the input byte array from which to begin using data.</param>
|
||||
/// <param name="inputCount">The number of bytes in the input byte array to use as data.</param>
|
||||
/// <param name="outputBuffer">The output to which to write encrypted data.</param>
|
||||
/// <param name="outputOffset">The offset into the output byte array from which to begin writing data.</param>
|
||||
/// <returns>
|
||||
/// The number of bytes encrypted.
|
||||
/// </returns>
|
||||
public override int EncryptBlock(byte[] inputBuffer, int inputOffset, int inputCount, byte[] outputBuffer, int outputOffset)
|
||||
{
|
||||
int x0 = BytesTo32Bits(inputBuffer, inputOffset) ^ gSubKeys[INPUT_WHITEN];
|
||||
@@ -83,6 +110,17 @@ namespace Renci.SshNet.Security.Cryptography.Ciphers
|
||||
return this.BlockSize;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Decrypts the specified region of the input byte array and copies the decrypted data to the specified region of the output byte array.
|
||||
/// </summary>
|
||||
/// <param name="inputBuffer">The input data to decrypt.</param>
|
||||
/// <param name="inputOffset">The offset into the input byte array from which to begin using data.</param>
|
||||
/// <param name="inputCount">The number of bytes in the input byte array to use as data.</param>
|
||||
/// <param name="outputBuffer">The output to which to write decrypted data.</param>
|
||||
/// <param name="outputOffset">The offset into the output byte array from which to begin writing data.</param>
|
||||
/// <returns>
|
||||
/// The number of bytes decrypted.
|
||||
/// </returns>
|
||||
public override int DecryptBlock(byte[] inputBuffer, int inputOffset, int inputCount, byte[] outputBuffer, int outputOffset)
|
||||
{
|
||||
int x2 = BytesTo32Bits(inputBuffer, inputOffset) ^ gSubKeys[OUTPUT_WHITEN];
|
||||
@@ -115,6 +153,21 @@ namespace Renci.SshNet.Security.Cryptography.Ciphers
|
||||
return this.BlockSize;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Validates the size of the key.
|
||||
/// </summary>
|
||||
/// <param name="keySize">Size of the key.</param>
|
||||
/// <returns>
|
||||
/// true if keySize is valid; otherwise false
|
||||
/// </returns>
|
||||
protected override bool ValidateKeySize(int keySize)
|
||||
{
|
||||
if (keySize == 128 || keySize == 192 || keySize == 256)
|
||||
return true;
|
||||
else
|
||||
return false;
|
||||
}
|
||||
|
||||
#region Static Definition Tables
|
||||
|
||||
private static readonly byte[,] P = {
|
||||
@@ -580,6 +633,5 @@ namespace Renci.SshNet.Security.Cryptography.Ciphers
|
||||
b[offset + 2] = (byte)(inData >> 16);
|
||||
b[offset + 3] = (byte)(inData >> 24);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,145 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Security.Cryptography;
|
||||
using Renci.SshNet.Common;
|
||||
using System.Globalization;
|
||||
|
||||
namespace Renci.SshNet.Security.Cryptography
|
||||
{
|
||||
/// <summary>
|
||||
/// Implements DSA digital signature algorithm.
|
||||
/// </summary>
|
||||
public class DsaDigitalSignature : DigitalSignature
|
||||
{
|
||||
private BigInteger _p;
|
||||
private BigInteger _q;
|
||||
private BigInteger _g;
|
||||
private BigInteger _privateKey;
|
||||
private BigInteger _publicKey;
|
||||
private HashAlgorithm _hash;
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="DsaDigitalSignature"/> class.
|
||||
/// </summary>
|
||||
/// <param name="p">The p.</param>
|
||||
/// <param name="q">The q.</param>
|
||||
/// <param name="g">The g.</param>
|
||||
/// <param name="privateKey">The private key.</param>
|
||||
/// <param name="publicKey">The public key.</param>
|
||||
public DsaDigitalSignature(byte[] p, byte[] q, byte[] g, byte[] privateKey, byte[] publicKey)
|
||||
{
|
||||
this._p = new BigInteger(p.Reverse().ToArray());
|
||||
this._q = new BigInteger(q.Reverse().ToArray());
|
||||
this._g = new BigInteger(g.Reverse().ToArray());
|
||||
if (privateKey != null)
|
||||
this._privateKey = new BigInteger(privateKey.Reverse().ToArray());
|
||||
if (publicKey != null)
|
||||
this._publicKey = new BigInteger(publicKey.Reverse().ToArray());
|
||||
this._hash = new SHA1Hash();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Verifies the signature.
|
||||
/// </summary>
|
||||
/// <param name="input">The input.</param>
|
||||
/// <param name="signature">The signature.</param>
|
||||
/// <returns></returns>
|
||||
public override bool VerifySignature(byte[] input, byte[] signature)
|
||||
{
|
||||
var hashInput = this._hash.ComputeHash(input);
|
||||
|
||||
BigInteger hm = new BigInteger(hashInput.Reverse().Concat(new byte[] { 0 }).ToArray());
|
||||
|
||||
if (signature.Length != 40)
|
||||
throw new InvalidOperationException("Invalid signature.");
|
||||
|
||||
// Extract r and s numbers from the signature
|
||||
var rBytes = new byte[21];
|
||||
var sBytes = new byte[21];
|
||||
|
||||
for (int i = 0, j = 20; i < 20; i++, j--)
|
||||
{
|
||||
rBytes[i] = signature[j - 1];
|
||||
sBytes[i] = signature[j + 20 - 1];
|
||||
}
|
||||
|
||||
BigInteger r = new BigInteger(rBytes);
|
||||
BigInteger s = new BigInteger(sBytes);
|
||||
|
||||
// Reject the signature if 0 < r < q or 0 < s < q is not satisfied.
|
||||
if (r <= 0 || r >= this._q)
|
||||
return false;
|
||||
|
||||
if (s <= 0 || s >= this._q)
|
||||
return false;
|
||||
|
||||
// Calculate w = s−1 mod q
|
||||
BigInteger w = BigInteger.ModInverse(s, this._q);
|
||||
|
||||
// Calculate u1 = H(m)·w mod q
|
||||
BigInteger u1 = hm * w % this._q;
|
||||
|
||||
// Calculate u2 = r * w mod q
|
||||
BigInteger u2 = r * w % this._q;
|
||||
|
||||
u1 = BigInteger.ModPow(this._g, u1, this._p);
|
||||
u2 = BigInteger.ModPow(this._publicKey, u2, this._p);
|
||||
|
||||
// Calculate v = ((g pow u1 * y pow u2) mod p) mod q
|
||||
BigInteger v = ((u1 * u2) % this._p) % this._q;
|
||||
|
||||
// The signature is valid if v = r
|
||||
return v == r;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Creates the signature.
|
||||
/// </summary>
|
||||
/// <param name="input">The input.</param>
|
||||
/// <returns></returns>
|
||||
public override byte[] CreateSignature(byte[] input)
|
||||
{
|
||||
var hashInput = this._hash.ComputeHash(input);
|
||||
|
||||
BigInteger m = new BigInteger(hashInput.Reverse().Concat(new byte[] { 0 }).ToArray());
|
||||
|
||||
BigInteger s = BigInteger.Zero;
|
||||
BigInteger r = BigInteger.Zero;
|
||||
|
||||
do
|
||||
{
|
||||
BigInteger k;
|
||||
|
||||
do
|
||||
{
|
||||
// TODO: Take random function to base class
|
||||
// Generate a random per-message value k where 0 < k < q
|
||||
do
|
||||
{
|
||||
//k = new BigInteger(q.BitLength, random);
|
||||
k = BigInteger.Parse("980263959677973875983479554308083464979482795347", System.Globalization.NumberStyles.None, CultureInfo.InvariantCulture);
|
||||
}
|
||||
while (k <= 0 || k >= this._q);
|
||||
|
||||
// Calculate r = ((g pow k) mod p) mod q
|
||||
r = BigInteger.ModPow(this._g, k, this._p) % this._q;
|
||||
|
||||
// In the unlikely case that r = 0, start again with a different random k
|
||||
} while (r.IsZero);
|
||||
|
||||
|
||||
// Calculate s = ((k pow −1)(H(m) + x*r)) mod q
|
||||
k = (BigInteger.ModInverse(k, this._q) * (m + this._privateKey * r));
|
||||
|
||||
s = k % this._q;
|
||||
|
||||
// In the unlikely case that s = 0, start again with a different random k
|
||||
} while (s.IsZero);
|
||||
|
||||
// The signature is (r, s)
|
||||
return r.ToByteArray().Reverse().TrimLeadingZero().Concat(s.ToByteArray().Reverse().TrimLeadingZero()).ToArray();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -10,7 +10,7 @@ namespace Renci.SshNet.Security.Cryptography
|
||||
/// Provides HMAC algorithm implementation.
|
||||
/// </summary>
|
||||
/// <typeparam name="T"></typeparam>
|
||||
public class HMAC<T> : KeyedHashAlgorithm where T : HashAlgorithm, new()
|
||||
public class HMac<T> : KeyedHashAlgorithm where T : HashAlgorithm, new()
|
||||
{
|
||||
private HashAlgorithm _hash;
|
||||
private bool _isHashing;
|
||||
@@ -35,7 +35,7 @@ namespace Renci.SshNet.Security.Cryptography
|
||||
/// Rfc 2104.
|
||||
/// </summary>
|
||||
/// <param name="key">The key.</param>
|
||||
public HMAC(byte[] key)
|
||||
public HMac(byte[] key)
|
||||
{
|
||||
// Create the hash algorithms.
|
||||
this._hash = new T();
|
||||
|
||||
@@ -0,0 +1,383 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Security.Cryptography;
|
||||
|
||||
namespace Renci.SshNet.Security.Cryptography
|
||||
{
|
||||
/// <summary>
|
||||
/// MD5 algorithm implementation
|
||||
/// </summary>
|
||||
public class MD5Hash : HashAlgorithm
|
||||
{
|
||||
private byte[] _buffer = new byte[4];
|
||||
private int _bufferOffset;
|
||||
private long _byteCount;
|
||||
private int H1, H2, H3, H4; // IV's
|
||||
private int[] _hashValue = new int[16];
|
||||
private int _offset;
|
||||
|
||||
/// <summary>
|
||||
/// Gets the size, in bits, of the computed hash code.
|
||||
/// </summary>
|
||||
/// <returns>The size, in bits, of the computed hash code.</returns>
|
||||
public override int HashSize
|
||||
{
|
||||
get
|
||||
{
|
||||
return 128;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the input block size.
|
||||
/// </summary>
|
||||
/// <returns>The input block size.</returns>
|
||||
public override int InputBlockSize
|
||||
{
|
||||
get
|
||||
{
|
||||
return 64;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the output block size.
|
||||
/// </summary>
|
||||
/// <returns>The output block size.</returns>
|
||||
public override int OutputBlockSize
|
||||
{
|
||||
get
|
||||
{
|
||||
return 64;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets a value indicating whether the current transform can be reused.
|
||||
/// </summary>
|
||||
/// <returns>Always true.</returns>
|
||||
public override bool CanReuseTransform
|
||||
{
|
||||
get
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets a value indicating whether multiple blocks can be transformed.
|
||||
/// </summary>
|
||||
/// <returns>true if multiple blocks can be transformed; otherwise, false.</returns>
|
||||
public override bool CanTransformMultipleBlocks
|
||||
{
|
||||
get
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="MD5Hash"/> class.
|
||||
/// </summary>
|
||||
public MD5Hash()
|
||||
{
|
||||
this.Initialize();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Routes data written to the object into the hash algorithm for computing the hash.
|
||||
/// </summary>
|
||||
/// <param name="array">The input to compute the hash code for.</param>
|
||||
/// <param name="ibStart">The offset into the byte array from which to begin using data.</param>
|
||||
/// <param name="cbSize">The number of bytes in the byte array to use as data.</param>
|
||||
protected override void HashCore(byte[] array, int ibStart, int cbSize)
|
||||
{
|
||||
// Fill the current word
|
||||
while ((this._bufferOffset != 0) && (cbSize > 0))
|
||||
{
|
||||
this.Update(array[ibStart]);
|
||||
ibStart++;
|
||||
cbSize--;
|
||||
}
|
||||
|
||||
// Process whole words.
|
||||
while (cbSize > this._buffer.Length)
|
||||
{
|
||||
this.ProcessWord(array, ibStart);
|
||||
|
||||
ibStart += this._buffer.Length;
|
||||
cbSize -= this._buffer.Length;
|
||||
this._byteCount += this._buffer.Length;
|
||||
}
|
||||
|
||||
// Load in the remainder.
|
||||
while (cbSize > 0)
|
||||
{
|
||||
this.Update(array[ibStart]);
|
||||
|
||||
ibStart++;
|
||||
cbSize--;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Finalizes the hash computation after the last data is processed by the cryptographic stream object.
|
||||
/// </summary>
|
||||
/// <returns>
|
||||
/// The computed hash code.
|
||||
/// </returns>
|
||||
protected override byte[] HashFinal()
|
||||
{
|
||||
long bitLength = (this._byteCount << 3);
|
||||
|
||||
// Add the pad bytes.
|
||||
this.Update((byte)128);
|
||||
|
||||
while (this._bufferOffset != 0)
|
||||
this.Update((byte)0);
|
||||
|
||||
if (this._offset > 14)
|
||||
{
|
||||
this.ProcessBlock();
|
||||
}
|
||||
|
||||
this._hashValue[14] = (int)(bitLength & 0xffffffff);
|
||||
this._hashValue[15] = (int)((ulong)bitLength >> 32);
|
||||
|
||||
this.ProcessBlock();
|
||||
|
||||
var output = new byte[16];
|
||||
|
||||
this.UnpackWord(H1, output, 0);
|
||||
this.UnpackWord(H2, output, 0 + 4);
|
||||
this.UnpackWord(H3, output, 0 + 8);
|
||||
this.UnpackWord(H4, output, 0 + 12);
|
||||
|
||||
this.Initialize();
|
||||
|
||||
return output;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Initializes an implementation of the <see cref="T:System.Security.Cryptography.HashAlgorithm"/> class.
|
||||
/// </summary>
|
||||
public override void Initialize()
|
||||
{
|
||||
this._byteCount = 0;
|
||||
this._bufferOffset = 0;
|
||||
Array.Clear(this._buffer, 0, this._buffer.Length);
|
||||
|
||||
H1 = unchecked((int)0x67452301);
|
||||
H2 = unchecked((int)0xefcdab89);
|
||||
H3 = unchecked((int)0x98badcfe);
|
||||
H4 = unchecked((int)0x10325476);
|
||||
|
||||
this._offset = 0;
|
||||
|
||||
for (int i = 0; i != this._hashValue.Length; i++)
|
||||
{
|
||||
this._hashValue[i] = 0;
|
||||
}
|
||||
}
|
||||
|
||||
private void Update(byte input)
|
||||
{
|
||||
this._buffer[this._bufferOffset++] = input;
|
||||
|
||||
if (this._bufferOffset == this._buffer.Length)
|
||||
{
|
||||
this.ProcessWord(this._buffer, 0);
|
||||
this._bufferOffset = 0;
|
||||
}
|
||||
|
||||
this._byteCount++;
|
||||
}
|
||||
|
||||
private void ProcessWord(byte[] input, int inOff)
|
||||
{
|
||||
this._hashValue[this._offset++] = (input[inOff] & 0xff) | ((input[inOff + 1] & 0xff) << 8)
|
||||
| ((input[inOff + 2] & 0xff) << 16) | ((input[inOff + 3] & 0xff) << 24);
|
||||
|
||||
if (this._offset == 16)
|
||||
{
|
||||
ProcessBlock();
|
||||
}
|
||||
}
|
||||
|
||||
private void UnpackWord(int word, byte[] outBytes, int outOff)
|
||||
{
|
||||
outBytes[outOff] = (byte)word;
|
||||
outBytes[outOff + 1] = (byte)((uint)word >> 8);
|
||||
outBytes[outOff + 2] = (byte)((uint)word >> 16);
|
||||
outBytes[outOff + 3] = (byte)((uint)word >> 24);
|
||||
}
|
||||
|
||||
//
|
||||
// round 1 left rotates
|
||||
//
|
||||
private static readonly int S11 = 7;
|
||||
private static readonly int S12 = 12;
|
||||
private static readonly int S13 = 17;
|
||||
private static readonly int S14 = 22;
|
||||
|
||||
//
|
||||
// round 2 left rotates
|
||||
//
|
||||
private static readonly int S21 = 5;
|
||||
private static readonly int S22 = 9;
|
||||
private static readonly int S23 = 14;
|
||||
private static readonly int S24 = 20;
|
||||
|
||||
//
|
||||
// round 3 left rotates
|
||||
//
|
||||
private static readonly int S31 = 4;
|
||||
private static readonly int S32 = 11;
|
||||
private static readonly int S33 = 16;
|
||||
private static readonly int S34 = 23;
|
||||
|
||||
//
|
||||
// round 4 left rotates
|
||||
//
|
||||
private static readonly int S41 = 6;
|
||||
private static readonly int S42 = 10;
|
||||
private static readonly int S43 = 15;
|
||||
private static readonly int S44 = 21;
|
||||
|
||||
/*
|
||||
* rotate int x left n bits.
|
||||
*/
|
||||
private int RotateLeft(int x, int n)
|
||||
{
|
||||
return (x << n) | (int)((uint)x >> (32 - n));
|
||||
}
|
||||
|
||||
/*
|
||||
* F, G, H and I are the basic MD5 functions.
|
||||
*/
|
||||
private int F(int u, int v, int w)
|
||||
{
|
||||
return (u & v) | (~u & w);
|
||||
}
|
||||
|
||||
private int G(int u, int v, int w)
|
||||
{
|
||||
return (u & w) | (v & ~w);
|
||||
}
|
||||
|
||||
private int H(int u, int v, int w)
|
||||
{
|
||||
return u ^ v ^ w;
|
||||
}
|
||||
|
||||
private int K(int u, int v, int w)
|
||||
{
|
||||
return v ^ (u | ~w);
|
||||
}
|
||||
|
||||
private void ProcessBlock()
|
||||
{
|
||||
int a = H1;
|
||||
int b = H2;
|
||||
int c = H3;
|
||||
int d = H4;
|
||||
|
||||
//
|
||||
// Round 1 - F cycle, 16 times.
|
||||
//
|
||||
a = RotateLeft((a + F(b, c, d) + this._hashValue[0] + unchecked((int)0xd76aa478)), S11) + b;
|
||||
d = RotateLeft((d + F(a, b, c) + this._hashValue[1] + unchecked((int)0xe8c7b756)), S12) + a;
|
||||
c = RotateLeft((c + F(d, a, b) + this._hashValue[2] + unchecked((int)0x242070db)), S13) + d;
|
||||
b = RotateLeft((b + F(c, d, a) + this._hashValue[3] + unchecked((int)0xc1bdceee)), S14) + c;
|
||||
a = RotateLeft((a + F(b, c, d) + this._hashValue[4] + unchecked((int)0xf57c0faf)), S11) + b;
|
||||
d = RotateLeft((d + F(a, b, c) + this._hashValue[5] + unchecked((int)0x4787c62a)), S12) + a;
|
||||
c = RotateLeft((c + F(d, a, b) + this._hashValue[6] + unchecked((int)0xa8304613)), S13) + d;
|
||||
b = RotateLeft((b + F(c, d, a) + this._hashValue[7] + unchecked((int)0xfd469501)), S14) + c;
|
||||
a = RotateLeft((a + F(b, c, d) + this._hashValue[8] + unchecked((int)0x698098d8)), S11) + b;
|
||||
d = RotateLeft((d + F(a, b, c) + this._hashValue[9] + unchecked((int)0x8b44f7af)), S12) + a;
|
||||
c = RotateLeft((c + F(d, a, b) + this._hashValue[10] + unchecked((int)0xffff5bb1)), S13) + d;
|
||||
b = RotateLeft((b + F(c, d, a) + this._hashValue[11] + unchecked((int)0x895cd7be)), S14) + c;
|
||||
a = RotateLeft((a + F(b, c, d) + this._hashValue[12] + unchecked((int)0x6b901122)), S11) + b;
|
||||
d = RotateLeft((d + F(a, b, c) + this._hashValue[13] + unchecked((int)0xfd987193)), S12) + a;
|
||||
c = RotateLeft((c + F(d, a, b) + this._hashValue[14] + unchecked((int)0xa679438e)), S13) + d;
|
||||
b = RotateLeft((b + F(c, d, a) + this._hashValue[15] + unchecked((int)0x49b40821)), S14) + c;
|
||||
|
||||
//
|
||||
// Round 2 - G cycle, 16 times.
|
||||
//
|
||||
a = RotateLeft((a + G(b, c, d) + this._hashValue[1] + unchecked((int)0xf61e2562)), S21) + b;
|
||||
d = RotateLeft((d + G(a, b, c) + this._hashValue[6] + unchecked((int)0xc040b340)), S22) + a;
|
||||
c = RotateLeft((c + G(d, a, b) + this._hashValue[11] + unchecked((int)0x265e5a51)), S23) + d;
|
||||
b = RotateLeft((b + G(c, d, a) + this._hashValue[0] + unchecked((int)0xe9b6c7aa)), S24) + c;
|
||||
a = RotateLeft((a + G(b, c, d) + this._hashValue[5] + unchecked((int)0xd62f105d)), S21) + b;
|
||||
d = RotateLeft((d + G(a, b, c) + this._hashValue[10] + unchecked((int)0x02441453)), S22) + a;
|
||||
c = RotateLeft((c + G(d, a, b) + this._hashValue[15] + unchecked((int)0xd8a1e681)), S23) + d;
|
||||
b = RotateLeft((b + G(c, d, a) + this._hashValue[4] + unchecked((int)0xe7d3fbc8)), S24) + c;
|
||||
a = RotateLeft((a + G(b, c, d) + this._hashValue[9] + unchecked((int)0x21e1cde6)), S21) + b;
|
||||
d = RotateLeft((d + G(a, b, c) + this._hashValue[14] + unchecked((int)0xc33707d6)), S22) + a;
|
||||
c = RotateLeft((c + G(d, a, b) + this._hashValue[3] + unchecked((int)0xf4d50d87)), S23) + d;
|
||||
b = RotateLeft((b + G(c, d, a) + this._hashValue[8] + unchecked((int)0x455a14ed)), S24) + c;
|
||||
a = RotateLeft((a + G(b, c, d) + this._hashValue[13] + unchecked((int)0xa9e3e905)), S21) + b;
|
||||
d = RotateLeft((d + G(a, b, c) + this._hashValue[2] + unchecked((int)0xfcefa3f8)), S22) + a;
|
||||
c = RotateLeft((c + G(d, a, b) + this._hashValue[7] + unchecked((int)0x676f02d9)), S23) + d;
|
||||
b = RotateLeft((b + G(c, d, a) + this._hashValue[12] + unchecked((int)0x8d2a4c8a)), S24) + c;
|
||||
|
||||
//
|
||||
// Round 3 - H cycle, 16 times.
|
||||
//
|
||||
a = RotateLeft((a + H(b, c, d) + this._hashValue[5] + unchecked((int)0xfffa3942)), S31) + b;
|
||||
d = RotateLeft((d + H(a, b, c) + this._hashValue[8] + unchecked((int)0x8771f681)), S32) + a;
|
||||
c = RotateLeft((c + H(d, a, b) + this._hashValue[11] + unchecked((int)0x6d9d6122)), S33) + d;
|
||||
b = RotateLeft((b + H(c, d, a) + this._hashValue[14] + unchecked((int)0xfde5380c)), S34) + c;
|
||||
a = RotateLeft((a + H(b, c, d) + this._hashValue[1] + unchecked((int)0xa4beea44)), S31) + b;
|
||||
d = RotateLeft((d + H(a, b, c) + this._hashValue[4] + unchecked((int)0x4bdecfa9)), S32) + a;
|
||||
c = RotateLeft((c + H(d, a, b) + this._hashValue[7] + unchecked((int)0xf6bb4b60)), S33) + d;
|
||||
b = RotateLeft((b + H(c, d, a) + this._hashValue[10] + unchecked((int)0xbebfbc70)), S34) + c;
|
||||
a = RotateLeft((a + H(b, c, d) + this._hashValue[13] + unchecked((int)0x289b7ec6)), S31) + b;
|
||||
d = RotateLeft((d + H(a, b, c) + this._hashValue[0] + unchecked((int)0xeaa127fa)), S32) + a;
|
||||
c = RotateLeft((c + H(d, a, b) + this._hashValue[3] + unchecked((int)0xd4ef3085)), S33) + d;
|
||||
b = RotateLeft((b + H(c, d, a) + this._hashValue[6] + unchecked((int)0x04881d05)), S34) + c;
|
||||
a = RotateLeft((a + H(b, c, d) + this._hashValue[9] + unchecked((int)0xd9d4d039)), S31) + b;
|
||||
d = RotateLeft((d + H(a, b, c) + this._hashValue[12] + unchecked((int)0xe6db99e5)), S32) + a;
|
||||
c = RotateLeft((c + H(d, a, b) + this._hashValue[15] + unchecked((int)0x1fa27cf8)), S33) + d;
|
||||
b = RotateLeft((b + H(c, d, a) + this._hashValue[2] + unchecked((int)0xc4ac5665)), S34) + c;
|
||||
|
||||
//
|
||||
// Round 4 - K cycle, 16 times.
|
||||
//
|
||||
a = RotateLeft((a + K(b, c, d) + this._hashValue[0] + unchecked((int)0xf4292244)), S41) + b;
|
||||
d = RotateLeft((d + K(a, b, c) + this._hashValue[7] + unchecked((int)0x432aff97)), S42) + a;
|
||||
c = RotateLeft((c + K(d, a, b) + this._hashValue[14] + unchecked((int)0xab9423a7)), S43) + d;
|
||||
b = RotateLeft((b + K(c, d, a) + this._hashValue[5] + unchecked((int)0xfc93a039)), S44) + c;
|
||||
a = RotateLeft((a + K(b, c, d) + this._hashValue[12] + unchecked((int)0x655b59c3)), S41) + b;
|
||||
d = RotateLeft((d + K(a, b, c) + this._hashValue[3] + unchecked((int)0x8f0ccc92)), S42) + a;
|
||||
c = RotateLeft((c + K(d, a, b) + this._hashValue[10] + unchecked((int)0xffeff47d)), S43) + d;
|
||||
b = RotateLeft((b + K(c, d, a) + this._hashValue[1] + unchecked((int)0x85845dd1)), S44) + c;
|
||||
a = RotateLeft((a + K(b, c, d) + this._hashValue[8] + unchecked((int)0x6fa87e4f)), S41) + b;
|
||||
d = RotateLeft((d + K(a, b, c) + this._hashValue[15] + unchecked((int)0xfe2ce6e0)), S42) + a;
|
||||
c = RotateLeft((c + K(d, a, b) + this._hashValue[6] + unchecked((int)0xa3014314)), S43) + d;
|
||||
b = RotateLeft((b + K(c, d, a) + this._hashValue[13] + unchecked((int)0x4e0811a1)), S44) + c;
|
||||
a = RotateLeft((a + K(b, c, d) + this._hashValue[4] + unchecked((int)0xf7537e82)), S41) + b;
|
||||
d = RotateLeft((d + K(a, b, c) + this._hashValue[11] + unchecked((int)0xbd3af235)), S42) + a;
|
||||
c = RotateLeft((c + K(d, a, b) + this._hashValue[2] + unchecked((int)0x2ad7d2bb)), S43) + d;
|
||||
b = RotateLeft((b + K(c, d, a) + this._hashValue[9] + unchecked((int)0xeb86d391)), S44) + c;
|
||||
|
||||
H1 += a;
|
||||
H2 += b;
|
||||
H3 += c;
|
||||
H4 += d;
|
||||
|
||||
//
|
||||
// reset the offset and clean out the word buffer.
|
||||
//
|
||||
this._offset = 0;
|
||||
for (int i = 0; i != this._hashValue.Length; i++)
|
||||
{
|
||||
this._hashValue[i] = 0;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,382 @@
|
||||
using System.Security.Cryptography;
|
||||
using System;
|
||||
|
||||
namespace Renci.SshNet.Security.Cryptography
|
||||
{
|
||||
/// <summary>
|
||||
/// SHA1 algorithm implementation
|
||||
/// </summary>
|
||||
public class SHA1Hash : HashAlgorithm
|
||||
{
|
||||
private const int DIGEST_SIZE = 20;
|
||||
|
||||
private const uint Y1 = 0x5a827999;
|
||||
|
||||
private const uint Y2 = 0x6ed9eba1;
|
||||
|
||||
private const uint Y3 = 0x8f1bbcdc;
|
||||
|
||||
private const uint Y4 = 0xca62c1d6;
|
||||
|
||||
private uint H1, H2, H3, H4, H5;
|
||||
|
||||
private uint[] _hashValue = new uint[80];
|
||||
|
||||
private int _offset;
|
||||
|
||||
private byte[] _buffer;
|
||||
|
||||
private int _bufferOffset;
|
||||
|
||||
private long _byteCount;
|
||||
|
||||
/// <summary>
|
||||
/// Gets the size, in bits, of the computed hash code.
|
||||
/// </summary>
|
||||
/// <returns>The size, in bits, of the computed hash code.</returns>
|
||||
public override int HashSize
|
||||
{
|
||||
get
|
||||
{
|
||||
return DIGEST_SIZE * 8;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the input block size.
|
||||
/// </summary>
|
||||
/// <returns>The input block size.</returns>
|
||||
public override int InputBlockSize
|
||||
{
|
||||
get
|
||||
{
|
||||
return 64;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the output block size.
|
||||
/// </summary>
|
||||
/// <returns>The output block size.</returns>
|
||||
public override int OutputBlockSize
|
||||
{
|
||||
get
|
||||
{
|
||||
return 64;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets a value indicating whether the current transform can be reused.
|
||||
/// </summary>
|
||||
/// <returns>Always true.</returns>
|
||||
public override bool CanReuseTransform
|
||||
{
|
||||
get
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets a value indicating whether multiple blocks can be transformed.
|
||||
/// </summary>
|
||||
/// <returns>true if multiple blocks can be transformed; otherwise, false.</returns>
|
||||
public override bool CanTransformMultipleBlocks
|
||||
{
|
||||
get
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="SHA1Hash"/> class.
|
||||
/// </summary>
|
||||
public SHA1Hash()
|
||||
{
|
||||
this._buffer = new byte[4];
|
||||
this.Initialize();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Routes data written to the object into the hash algorithm for computing the hash.
|
||||
/// </summary>
|
||||
/// <param name="array">The input to compute the hash code for.</param>
|
||||
/// <param name="ibStart">The offset into the byte array from which to begin using data.</param>
|
||||
/// <param name="cbSize">The number of bytes in the byte array to use as data.</param>
|
||||
protected override void HashCore(byte[] array, int ibStart, int cbSize)
|
||||
{
|
||||
// Fill the current word
|
||||
while ((this._bufferOffset != 0) && (cbSize > 0))
|
||||
{
|
||||
this.Update(array[ibStart]);
|
||||
ibStart++;
|
||||
cbSize--;
|
||||
}
|
||||
|
||||
// Process whole words.
|
||||
while (cbSize > this._buffer.Length)
|
||||
{
|
||||
this.ProcessWord(array, ibStart);
|
||||
|
||||
ibStart += this._buffer.Length;
|
||||
cbSize -= this._buffer.Length;
|
||||
this._byteCount += this._buffer.Length;
|
||||
}
|
||||
|
||||
// Load in the remainder.
|
||||
while (cbSize > 0)
|
||||
{
|
||||
this.Update(array[ibStart]);
|
||||
|
||||
ibStart++;
|
||||
cbSize--;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Finalizes the hash computation after the last data is processed by the cryptographic stream object.
|
||||
/// </summary>
|
||||
/// <returns>
|
||||
/// The computed hash code.
|
||||
/// </returns>
|
||||
protected override byte[] HashFinal()
|
||||
{
|
||||
var output = new byte[DIGEST_SIZE];
|
||||
long bitLength = (this._byteCount << 3);
|
||||
|
||||
//
|
||||
// add the pad bytes.
|
||||
//
|
||||
this.Update((byte)128);
|
||||
|
||||
while (this._bufferOffset != 0)
|
||||
this.Update((byte)0);
|
||||
|
||||
if (this._offset > 14)
|
||||
{
|
||||
this.ProcessBlock();
|
||||
}
|
||||
|
||||
_hashValue[14] = (uint)((ulong)bitLength >> 32);
|
||||
_hashValue[15] = (uint)((ulong)bitLength);
|
||||
|
||||
|
||||
this.ProcessBlock();
|
||||
|
||||
UInt32_To__BE(H1, output, 0);
|
||||
UInt32_To__BE(H2, output, 0 + 4);
|
||||
UInt32_To__BE(H3, output, 0 + 8);
|
||||
UInt32_To__BE(H4, output, 0 + 12);
|
||||
UInt32_To__BE(H5, output, 0 + 16);
|
||||
|
||||
this.Initialize();
|
||||
|
||||
return output;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Initializes an implementation of the <see cref="T:System.Security.Cryptography.HashAlgorithm"/> class.
|
||||
/// </summary>
|
||||
public override void Initialize()
|
||||
{
|
||||
this._byteCount = 0;
|
||||
this._bufferOffset = 0;
|
||||
Array.Clear(this._buffer, 0, this._buffer.Length);
|
||||
|
||||
H1 = 0x67452301;
|
||||
H2 = 0xefcdab89;
|
||||
H3 = 0x98badcfe;
|
||||
H4 = 0x10325476;
|
||||
H5 = 0xc3d2e1f0;
|
||||
|
||||
this._offset = 0;
|
||||
Array.Clear(_hashValue, 0, _hashValue.Length);
|
||||
|
||||
}
|
||||
|
||||
private void Update(byte input)
|
||||
{
|
||||
this._buffer[this._bufferOffset++] = input;
|
||||
|
||||
if (this._bufferOffset == this._buffer.Length)
|
||||
{
|
||||
this.ProcessWord(this._buffer, 0);
|
||||
this._bufferOffset = 0;
|
||||
}
|
||||
|
||||
this._byteCount++;
|
||||
}
|
||||
|
||||
private void ProcessWord(byte[] input, int inOff)
|
||||
{
|
||||
_hashValue[this._offset] = BE_To__UInt32(input, inOff);
|
||||
|
||||
if (++this._offset == 16)
|
||||
{
|
||||
this.ProcessBlock();
|
||||
}
|
||||
}
|
||||
|
||||
private static uint F(uint u, uint v, uint w)
|
||||
{
|
||||
return (u & v) | (~u & w);
|
||||
}
|
||||
|
||||
private static uint H(uint u, uint v, uint w)
|
||||
{
|
||||
return u ^ v ^ w;
|
||||
}
|
||||
|
||||
private static uint G(uint u, uint v, uint w)
|
||||
{
|
||||
return (u & v) | (u & w) | (v & w);
|
||||
}
|
||||
|
||||
private void ProcessBlock()
|
||||
{
|
||||
//
|
||||
// expand 16 word block into 80 word block.
|
||||
//
|
||||
for (int i = 16; i < 80; i++)
|
||||
{
|
||||
uint t = _hashValue[i - 3] ^ _hashValue[i - 8] ^ _hashValue[i - 14] ^ _hashValue[i - 16];
|
||||
_hashValue[i] = t << 1 | t >> 31;
|
||||
}
|
||||
|
||||
//
|
||||
// set up working variables.
|
||||
//
|
||||
uint A = H1;
|
||||
uint B = H2;
|
||||
uint C = H3;
|
||||
uint D = H4;
|
||||
uint E = H5;
|
||||
|
||||
//
|
||||
// round 1
|
||||
//
|
||||
int idx = 0;
|
||||
|
||||
for (int j = 0; j < 4; j++)
|
||||
{
|
||||
// E = rotateLeft(A, 5) + F(B, C, D) + E + X[idx++] + Y1
|
||||
// B = rotateLeft(B, 30)
|
||||
E += (A << 5 | (A >> 27)) + F(B, C, D) + _hashValue[idx++] + Y1;
|
||||
B = B << 30 | (B >> 2);
|
||||
|
||||
D += (E << 5 | (E >> 27)) + F(A, B, C) + _hashValue[idx++] + Y1;
|
||||
A = A << 30 | (A >> 2);
|
||||
|
||||
C += (D << 5 | (D >> 27)) + F(E, A, B) + _hashValue[idx++] + Y1;
|
||||
E = E << 30 | (E >> 2);
|
||||
|
||||
B += (C << 5 | (C >> 27)) + F(D, E, A) + _hashValue[idx++] + Y1;
|
||||
D = D << 30 | (D >> 2);
|
||||
|
||||
A += (B << 5 | (B >> 27)) + F(C, D, E) + _hashValue[idx++] + Y1;
|
||||
C = C << 30 | (C >> 2);
|
||||
}
|
||||
|
||||
//
|
||||
// round 2
|
||||
//
|
||||
for (int j = 0; j < 4; j++)
|
||||
{
|
||||
// E = rotateLeft(A, 5) + H(B, C, D) + E + X[idx++] + Y2
|
||||
// B = rotateLeft(B, 30)
|
||||
E += (A << 5 | (A >> 27)) + H(B, C, D) + _hashValue[idx++] + Y2;
|
||||
B = B << 30 | (B >> 2);
|
||||
|
||||
D += (E << 5 | (E >> 27)) + H(A, B, C) + _hashValue[idx++] + Y2;
|
||||
A = A << 30 | (A >> 2);
|
||||
|
||||
C += (D << 5 | (D >> 27)) + H(E, A, B) + _hashValue[idx++] + Y2;
|
||||
E = E << 30 | (E >> 2);
|
||||
|
||||
B += (C << 5 | (C >> 27)) + H(D, E, A) + _hashValue[idx++] + Y2;
|
||||
D = D << 30 | (D >> 2);
|
||||
|
||||
A += (B << 5 | (B >> 27)) + H(C, D, E) + _hashValue[idx++] + Y2;
|
||||
C = C << 30 | (C >> 2);
|
||||
}
|
||||
|
||||
//
|
||||
// round 3
|
||||
//
|
||||
for (int j = 0; j < 4; j++)
|
||||
{
|
||||
// E = rotateLeft(A, 5) + G(B, C, D) + E + X[idx++] + Y3
|
||||
// B = rotateLeft(B, 30)
|
||||
E += (A << 5 | (A >> 27)) + G(B, C, D) + _hashValue[idx++] + Y3;
|
||||
B = B << 30 | (B >> 2);
|
||||
|
||||
D += (E << 5 | (E >> 27)) + G(A, B, C) + _hashValue[idx++] + Y3;
|
||||
A = A << 30 | (A >> 2);
|
||||
|
||||
C += (D << 5 | (D >> 27)) + G(E, A, B) + _hashValue[idx++] + Y3;
|
||||
E = E << 30 | (E >> 2);
|
||||
|
||||
B += (C << 5 | (C >> 27)) + G(D, E, A) + _hashValue[idx++] + Y3;
|
||||
D = D << 30 | (D >> 2);
|
||||
|
||||
A += (B << 5 | (B >> 27)) + G(C, D, E) + _hashValue[idx++] + Y3;
|
||||
C = C << 30 | (C >> 2);
|
||||
}
|
||||
|
||||
//
|
||||
// round 4
|
||||
//
|
||||
for (int j = 0; j < 4; j++)
|
||||
{
|
||||
// E = rotateLeft(A, 5) + H(B, C, D) + E + X[idx++] + Y4
|
||||
// B = rotateLeft(B, 30)
|
||||
E += (A << 5 | (A >> 27)) + H(B, C, D) + _hashValue[idx++] + Y4;
|
||||
B = B << 30 | (B >> 2);
|
||||
|
||||
D += (E << 5 | (E >> 27)) + H(A, B, C) + _hashValue[idx++] + Y4;
|
||||
A = A << 30 | (A >> 2);
|
||||
|
||||
C += (D << 5 | (D >> 27)) + H(E, A, B) + _hashValue[idx++] + Y4;
|
||||
E = E << 30 | (E >> 2);
|
||||
|
||||
B += (C << 5 | (C >> 27)) + H(D, E, A) + _hashValue[idx++] + Y4;
|
||||
D = D << 30 | (D >> 2);
|
||||
|
||||
A += (B << 5 | (B >> 27)) + H(C, D, E) + _hashValue[idx++] + Y4;
|
||||
C = C << 30 | (C >> 2);
|
||||
}
|
||||
|
||||
H1 += A;
|
||||
H2 += B;
|
||||
H3 += C;
|
||||
H4 += D;
|
||||
H5 += E;
|
||||
|
||||
//
|
||||
// reset start of the buffer.
|
||||
//
|
||||
this._offset = 0;
|
||||
Array.Clear(_hashValue, 0, 16);
|
||||
}
|
||||
|
||||
private static uint BE_To__UInt32(byte[] bs, int off)
|
||||
{
|
||||
uint n = (uint)bs[off] << 24;
|
||||
n |= (uint)bs[++off] << 16;
|
||||
n |= (uint)bs[++off] << 8;
|
||||
n |= (uint)bs[++off];
|
||||
return n;
|
||||
}
|
||||
|
||||
private static void UInt32_To__BE
|
||||
(uint n, byte[] bs, int off)
|
||||
{
|
||||
bs[off] = (byte)(n >> 24);
|
||||
bs[++off] = (byte)(n >> 16);
|
||||
bs[++off] = (byte)(n >> 8);
|
||||
bs[++off] = (byte)(n);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,389 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Security.Cryptography;
|
||||
|
||||
namespace Renci.SshNet.Security.Cryptography
|
||||
{
|
||||
/// <summary>
|
||||
/// SHA256 algorithm implementation.
|
||||
/// </summary>
|
||||
public class SHA256Hash : HashAlgorithm
|
||||
{
|
||||
private const int DIGEST_SIZE = 32;
|
||||
|
||||
private uint H1, H2, H3, H4, H5, H6, H7, H8;
|
||||
|
||||
private uint[] X = new uint[64];
|
||||
|
||||
private int _offset;
|
||||
|
||||
private byte[] _buffer;
|
||||
|
||||
private int _bufferOffset;
|
||||
|
||||
private long _byteCount;
|
||||
|
||||
/// <summary>
|
||||
/// Gets the size, in bits, of the computed hash code.
|
||||
/// </summary>
|
||||
/// <returns>The size, in bits, of the computed hash code.</returns>
|
||||
public override int HashSize
|
||||
{
|
||||
get
|
||||
{
|
||||
return DIGEST_SIZE * 8;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the input block size.
|
||||
/// </summary>
|
||||
/// <returns>The input block size.</returns>
|
||||
public override int InputBlockSize
|
||||
{
|
||||
get
|
||||
{
|
||||
return 64;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the output block size.
|
||||
/// </summary>
|
||||
/// <returns>The output block size.</returns>
|
||||
public override int OutputBlockSize
|
||||
{
|
||||
get
|
||||
{
|
||||
return 64;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets a value indicating whether the current transform can be reused.
|
||||
/// </summary>
|
||||
/// <returns>Always true.</returns>
|
||||
public override bool CanReuseTransform
|
||||
{
|
||||
get
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets a value indicating whether multiple blocks can be transformed.
|
||||
/// </summary>
|
||||
/// <returns>true if multiple blocks can be transformed; otherwise, false.</returns>
|
||||
public override bool CanTransformMultipleBlocks
|
||||
{
|
||||
get
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="SHA1"/> class.
|
||||
/// </summary>
|
||||
public SHA256Hash()
|
||||
{
|
||||
this._buffer = new byte[4];
|
||||
this.Initialize();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Routes data written to the object into the hash algorithm for computing the hash.
|
||||
/// </summary>
|
||||
/// <param name="array">The input to compute the hash code for.</param>
|
||||
/// <param name="ibStart">The offset into the byte array from which to begin using data.</param>
|
||||
/// <param name="cbSize">The number of bytes in the byte array to use as data.</param>
|
||||
protected override void HashCore(byte[] array, int ibStart, int cbSize)
|
||||
{
|
||||
// Fill the current word
|
||||
while ((this._bufferOffset != 0) && (cbSize > 0))
|
||||
{
|
||||
this.Update(array[ibStart]);
|
||||
ibStart++;
|
||||
cbSize--;
|
||||
}
|
||||
|
||||
// Process whole words.
|
||||
while (cbSize > this._buffer.Length)
|
||||
{
|
||||
this.ProcessWord(array, ibStart);
|
||||
|
||||
ibStart += this._buffer.Length;
|
||||
cbSize -= this._buffer.Length;
|
||||
this._byteCount += this._buffer.Length;
|
||||
}
|
||||
|
||||
// Load in the remainder.
|
||||
while (cbSize > 0)
|
||||
{
|
||||
this.Update(array[ibStart]);
|
||||
|
||||
ibStart++;
|
||||
cbSize--;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Finalizes the hash computation after the last data is processed by the cryptographic stream object.
|
||||
/// </summary>
|
||||
/// <returns>
|
||||
/// The computed hash code.
|
||||
/// </returns>
|
||||
protected override byte[] HashFinal()
|
||||
{
|
||||
var output = new byte[DIGEST_SIZE];
|
||||
long bitLength = (this._byteCount << 3);
|
||||
|
||||
//
|
||||
// add the pad bytes.
|
||||
//
|
||||
this.Update((byte)128);
|
||||
|
||||
while (this._bufferOffset != 0)
|
||||
this.Update((byte)0);
|
||||
|
||||
if (this._offset > 14)
|
||||
{
|
||||
this.ProcessBlock();
|
||||
}
|
||||
|
||||
X[14] = (uint)((ulong)bitLength >> 32);
|
||||
X[15] = (uint)((ulong)bitLength);
|
||||
|
||||
|
||||
this.ProcessBlock();
|
||||
|
||||
UInt32_To_BE((uint)H1, output, 0);
|
||||
UInt32_To_BE((uint)H2, output, 0 + 4);
|
||||
UInt32_To_BE((uint)H3, output, 0 + 8);
|
||||
UInt32_To_BE((uint)H4, output, 0 + 12);
|
||||
UInt32_To_BE((uint)H5, output, 0 + 16);
|
||||
UInt32_To_BE((uint)H6, output, 0 + 20);
|
||||
UInt32_To_BE((uint)H7, output, 0 + 24);
|
||||
UInt32_To_BE((uint)H8, output, 0 + 28);
|
||||
|
||||
this.Initialize();
|
||||
|
||||
return output;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Initializes an implementation of the <see cref="T:System.Security.Cryptography.HashAlgorithm"/> class.
|
||||
/// </summary>
|
||||
public override void Initialize()
|
||||
{
|
||||
//this.Reset();
|
||||
this._byteCount = 0;
|
||||
this._bufferOffset = 0;
|
||||
Array.Clear(this._buffer, 0, this._buffer.Length);
|
||||
|
||||
H1 = 0x6a09e667;
|
||||
H2 = 0xbb67ae85;
|
||||
H3 = 0x3c6ef372;
|
||||
H4 = 0xa54ff53a;
|
||||
H5 = 0x510e527f;
|
||||
H6 = 0x9b05688c;
|
||||
H7 = 0x1f83d9ab;
|
||||
H8 = 0x5be0cd19;
|
||||
|
||||
this._offset = 0;
|
||||
Array.Clear(X, 0, X.Length);
|
||||
}
|
||||
|
||||
private void Update(byte input)
|
||||
{
|
||||
this._buffer[this._bufferOffset++] = input;
|
||||
|
||||
if (this._bufferOffset == this._buffer.Length)
|
||||
{
|
||||
this.ProcessWord(this._buffer, 0);
|
||||
this._bufferOffset = 0;
|
||||
}
|
||||
|
||||
this._byteCount++;
|
||||
}
|
||||
|
||||
private static uint BE_To_UInt32(byte[] bs, int off)
|
||||
{
|
||||
uint n = (uint)bs[off] << 24;
|
||||
n |= (uint)bs[++off] << 16;
|
||||
n |= (uint)bs[++off] << 8;
|
||||
n |= (uint)bs[++off];
|
||||
return n;
|
||||
}
|
||||
|
||||
private static void UInt32_To_BE(uint n, byte[] bs, int off)
|
||||
{
|
||||
bs[off] = (byte)(n >> 24);
|
||||
bs[++off] = (byte)(n >> 16);
|
||||
bs[++off] = (byte)(n >> 8);
|
||||
bs[++off] = (byte)(n);
|
||||
}
|
||||
|
||||
private void ProcessWord(byte[] input, int inOff)
|
||||
{
|
||||
X[this._offset] = BE_To_UInt32(input, inOff);
|
||||
|
||||
if (++this._offset == 16)
|
||||
{
|
||||
ProcessBlock();
|
||||
}
|
||||
}
|
||||
|
||||
private void ProcessLength(long bitLength)
|
||||
{
|
||||
if (this._offset > 14)
|
||||
{
|
||||
ProcessBlock();
|
||||
}
|
||||
|
||||
X[14] = (uint)((ulong)bitLength >> 32);
|
||||
X[15] = (uint)((ulong)bitLength);
|
||||
}
|
||||
|
||||
private void ProcessBlock()
|
||||
{
|
||||
//
|
||||
// expand 16 word block into 64 word blocks.
|
||||
//
|
||||
for (int ti = 16; ti <= 63; ti++)
|
||||
{
|
||||
X[ti] = Theta1(X[ti - 2]) + X[ti - 7] + Theta0(X[ti - 15]) + X[ti - 16];
|
||||
}
|
||||
|
||||
//
|
||||
// set up working variables.
|
||||
//
|
||||
uint a = H1;
|
||||
uint b = H2;
|
||||
uint c = H3;
|
||||
uint d = H4;
|
||||
uint e = H5;
|
||||
uint f = H6;
|
||||
uint g = H7;
|
||||
uint h = H8;
|
||||
|
||||
int t = 0;
|
||||
for (int i = 0; i < 8; ++i)
|
||||
{
|
||||
// t = 8 * i
|
||||
h += Sum1Ch(e, f, g) + K[t] + X[t];
|
||||
d += h;
|
||||
h += Sum0Maj(a, b, c);
|
||||
++t;
|
||||
|
||||
// t = 8 * i + 1
|
||||
g += Sum1Ch(d, e, f) + K[t] + X[t];
|
||||
c += g;
|
||||
g += Sum0Maj(h, a, b);
|
||||
++t;
|
||||
|
||||
// t = 8 * i + 2
|
||||
f += Sum1Ch(c, d, e) + K[t] + X[t];
|
||||
b += f;
|
||||
f += Sum0Maj(g, h, a);
|
||||
++t;
|
||||
|
||||
// t = 8 * i + 3
|
||||
e += Sum1Ch(b, c, d) + K[t] + X[t];
|
||||
a += e;
|
||||
e += Sum0Maj(f, g, h);
|
||||
++t;
|
||||
|
||||
// t = 8 * i + 4
|
||||
d += Sum1Ch(a, b, c) + K[t] + X[t];
|
||||
h += d;
|
||||
d += Sum0Maj(e, f, g);
|
||||
++t;
|
||||
|
||||
// t = 8 * i + 5
|
||||
c += Sum1Ch(h, a, b) + K[t] + X[t];
|
||||
g += c;
|
||||
c += Sum0Maj(d, e, f);
|
||||
++t;
|
||||
|
||||
// t = 8 * i + 6
|
||||
b += Sum1Ch(g, h, a) + K[t] + X[t];
|
||||
f += b;
|
||||
b += Sum0Maj(c, d, e);
|
||||
++t;
|
||||
|
||||
// t = 8 * i + 7
|
||||
a += Sum1Ch(f, g, h) + K[t] + X[t];
|
||||
e += a;
|
||||
a += Sum0Maj(b, c, d);
|
||||
++t;
|
||||
}
|
||||
|
||||
H1 += a;
|
||||
H2 += b;
|
||||
H3 += c;
|
||||
H4 += d;
|
||||
H5 += e;
|
||||
H6 += f;
|
||||
H7 += g;
|
||||
H8 += h;
|
||||
|
||||
//
|
||||
// reset the offset and clean out the word buffer.
|
||||
//
|
||||
this._offset = 0;
|
||||
Array.Clear(X, 0, 16);
|
||||
}
|
||||
|
||||
private static uint Sum1Ch(uint x, uint y, uint z)
|
||||
{
|
||||
// return Sum1(x) + Ch(x, y, z);
|
||||
return (((x >> 6) | (x << 26)) ^ ((x >> 11) | (x << 21)) ^ ((x >> 25) | (x << 7)))
|
||||
+ ((x & y) ^ ((~x) & z));
|
||||
}
|
||||
|
||||
private static uint Sum0Maj(uint x, uint y, uint z)
|
||||
{
|
||||
// return Sum0(x) + Maj(x, y, z);
|
||||
return (((x >> 2) | (x << 30)) ^ ((x >> 13) | (x << 19)) ^ ((x >> 22) | (x << 10)))
|
||||
+ ((x & y) ^ (x & z) ^ (y & z));
|
||||
}
|
||||
|
||||
private static uint Theta0(uint x)
|
||||
{
|
||||
return ((x >> 7) | (x << 25)) ^ ((x >> 18) | (x << 14)) ^ (x >> 3);
|
||||
}
|
||||
|
||||
private static uint Theta1(uint x)
|
||||
{
|
||||
return ((x >> 17) | (x << 15)) ^ ((x >> 19) | (x << 13)) ^ (x >> 10);
|
||||
}
|
||||
|
||||
/* SHA-256 Constants
|
||||
* (represent the first 32 bits of the fractional parts of the
|
||||
* cube roots of the first sixty-four prime numbers)
|
||||
*/
|
||||
private static readonly uint[] K = {
|
||||
0x428a2f98, 0x71374491, 0xb5c0fbcf, 0xe9b5dba5,
|
||||
0x3956c25b, 0x59f111f1, 0x923f82a4, 0xab1c5ed5,
|
||||
0xd807aa98, 0x12835b01, 0x243185be, 0x550c7dc3,
|
||||
0x72be5d74, 0x80deb1fe, 0x9bdc06a7, 0xc19bf174,
|
||||
0xe49b69c1, 0xefbe4786, 0x0fc19dc6, 0x240ca1cc,
|
||||
0x2de92c6f, 0x4a7484aa, 0x5cb0a9dc, 0x76f988da,
|
||||
0x983e5152, 0xa831c66d, 0xb00327c8, 0xbf597fc7,
|
||||
0xc6e00bf3, 0xd5a79147, 0x06ca6351, 0x14292967,
|
||||
0x27b70a85, 0x2e1b2138, 0x4d2c6dfc, 0x53380d13,
|
||||
0x650a7354, 0x766a0abb, 0x81c2c92e, 0x92722c85,
|
||||
0xa2bfe8a1, 0xa81a664b, 0xc24b8b70, 0xc76c51a3,
|
||||
0xd192e819, 0xd6990624, 0xf40e3585, 0x106aa070,
|
||||
0x19a4c116, 0x1e376c08, 0x2748774c, 0x34b0bcb5,
|
||||
0x391c0cb3, 0x4ed8aa4a, 0x5b9cca4f, 0x682e6ff3,
|
||||
0x748f82ee, 0x78a5636f, 0x84c87814, 0x8cc70208,
|
||||
0x90befffa, 0xa4506ceb, 0xbef9a3f7, 0xc67178f2
|
||||
};
|
||||
|
||||
}
|
||||
}
|
||||
@@ -1,70 +0,0 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
|
||||
namespace Renci.SshNet.Security.Cryptography
|
||||
{
|
||||
/// <summary>
|
||||
/// Provides additional cipher modes
|
||||
/// </summary>
|
||||
public enum CipherModeEx
|
||||
{
|
||||
/// <summary>
|
||||
/// The Cipher Block Chaining (CBC) mode introduces feedback. Before each plain
|
||||
/// text block is encrypted, it is combined with the cipher text of the previous
|
||||
/// block by a bitwise exclusive OR operation. This ensures that even if the
|
||||
/// plain text contains many identical blocks, they will each encrypt to a different
|
||||
/// cipher text block. The initialization vector is combined with the first plain
|
||||
/// text block by a bitwise exclusive OR operation before the block is encrypted.
|
||||
/// If a single bit of the cipher text block is mangled, the corresponding plain
|
||||
/// text block will also be mangled. In addition, a bit in the subsequent block,
|
||||
/// in the same position as the original mangled bit, will be mangled.
|
||||
/// </summary>
|
||||
CBC = 1,
|
||||
/// <summary>
|
||||
/// The Electronic Codebook (ECB) mode encrypts each block individually. This
|
||||
/// means that any blocks of plain text that are identical and are in the same
|
||||
/// message, or in a different message encrypted with the same key, will be transformed
|
||||
/// into identical cipher text blocks. If the plain text to be encrypted contains
|
||||
/// substantial repetition, it is feasible for the cipher text to be broken one
|
||||
/// block at a time. Also, it is possible for an active adversary to substitute
|
||||
/// and exchange individual blocks without detection. If a single bit of the
|
||||
/// cipher text block is mangled, the entire corresponding plain text block will
|
||||
/// also be mangled.
|
||||
/// </summary>
|
||||
ECB = 2,
|
||||
/// <summary>
|
||||
/// The Output Feedback (OFB) mode processes small increments of plain text into
|
||||
/// cipher text instead of processing an entire block at a time. This mode is
|
||||
/// similar to CFB; the only difference between the two modes is the way that
|
||||
/// the shift register is filled. If a bit in the cipher text is mangled, the
|
||||
/// corresponding bit of plain text will be mangled. However, if there are extra
|
||||
/// or missing bits from the cipher text, the plain text will be mangled from
|
||||
/// that point on.
|
||||
/// </summary>
|
||||
OFB = 3,
|
||||
/// <summary>
|
||||
/// The Cipher Feedback (CFB) mode processes small increments of plain text into
|
||||
/// cipher text, instead of processing an entire block at a time. This mode uses
|
||||
/// a shift register that is one block in length and is divided into sections.
|
||||
/// For example, if the block size is eight bytes, with one byte processed at
|
||||
/// a time, the shift register is divided into eight sections. If a bit in the
|
||||
/// cipher text is mangled, one plain text bit is mangled and the shift register
|
||||
/// is corrupted. This results in the next several plain text increments being
|
||||
/// mangled until the bad bit is shifted out of the shift register.
|
||||
/// </summary>
|
||||
CFB = 4,
|
||||
/// <summary>
|
||||
/// The Cipher Text Stealing (CTS) mode handles any length of plain text and
|
||||
/// produces cipher text whose length matches the plain text length. This mode
|
||||
/// behaves like the CBC mode for all but the last two blocks of the plain text.
|
||||
/// </summary>
|
||||
CTS = 5,
|
||||
/// <summary>
|
||||
/// Counter Block Cipher mode
|
||||
/// </summary>
|
||||
CTR = 10,
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,28 +0,0 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
|
||||
namespace Renci.SshNet.Security.Cryptography
|
||||
{
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
public abstract class ModeBase : CipherBase
|
||||
{
|
||||
/// <summary>
|
||||
/// Gets the cipher.
|
||||
/// </summary>
|
||||
public CipherBase Cipher { get; private set; }
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="ModeBase"/> class.
|
||||
/// </summary>
|
||||
/// <param name="cipher">The cipher.</param>
|
||||
public ModeBase(CipherBase cipher)
|
||||
: base(cipher.Key, cipher.IV)
|
||||
{
|
||||
this.Cipher = cipher;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,42 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Security.Cryptography;
|
||||
using Renci.SshNet.Common;
|
||||
using Renci.SshNet.Security.Cryptography.Ciphers;
|
||||
|
||||
namespace Renci.SshNet.Security.Cryptography
|
||||
{
|
||||
/// <summary>
|
||||
/// Implements RSA digital signature algorithm.
|
||||
/// </summary>
|
||||
public class RsaDigitalSignature : CipherDigitalSignature
|
||||
{
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="RsaDigitalSignature"/> class.
|
||||
/// </summary>
|
||||
/// <param name="exponent">The exponent.</param>
|
||||
/// <param name="modulus">The modulus.</param>
|
||||
/// <param name="d">The D value.</param>
|
||||
/// <param name="dp">The DP value.</param>
|
||||
/// <param name="dq">The DQ value.</param>
|
||||
/// <param name="inverseQ">The InverseQ value.</param>
|
||||
/// <param name="p">The P value.</param>
|
||||
/// <param name="q">The Q value.</param>
|
||||
public RsaDigitalSignature(byte[] exponent, byte[] modulus, byte[] d, byte[] dp, byte[] dq, byte[] inverseQ, byte[] p, byte[] q)
|
||||
: base(new SHA1Hash(), new RsaCipher(new BigInteger(exponent.Reverse().ToArray()), new BigInteger(modulus.Reverse().ToArray()), new BigInteger(d.Reverse().ToArray()), new BigInteger(dp.Reverse().ToArray()), new BigInteger(dq.Reverse().ToArray()), new BigInteger(inverseQ.Reverse().ToArray()), new BigInteger(p.Reverse().ToArray()), new BigInteger(q.Reverse().ToArray())))
|
||||
{
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="RsaDigitalSignature"/> class.
|
||||
/// </summary>
|
||||
/// <param name="exponent">The exponent.</param>
|
||||
/// <param name="modulus">The modulus.</param>
|
||||
public RsaDigitalSignature(byte[] exponent, byte[] modulus)
|
||||
: base(new SHA1Hash(), new RsaCipher(new BigInteger(exponent.Reverse().ToArray()), new BigInteger(modulus.Reverse().ToArray())))
|
||||
{
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,22 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
|
||||
namespace Renci.SshNet.Security.Cryptography
|
||||
{
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
public abstract class StreamCipher : SymmetricCipher
|
||||
{
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="StreamCipher"/> class.
|
||||
/// </summary>
|
||||
/// <param name="key">The key.</param>
|
||||
protected StreamCipher(byte[] key)
|
||||
: base(key)
|
||||
{
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,72 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
|
||||
namespace Renci.SshNet.Security.Cryptography
|
||||
{
|
||||
/// <summary>
|
||||
/// Base class for symmetric cipher implementations.
|
||||
/// </summary>
|
||||
public abstract class SymmetricCipher : Cipher
|
||||
{
|
||||
/// <summary>
|
||||
/// Gets the size of the key in bits.
|
||||
/// </summary>
|
||||
/// <value>
|
||||
/// The size of the key in bits.
|
||||
/// </value>
|
||||
public int KeySize { get; private set; }
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="SymmetricCipher"/> class.
|
||||
/// </summary>
|
||||
/// <param name="key">The key.</param>
|
||||
protected SymmetricCipher(byte[] key)
|
||||
{
|
||||
var keySize = key.Length * 8;
|
||||
|
||||
if (this.ValidateKeySize(keySize))
|
||||
{
|
||||
this.KeySize = keySize;
|
||||
}
|
||||
else
|
||||
{
|
||||
throw new ArgumentException(string.Format("KeySize '{0}' is not valid for this algorithm.", keySize));
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Encrypts the specified region of the input byte array and copies the encrypted data to the specified region of the output byte array.
|
||||
/// </summary>
|
||||
/// <param name="inputBuffer">The input data to encrypt.</param>
|
||||
/// <param name="inputOffset">The offset into the input byte array from which to begin using data.</param>
|
||||
/// <param name="inputCount">The number of bytes in the input byte array to use as data.</param>
|
||||
/// <param name="outputBuffer">The output to which to write encrypted data.</param>
|
||||
/// <param name="outputOffset">The offset into the output byte array from which to begin writing data.</param>
|
||||
/// <returns>
|
||||
/// The number of bytes encrypted.
|
||||
/// </returns>
|
||||
public abstract int EncryptBlock(byte[] inputBuffer, int inputOffset, int inputCount, byte[] outputBuffer, int outputOffset);
|
||||
|
||||
/// <summary>
|
||||
/// Decrypts the specified region of the input byte array and copies the decrypted data to the specified region of the output byte array.
|
||||
/// </summary>
|
||||
/// <param name="inputBuffer">The input data to decrypt.</param>
|
||||
/// <param name="inputOffset">The offset into the input byte array from which to begin using data.</param>
|
||||
/// <param name="inputCount">The number of bytes in the input byte array to use as data.</param>
|
||||
/// <param name="outputBuffer">The output to which to write decrypted data.</param>
|
||||
/// <param name="outputOffset">The offset into the output byte array from which to begin writing data.</param>
|
||||
/// <returns>
|
||||
/// The number of bytes decrypted.
|
||||
/// </returns>
|
||||
public abstract int DecryptBlock(byte[] inputBuffer, int inputOffset, int inputCount, byte[] outputBuffer, int outputOffset);
|
||||
|
||||
/// <summary>
|
||||
/// Validates the size of the key.
|
||||
/// </summary>
|
||||
/// <param name="keySize">Size of the key.</param>
|
||||
/// <returns>true if keySize is valid; otherwise false</returns>
|
||||
protected abstract bool ValidateKeySize(int keySize);
|
||||
}
|
||||
}
|
||||
@@ -6,6 +6,8 @@ using Renci.SshNet.Common;
|
||||
using Renci.SshNet.Compression;
|
||||
using Renci.SshNet.Messages;
|
||||
using Renci.SshNet.Messages.Transport;
|
||||
using Renci.SshNet.Security.Cryptography.Ciphers;
|
||||
using Renci.SshNet.Security.Cryptography;
|
||||
|
||||
namespace Renci.SshNet.Security
|
||||
{
|
||||
@@ -14,13 +16,13 @@ namespace Renci.SshNet.Security
|
||||
/// </summary>
|
||||
public abstract class KeyExchange : Algorithm, IDisposable
|
||||
{
|
||||
private Type _clientCipherType;
|
||||
private CipherInfo _clientCipherInfo;
|
||||
|
||||
private Type _serverCipherType;
|
||||
private CipherInfo _serverCipherInfo;
|
||||
|
||||
private Type _cientHmacAlgorithmType;
|
||||
private Func<byte[], HashAlgorithm> _cientHmacAlgorithmType;
|
||||
|
||||
private Type _serverHmacAlgorithmType;
|
||||
private Func<byte[], HashAlgorithm> _serverHmacAlgorithmType;
|
||||
|
||||
private Type _compressionType;
|
||||
|
||||
@@ -131,8 +133,8 @@ namespace Renci.SshNet.Security
|
||||
throw new SshConnectionException("Decompression algorithm not found", DisconnectReason.KeyExchangeFailed);
|
||||
}
|
||||
|
||||
this._clientCipherType = session.ConnectionInfo.Encryptions[clientEncryptionAlgorithmName];
|
||||
this._serverCipherType = session.ConnectionInfo.Encryptions[clientEncryptionAlgorithmName];
|
||||
this._clientCipherInfo = session.ConnectionInfo.Encryptions[clientEncryptionAlgorithmName];
|
||||
this._serverCipherInfo = session.ConnectionInfo.Encryptions[clientEncryptionAlgorithmName];
|
||||
this._cientHmacAlgorithmType = session.ConnectionInfo.HmacAlgorithms[clientHmacAlgorithmName];
|
||||
this._serverHmacAlgorithmType = session.ConnectionInfo.HmacAlgorithms[serverHmacAlgorithmName];
|
||||
this._compressionType = session.ConnectionInfo.CompressionAlgorithms[compressionAlgorithmName];
|
||||
@@ -159,84 +161,78 @@ namespace Renci.SshNet.Security
|
||||
/// Creates the server side cipher to use.
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
public Cipher CreateServerCipher()
|
||||
public BlockCipher CreateServerCipher()
|
||||
{
|
||||
// Resolve Session ID
|
||||
var sessionId = this.Session.SessionId ?? this.ExchangeHash;
|
||||
|
||||
// Create server cipher
|
||||
var serverCipher = this._serverCipherType.CreateInstance<Cipher>();
|
||||
|
||||
// Calculate server to client initial IV
|
||||
var serverVector = this.Hash(this.GenerateSessionKey(this.SharedKey, this.ExchangeHash, 'B', sessionId));
|
||||
|
||||
// Calculate server to client encryption
|
||||
var serverKey = this.Hash(this.GenerateSessionKey(this.SharedKey, this.ExchangeHash, 'D', sessionId));
|
||||
|
||||
serverKey = this.GenerateSessionKey(this.SharedKey, this.ExchangeHash, serverKey, serverCipher.KeySize / 8);
|
||||
|
||||
serverCipher.Init(serverKey, serverVector);
|
||||
|
||||
return serverCipher;
|
||||
serverKey = this.GenerateSessionKey(this.SharedKey, this.ExchangeHash, serverKey, this._serverCipherInfo.KeySize / 8);
|
||||
|
||||
// Create server cipher
|
||||
return this._serverCipherInfo.Cipher(serverKey, serverVector);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Creates the client side cipher to use.
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
public Cipher CreateClientCipher()
|
||||
public BlockCipher CreateClientCipher()
|
||||
{
|
||||
// Resolve Session ID
|
||||
var sessionId = this.Session.SessionId ?? this.ExchangeHash;
|
||||
|
||||
// Create client cipher
|
||||
var clientCipher = this._clientCipherType.CreateInstance<Cipher>();
|
||||
|
||||
// Calculate client to server initial IV
|
||||
var clientVector = this.Hash(this.GenerateSessionKey(this.SharedKey, this.ExchangeHash, 'A', sessionId));
|
||||
|
||||
// Calculate client to server encryption
|
||||
var clientKey = this.Hash(this.GenerateSessionKey(this.SharedKey, this.ExchangeHash, 'C', sessionId));
|
||||
|
||||
clientKey = this.GenerateSessionKey(this.SharedKey, this.ExchangeHash, clientKey, clientCipher.KeySize / 8);
|
||||
clientKey = this.GenerateSessionKey(this.SharedKey, this.ExchangeHash, clientKey, this._clientCipherInfo.KeySize / 8);
|
||||
|
||||
clientCipher.Init(clientKey, clientVector);
|
||||
|
||||
return clientCipher;
|
||||
// Create client cipher
|
||||
return this._clientCipherInfo.Cipher(clientKey, clientVector);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Creates the server side hash algorithm to use.
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
public HMac CreateServerHash()
|
||||
public HashAlgorithm CreateServerHash()
|
||||
{
|
||||
// Resolve Session ID
|
||||
var sessionId = this.Session.SessionId ?? this.ExchangeHash;
|
||||
|
||||
// Create server HMac
|
||||
var serverHMac = this._serverHmacAlgorithmType.CreateInstance<HMac>();
|
||||
//var serverHMac = this._serverHmacAlgorithmType.CreateInstance<HMac>();
|
||||
|
||||
serverHMac.Init(this.Hash(this.GenerateSessionKey(this.SharedKey, this.ExchangeHash, 'F', sessionId)));
|
||||
//serverHMac.Init(this.Hash(this.GenerateSessionKey(this.SharedKey, this.ExchangeHash, 'F', sessionId)));
|
||||
|
||||
return serverHMac;
|
||||
//return serverHMac;
|
||||
return this._serverHmacAlgorithmType(this.Hash(this.GenerateSessionKey(this.SharedKey, this.ExchangeHash, 'F', sessionId)));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Creates the client side hash algorithm to use.
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
public HMac CreateClientHash()
|
||||
public HashAlgorithm CreateClientHash()
|
||||
{
|
||||
// Resolve Session ID
|
||||
var sessionId = this.Session.SessionId ?? this.ExchangeHash;
|
||||
|
||||
// Create client HMac
|
||||
var clientHMac = this._cientHmacAlgorithmType.CreateInstance<HMac>();
|
||||
//var clientHMac = this._cientHmacAlgorithmType.CreateInstance<HMac>();
|
||||
|
||||
clientHMac.Init(this.Hash(this.GenerateSessionKey(this.SharedKey, this.ExchangeHash, 'E', sessionId)));
|
||||
//clientHMac.Init(this.Hash(this.GenerateSessionKey(this.SharedKey, this.ExchangeHash, 'E', sessionId)));
|
||||
|
||||
return clientHMac;
|
||||
//return clientHMac;
|
||||
return this._cientHmacAlgorithmType(this.Hash(this.GenerateSessionKey(this.SharedKey, this.ExchangeHash, 'E', sessionId)));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
||||
@@ -17,6 +17,8 @@ using Renci.SshNet.Messages.Connection;
|
||||
using Renci.SshNet.Messages.Transport;
|
||||
using Renci.SshNet.Security;
|
||||
using System.Globalization;
|
||||
using Renci.SshNet.Security.Cryptography.Ciphers;
|
||||
using Renci.SshNet.Security.Cryptography;
|
||||
|
||||
namespace Renci.SshNet
|
||||
{
|
||||
@@ -108,13 +110,13 @@ namespace Renci.SshNet
|
||||
|
||||
private KeyExchange _keyExchange;
|
||||
|
||||
private HMac _serverMac;
|
||||
private HashAlgorithm _serverMac;
|
||||
|
||||
private HMac _clientMac;
|
||||
private HashAlgorithm _clientMac;
|
||||
|
||||
private Cipher _clientCipher;
|
||||
private BlockCipher _clientCipher;
|
||||
|
||||
private Cipher _serverCipher;
|
||||
private BlockCipher _serverCipher;
|
||||
|
||||
private Compressor _serverDecompression;
|
||||
|
||||
|
||||
Reference in New Issue
Block a user