我在VB.NET中编写的类如下,并且功能齐全,因为它将完美地加密和解密自己的块.
Imports System Imports System.Text Imports System.IO Imports System.Security.Cryptography Public Class Cipher Dim method As TripleDESCryptoServiceProvider Dim key As Byte() Public Property Password() As String Get Return System.Text.Encoding.Unicode.GetString(Key) End Get Set(value As String) key = System.Text.Encoding.Unicode.GetBytes(value) End Set End Property Public Function Encrypt(data As String) As String Dim ms As New System.IO.MemoryStream ' Create the encoder to write to the stream. Dim dataBytes() As Byte = System.Text.Encoding.Unicode.GetBytes(data) Dim encStream As New CryptoStream(ms, method.CreateEncryptor(), System.Security.Cryptography.CryptoStreamMode.Write) ' Use the crypto stream to write the byte array to the stream. encStream.Write(dataBytes, 0, dataBytes.Length) encStream.FlushFinalBlock() ' IV and Ciphered string are each Base64'd and seperated by a comma, then the whole result is Base64'd Return Convert.ToBase64String(System.Text.Encoding.Unicode.GetBytes(Convert.ToBase64String(method.IV) & "," & Convert.ToBase64String(ms.ToArray))) End Function Public Function Decrypt(data As String) As String ' Convert the encrypted text string to a byte array. Dim partDecoded As String = System.Text.Encoding.Unicode.GetString(Convert.FromBase64String(data)) Dim dataBytes() As Byte If InStr(partDecoded, ",") > 0 Then Dim parts() As String = Split(partDecoded, ",") ' Get IV from first part method.IV = Convert.FromBase64String(parts(0)) ' Get ciphered data from second part dataBytes = Convert.FromBase64String(parts(1)) ' Create the stream. Dim ms As New System.IO.MemoryStream ' Create the decoder to write to the stream. Dim decStream As New CryptoStream(ms, method.CreateDecryptor(), System.Security.Cryptography.CryptoStreamMode.Write) ' Use the crypto stream to write the byte array to the stream. decStream.Write(dataBytes, 0, dataBytes.Length) decStream.FlushFinalBlock() ' Convert the plaintext stream to a string. Return System.Text.Encoding.Unicode.GetString(ms.ToArray) Else Return False End If End Function Public Sub New() method = New TripleDESCryptoServiceProvider method.Mode = CipherMode.CFB method.GenerateIV() End Sub End Class
上述类的示例用法
Dim c As New Cipher c.Password = "12345" Dim encrypted As String = c.Encrypt("hello") Debug.Print(encrypted) Dim decrypted As String = c.Decrypt(encrypted) Debug.Print(decrypted)
现在我还有以下PHP代码(也可以)
class Cipher { private $iv; private $securekey; function __construct($key) { $this->securekey = $key; } function encrypt($string) { $this->iv = mcrypt_create_iv(mcrypt_get_iv_size(MCRYPT_3DES, MCRYPT_MODE_CFB),MCRYPT_DEV_RANDOM); $encrypted = base64_encode(mcrypt_encrypt(MCRYPT_3DES, $this->securekey, $string, MCRYPT_MODE_CFB, $this->iv)); return base64_encode(base64_encode($this->iv) . ',' . $encrypted); } function decrypt($string) { $decrypt = base64_decode($string); if(strpos($decrypt,',') > 0) { $decrypt = explode(',', $decrypt); $this->iv = base64_decode($decrypt[0]); return trim(mcrypt_decrypt(MCRYPT_3DES, $this->securekey, base64_decode($decrypt[1]), MCRYPT_MODE_CFB, $this->iv)); } else { return false; } } }
PHP示例用法
$c = new Cipher("12345"); $encrypted = $c->encrypt("hello"); echo 'Encrypted: ' . $encrypted . '<br />'; $decrypted = $c->decrypt($encrypted); echo 'Decrypted: ' . $decrypted . '<br />'; $vb = "MwBOAEoAOQBjAEgAcQAyAC8ASABzAD0ALABmAEUAOQBaAHYAVwBzAFUAYQB3AFYARwBGAHUANABLAGUAVgB3AFcAaABRAD0APQA="; echo 'VB.NET Dec: ' . $c->decrypt($vb);
上面我在PHP中使用的内容是用VB.NET编写的Base64字符串,它在VB.NET中将PERFECTLY解码为变量$vb.
这让我非常沮丧,因为代码是正确的,并且功能正常 – 在两种情况下 – 所以我错过了什么,你能指出/解决问题.我不希望使用Rijndael,或者探索其他密码方法,因为这个方法很好,可以在多个设备上本地工作(iOS,Android,Windows,Linux等).
由于没有人能够提供功能齐全的BI-DIRECTIONAL解决方案,我已经冒昧地在本文中为社区提供了一个解决方案.问题是,PHP不符合标准,强制填充字符串以便匹配.目前,如果在.NET和PHP之间随机生成,没有已知的方法可靠地传递IV(如果你确实发现了如何或者这种变化,请随时修改它).
以下是使用Triple DES加密数据的COMPLETE解决方案,其方式与.NET和PHP兼容,允许双向三重DES加密通信.此方法也与Java,Delphi,Objective-C和许多其他语言兼容,但此类代码不会在此处提供,因为这不是已发布问题的解决方案.
VB.NET Triple DES Class
Imports System Imports System.Text Imports System.IO Imports System.Security.Cryptography Public Class TripleDES Private bPassword As Byte() Private sPassword As String Public Sub New(Optional ByVal Password As String = "password") ' On Class Begin Me.Password = Password End Sub Public ReadOnly Property PasswordHash As String Get Dim UTF8 As System.Text.UTF8Encoding = New System.Text.UTF8Encoding Return UTF8.GetString(bPassword) End Get End Property Public Property Password() As String Get Dim UTF8 As System.Text.UTF8Encoding = New System.Text.UTF8Encoding Return sPassword End Get Set(value As String) Dim UTF8 As System.Text.UTF8Encoding = New System.Text.UTF8Encoding Dim HashProvider As MD5CryptoServiceProvider = New MD5CryptoServiceProvider() bPassword = HashProvider.ComputeHash(UTF8.GetBytes(value)) sPassword = value End Set End Property #Region "Encrypt" ' Encrypt using Password from Property Set (pre-hashed) Public Function Encrypt(ByVal Message As String) As String Dim Results() As Byte Dim UTF8 As System.Text.UTF8Encoding = New System.Text.UTF8Encoding Using HashProvider As MD5CryptoServiceProvider = New MD5CryptoServiceProvider() Dim TDESKey() As Byte = bPassword Using TDESAlgorithm As TripleDESCryptoServiceProvider = New TripleDESCryptoServiceProvider() With {.Key = TDESKey, .Mode = CipherMode.ECB, .Padding = PaddingMode.PKCS7} Dim DataToEncrypt() As Byte = UTF8.GetBytes(Message) Try Dim Encryptor As ICryptoTransform = TDESAlgorithm.CreateEncryptor Results = Encryptor.TransformFinalBlock(DataToEncrypt, 0, DataToEncrypt.Length) Finally TDESAlgorithm.Clear() HashProvider.Clear() End Try End Using End Using Return Convert.ToBase64String(Results) End Function ' Encrypt using Password as byte array Private Function Encrypt(ByVal Message As String, ByVal Password() As Byte) As String Dim Results() As Byte Dim UTF8 As System.Text.UTF8Encoding = New System.Text.UTF8Encoding Using HashProvider As MD5CryptoServiceProvider = New MD5CryptoServiceProvider() Dim TDESKey() As Byte = HashProvider.ComputeHash(UTF8.GetBytes(UTF8.GetString(Password))) Using TDESAlgorithm As TripleDESCryptoServiceProvider = New TripleDESCryptoServiceProvider() With {.Key = TDESKey, .Mode = CipherMode.ECB, .Padding = PaddingMode.PKCS7} Dim DataToEncrypt() As Byte = UTF8.GetBytes(Message) Try Dim Encryptor As ICryptoTransform = TDESAlgorithm.CreateEncryptor Results = Encryptor.TransformFinalBlock(DataToEncrypt, 0, DataToEncrypt.Length) Finally TDESAlgorithm.Clear() HashProvider.Clear() End Try End Using End Using Return Convert.ToBase64String(Results) End Function ' Encrypt using Password as string Public Function Encrypt(ByVal Message As String, ByVal Password As String) As String Dim Results() As Byte Dim UTF8 As System.Text.UTF8Encoding = New System.Text.UTF8Encoding ' Step 1. We hash the Passphrase using MD5 ' We use the MD5 hash generator as the result is a 128 bit byte array ' which is a valid length for the Triple DES encoder we use below Using HashProvider As MD5CryptoServiceProvider = New MD5CryptoServiceProvider() Dim TDESKey() As Byte = HashProvider.ComputeHash(UTF8.GetBytes(Password)) ' Step 2. Create a new TripleDESCryptoServiceProvider object ' Step 3. Setup the encoder Using TDESAlgorithm As TripleDESCryptoServiceProvider = New TripleDESCryptoServiceProvider() With {.Key = TDESKey, .Mode = CipherMode.ECB, .Padding = PaddingMode.PKCS7} ' Step 4. Convert the input string to a byte[] Dim DataToEncrypt() As Byte = UTF8.GetBytes(Message) ' Step 5. Attempt to encrypt the string Try Dim Encryptor As ICryptoTransform = TDESAlgorithm.CreateEncryptor Results = Encryptor.TransformFinalBlock(DataToEncrypt, 0, DataToEncrypt.Length) Finally ' Clear the Triple Des and Hashprovider services of any sensitive information TDESAlgorithm.Clear() HashProvider.Clear() End Try End Using End Using ' Step 6. Return the encrypted string as a base64 encoded string Return Convert.ToBase64String(Results) End Function #End Region #Region "Decrypt" ' Decrypt using Password from Property (pre-hashed) Public Function Decrypt(ByVal Message As String) As String Dim Results() As Byte Dim UTF8 As System.Text.UTF8Encoding = New System.Text.UTF8Encoding Using HashProvider As MD5CryptoServiceProvider = New MD5CryptoServiceProvider() Dim TDESKey() As Byte = Me.bPassword Using TDESAlgorithm As TripleDESCryptoServiceProvider = New TripleDESCryptoServiceProvider() With {.Key = TDESKey, .Mode = CipherMode.ECB, .Padding = PaddingMode.PKCS7} Dim DataToDecrypt() As Byte = Convert.FromBase64String(Message) Try Dim Decryptor As ICryptoTransform = TDESAlgorithm.CreateDecryptor Results = Decryptor.TransformFinalBlock(DataToDecrypt, 0, DataToDecrypt.Length) Finally TDESAlgorithm.Clear() HashProvider.Clear() End Try End Using End Using Return UTF8.GetString(Results) End Function ' Decrypt using Password as Byte array Public Function Decrypt(ByVal Message As String, ByVal Password() As Byte) As String Dim Results() As Byte Dim UTF8 As System.Text.UTF8Encoding = New System.Text.UTF8Encoding Using HashProvider As MD5CryptoServiceProvider = New MD5CryptoServiceProvider() Dim TDESKey() As Byte = HashProvider.ComputeHash(UTF8.GetBytes(UTF8.GetString(Password))) Using TDESAlgorithm As TripleDESCryptoServiceProvider = New TripleDESCryptoServiceProvider() With {.Key = TDESKey, .Mode = CipherMode.ECB, .Padding = PaddingMode.PKCS7} Dim DataToDecrypt() As Byte = Convert.FromBase64String(Message) Try Dim Decryptor As ICryptoTransform = TDESAlgorithm.CreateDecryptor Results = Decryptor.TransformFinalBlock(DataToDecrypt, 0, DataToDecrypt.Length) Finally TDESAlgorithm.Clear() HashProvider.Clear() End Try End Using End Using Return UTF8.GetString(Results) End Function ' Decrypt using Password as string Public Function Decrypt(ByVal Message As String, ByVal Password As String) As String Dim Results() As Byte Dim UTF8 As System.Text.UTF8Encoding = New System.Text.UTF8Encoding ' Step 1. We hash the pass phrase using MD5 ' We use the MD5 hash generator as the result is a 128-bit byte array ' which is a valid length for the Triple DES encoder we use below Using HashProvider As MD5CryptoServiceProvider = New MD5CryptoServiceProvider() Dim TDESKey() As Byte = HashProvider.ComputeHash(UTF8.GetBytes(Password)) ' Step 2. Create a new TripleDESCryptoServiceProvider object ' Step 3. Setup the decoder Using TDESAlgorithm As TripleDESCryptoServiceProvider = New TripleDESCryptoServiceProvider() With {.Key = TDESKey, .Mode = CipherMode.ECB, .Padding = PaddingMode.PKCS7} ' Step 4. Convert the input string to a byte[] Dim DataToDecrypt() As Byte = Convert.FromBase64String(Message) ' Step 5. Attempt to decrypt the string Try Dim Decryptor As ICryptoTransform = TDESAlgorithm.CreateDecryptor Results = Decryptor.TransformFinalBlock(DataToDecrypt, 0, DataToDecrypt.Length) Finally ' Clear the Triple Des and Hash provider services of any sensitive information TDESAlgorithm.Clear() HashProvider.Clear() End Try End Using End Using ' Step 6. Return the decrypted string in UTF8 format Return UTF8.GetString(Results) End Function #End Region End Class
VB.NET Triple DES类用法
Dim tdes As New TripleDES("12345") Dim vbEncrypted = tdes.Encrypt("Encrypted using VB.NET") Dim phpEncrypted = "5Ittyr0+jiI7QQmPrvSVnMc9MEWQCjAN" Debug.Print("PHP Encrypted: " & phpEncrypted) Debug.Print("VB Encrypted: " & vbEncrypted) Debug.Print("PHP Encrypted (decrypted result): " & tdes.Decrypt(phpEncrypted)) Debug.Print("VB Encrypted (decrypted result): " & tdes.Decrypt(vbEncrypted))
PHP三重DES类
class TripleDES { private $bPassword; private $sPassword; function __construct($Password) { $this->bPassword = md5(utf8_encode($Password),TRUE); $this->bPassword .= substr($this->bPassword,0,8); $this->sPassword - $Password; } function Password($Password = "") { if($Password == "") { return $this->sPassword; } else { $this->bPassword = md5(utf8_encode($Password),TRUE); $this->bPassword .= substr($this->bPassword,0,8); $this->sPassword - $Password; } } function PasswordHash() { return $this->bPassword; } function Encrypt($Message, $Password = "") { if($Password <> "") { $this->Password($Password); } $size=mcrypt_get_block_size('tripledes','ecb'); $padding=$size-((strlen($Message)) % $size); $Message .= str_repeat(chr($padding),$padding); $encrypt = mcrypt_encrypt('tripledes',$this->bPassword,$Message,'ecb'); return base64_encode($encrypt); } function Decrypt($message, $Password = "") { if($Password <> "") { $this->Password($Password); } return trim(mcrypt_decrypt('tripledes', $this->bPassword, base64_decode($message), 'ecb'), ord(2)); } }
PHP Triple DES类用法
$tdes = new TripleDES("12345"); $phpEncrypted = $tdes->encrypt("Encrypted using PHP"); $vbEncrypted = "5Ittyr0+jiI7QQmPrvSVnP3s2CeoTJmF"; // Encrypted using VB.NET echo "PHP Encrypted: " . $phpEncrypted . '<br />'; echo "VB Encrypted: " . $vbEncrypted . '<br />'; echo "PHP Encrypted (decrypted result): " . $tdes->Decrypt($phpEncrypted) . '<br />'; echo "VB Encrypted (decrypted result): " . $tdes->Decrypt($vbEncrypted) . '<br />';
我尽我所能使两个类的可用性水平相同,因为语言自然允许.由于PHP不允许重载函数,我不得不使用密码作为可选参数,这是一个字符串值. VB.NET解决方案有一个额外的覆盖,允许您在加密/解密函数上传递密码字符串的字节值.提供示例代码以显示每个的用法,显示了实例化对象的最简单形式,两个类都允许在对象创建时设置密码.
对于其他任何人都在抨击他们的大脑试图找到一个三重DES的工作双向解决方案(并且不想被强制进入每个人似乎指向的方框 – Rijndael),那么这个解决方案是为你,你可以不停地撞到墙上.
添加了VB.NET TripleDES类的C#转换
C#类(已添加[2017-01-11])
using System; using System.Security.Cryptography; public class TripleDES { private byte[] bPassword; private string sPassword; public TripleDES( string Password = "password" ) { // On Class Begin this.Password = Password; } public string PasswordHash { get { System.Text.UTF8Encoding UTF8 = new System.Text.UTF8Encoding(); return UTF8.GetString( bPassword ); } } public string Password { get { System.Text.UTF8Encoding UTF8 = new System.Text.UTF8Encoding(); return sPassword; } set { System.Text.UTF8Encoding UTF8 = new System.Text.UTF8Encoding(); MD5CryptoServiceProvider HashProvider = new MD5CryptoServiceProvider(); bPassword = HashProvider.ComputeHash( UTF8.GetBytes( value ) ); sPassword = value; } } #region "Encrypt" // Encrypt using Password from Property Set (pre-hashed) public string Encrypt( string Message ) { byte[] Results = null; System.Text.UTF8Encoding UTF8 = new System.Text.UTF8Encoding(); using ( MD5CryptoServiceProvider HashProvider = new MD5CryptoServiceProvider() ) { byte[] TDESKey = bPassword; using ( TripleDESCryptoServiceProvider TDESAlgorithm = new TripleDESCryptoServiceProvider { Key = TDESKey, Mode = CipherMode.ECB, Padding = PaddingMode.PKCS7 } ) { byte[] DataToEncrypt = UTF8.GetBytes( Message ); try { ICryptoTransform Encryptor = TDESAlgorithm.CreateEncryptor(); Results = Encryptor.TransformFinalBlock( DataToEncrypt, 0, DataToEncrypt.Length ); } finally { TDESAlgorithm.Clear(); HashProvider.Clear(); } } } return Convert.ToBase64String( Results ); } // Encrypt using Password as byte array private string Encrypt( string Message, byte[] Password ) { byte[] Results = null; System.Text.UTF8Encoding UTF8 = new System.Text.UTF8Encoding(); using ( MD5CryptoServiceProvider HashProvider = new MD5CryptoServiceProvider() ) { byte[] TDESKey = HashProvider.ComputeHash( UTF8.GetBytes( UTF8.GetString( Password ) ) ); using ( TripleDESCryptoServiceProvider TDESAlgorithm = new TripleDESCryptoServiceProvider { Key = TDESKey, Mode = CipherMode.ECB, Padding = PaddingMode.PKCS7 } ) { byte[] DataToEncrypt = UTF8.GetBytes( Message ); try { ICryptoTransform Encryptor = TDESAlgorithm.CreateEncryptor(); Results = Encryptor.TransformFinalBlock( DataToEncrypt, 0, DataToEncrypt.Length ); } finally { TDESAlgorithm.Clear(); HashProvider.Clear(); } } } return Convert.ToBase64String( Results ); } // Encrypt using Password as string public string Encrypt( string Message, string Password ) { byte[] Results = null; System.Text.UTF8Encoding UTF8 = new System.Text.UTF8Encoding(); // Step 1. We hash the Passphrase using MD5 // We use the MD5 hash generator as the result is a 128 bit byte array // which is a valid length for the Triple DES encoder we use below using ( MD5CryptoServiceProvider HashProvider = new MD5CryptoServiceProvider() ) { byte[] TDESKey = HashProvider.ComputeHash( UTF8.GetBytes( Password ) ); // Step 2. Create a new TripleDESCryptoServiceProvider object // Step 3. Setup the encoder using ( TripleDESCryptoServiceProvider TDESAlgorithm = new TripleDESCryptoServiceProvider { Key = TDESKey, Mode = CipherMode.ECB, Padding = PaddingMode.PKCS7 } ) { // Step 4. Convert the input string to a byte[] byte[] DataToEncrypt = UTF8.GetBytes( Message ); // Step 5. Attempt to encrypt the string try { ICryptoTransform Encryptor = TDESAlgorithm.CreateEncryptor(); Results = Encryptor.TransformFinalBlock( DataToEncrypt, 0, DataToEncrypt.Length ); } finally { // Clear the Triple Des and Hashprovider services of any sensitive information TDESAlgorithm.Clear(); HashProvider.Clear(); } } } // Step 6. Return the encrypted string as a base64 encoded string return Convert.ToBase64String( Results ); } #endregion #region "Decrypt" // Decrypt using Password from Property (pre-hashed) public string Decrypt( string Message ) { byte[] Results = null; System.Text.UTF8Encoding UTF8 = new System.Text.UTF8Encoding(); using ( MD5CryptoServiceProvider HashProvider = new MD5CryptoServiceProvider() ) { byte[] TDESKey = this.bPassword; using ( TripleDESCryptoServiceProvider TDESAlgorithm = new TripleDESCryptoServiceProvider { Key = TDESKey, Mode = CipherMode.ECB, Padding = PaddingMode.PKCS7 } ) { byte[] DataToDecrypt = Convert.FromBase64String( Message ); try { ICryptoTransform Decryptor = TDESAlgorithm.CreateDecryptor(); Results = Decryptor.TransformFinalBlock( DataToDecrypt, 0, DataToDecrypt.Length ); } finally { TDESAlgorithm.Clear(); HashProvider.Clear(); } } } return UTF8.GetString( Results ); } // Decrypt using Password as Byte array public string Decrypt( string Message, byte[] Password ) { byte[] Results = null; System.Text.UTF8Encoding UTF8 = new System.Text.UTF8Encoding(); using ( MD5CryptoServiceProvider HashProvider = new MD5CryptoServiceProvider() ) { byte[] TDESKey = HashProvider.ComputeHash( UTF8.GetBytes( UTF8.GetString( Password ) ) ); using ( TripleDESCryptoServiceProvider TDESAlgorithm = new TripleDESCryptoServiceProvider { Key = TDESKey, Mode = CipherMode.ECB, Padding = PaddingMode.PKCS7 } ) { byte[] DataToDecrypt = Convert.FromBase64String( Message ); try { ICryptoTransform Decryptor = TDESAlgorithm.CreateDecryptor(); Results = Decryptor.TransformFinalBlock( DataToDecrypt, 0, DataToDecrypt.Length ); } finally { TDESAlgorithm.Clear(); HashProvider.Clear(); } } } return UTF8.GetString( Results ); } // Decrypt using Password as string public string Decrypt( string Message, string Password ) { byte[] Results = null; System.Text.UTF8Encoding UTF8 = new System.Text.UTF8Encoding(); // Step 1. We hash the pass phrase using MD5 // We use the MD5 hash generator as the result is a 128-bit byte array // which is a valid length for the Triple DES encoder we use below using ( MD5CryptoServiceProvider HashProvider = new MD5CryptoServiceProvider() ) { byte[] TDESKey = HashProvider.ComputeHash( UTF8.GetBytes( Password ) ); // Step 2. Create a new TripleDESCryptoServiceProvider object // Step 3. Setup the decoder using ( TripleDESCryptoServiceProvider TDESAlgorithm = new TripleDESCryptoServiceProvider { Key = TDESKey, Mode = CipherMode.ECB, Padding = PaddingMode.PKCS7 } ) { // Step 4. Convert the input string to a byte[] byte[] DataToDecrypt = Convert.FromBase64String( Message ); // Step 5. Attempt to decrypt the string try { ICryptoTransform Decryptor = TDESAlgorithm.CreateDecryptor(); Results = Decryptor.TransformFinalBlock( DataToDecrypt, 0, DataToDecrypt.Length ); } finally { // Clear the Triple Des and Hash provider services of any sensitive information TDESAlgorithm.Clear(); HashProvider.Clear(); } } } // Step 6. Return the decrypted string in UTF8 format return UTF8.GetString( Results ); } #endregion }