2016-05-26 107 views
1

我已经从第三方获得了一组需要加密/解密的代码,但他们给我的示例加密代码是在C#中,我主要是前端PHP开发人员。在PHP中复制C#加密/解密

我已经设置了一个精简的工作示例代码,我提供的代码是 here使用A818163DD5E0DE87的示例键。

public static byte[] HexStringToByteArray(String hex) 
{ 
int NumberChars = hex.Length; 
byte[] bytes = new byte[NumberChars/2]; 
for (int i = 0; i < NumberChars; i += 2) { 
bytes[i/2] = Convert.ToByte(hex.Substring(i, 2), 16); 
} 
return bytes; 
} 

// Convers a byte array to a HEX string 
public static string ByteArrayToHexString(byte[] bytes) 
{ 
StringBuilder hexString = new StringBuilder(bytes.Length * 2); 
for (int i = 0; i < bytes.Length; i++) 
{ 
hexString.Append(bytes[i].ToString("X2")); 
} 
return hexString.ToString(); 
} 

public static byte[] Encrypt() 
{ 
string plainText = "GROW06BP"; 
DESCryptoServiceProvider desCrypto = new DESCryptoServiceProvider(); 
desCrypto.Key = HexStringToByteArray("A818163DD5E0DE87"); 
desCrypto.IV = HexStringToByteArray("A818163DD5E0DE87"); 
desCrypto.Mode = CipherMode.CBC; 
desCrypto.Padding = PaddingMode.Zeros; 
// Create a buffer for the Plain Text using ASCIIEncoding 
byte[] plaintextBytes = (new ASCIIEncoding()).GetBytes(plainText); 
// Create a memory stream for the encrypted bytes 
MemoryStream msEncrypt = new MemoryStream(); 
// Create a CryptoStream using the memory stream and the passed Algorithm 
CryptoStream csEncrypt = new CryptoStream(msEncrypt, desCrypto.CreateEncryptor(), CryptoStreamMode.Write); 
// Write the plaintext to the CryptoStream 
csEncrypt.Write(plaintextBytes, 0, plaintextBytes.Length); 
// Close the CryptoStream 
csEncrypt.Close(); 
// Read the Encrypted bytes into our buffer 
byte[] encryptedTextBytes = msEncrypt.ToArray(); 
// Close the Memory Stream 
msEncrypt.Close(); 
// And return the encrypted buffer 
return encryptedTextBytes; 
} 

我已经搜查堆栈溢出和其他网站,试图在PHP中复制这个,但没有接近正确的输出。我也对我打算使用哪种密码以及如何转换密钥和iv以匹配C#示例感到困惑。以下是我迄今为止所尝试的内容。

$key = unpack('H*', "A818163DD5E0DE87"); 
$key = "A818163DD5E0DE87"; 
$iv = $key; 
$plaintext = "GROW06BP"; 
$ciphertext = mcrypt_encrypt(MCRYPT_RIJNDAEL_128, $key, $plaintext,MCRYPT_MODE_CBC, $iv); 
echo base64_encode($ciphertext); 

任何帮助,将不胜感激。你需要

+2

在C#中你使用DES相同的,但在PHP您正在使用Rijndael算法(AES)。他们是不同的加密算法! – Nasreddine

回答

0

需要考虑的事情:

  • DESCryptoServiceProvider - > mcrypt_module_open( 'DES'
  • desCrypto.Mode = CipherMode.CBC; - > mcrypt_module_open(...,..., 'CBC' ,
  • 键,IV和加密输出的“经处理的”与HexStringToByteArray(),pack('H*)可以撤消

因此,考虑到达网络的输出导致小提琴(7860D97E56DA6A40)到

<?php 
$msgHex = '7860D97E56DA6A40'; 
$keyHex = 'A818163DD5E0DE87'; 
$ivHex = 'A818163DD5E0DE87'; // really? invalidates the use-case of an iv :-/ 

// this reverts the effect of HexStringToByteArray() 
$msg = pack('H*', $msgHex); 
$key = pack('H*', $keyHex); 
$iv = pack('H*', $ivHex); 

// add error handing ! 
$module = mcrypt_module_open('des', '', 'cbc', ''); 
mcrypt_generic_init($module, $key, $iv); 
$plaintext = mdecrypt_generic($module, $msg); 
mcrypt_generic_deinit($module); 

echo $plaintext; 

输出:GROW06BP

+0

非常感谢VolkerK,这使我能够成功解密代码。我不认为我会这样做,因为我在搜索时没有遇到这些功能。 –

0

正如我在我的评论已经提到的,你使用了错误的算法在你的PHP代码,因为它的Rijndael算法。你应该使用的是MCRYPT_DES

$key = "A818163DD5E0DE87"; 
// Here you need pack instead of unpack 
$packKey = pack("H*",$key); 
// you should use the key as the initialization vector 
// use something like mcrypt_create_iv to generate an IV 
$iv = $packKey; 
$plaintext = "GROW06BP"; 
// replaced MCRYPT_RIJNDAEL_128 with MCRYPT_DES 
$ciphertext = mcrypt_encrypt(MCRYPT_DES, $packKey, $plaintext,MCRYPT_MODE_CBC, $iv); 
echo base64_encode($ciphertext); 

这将产生输出的C#代码

+0

感谢您的帮助Nasreddine。你的代码对我来说看起来很不错,但似乎向C#代码输出了一个不同的结果,这就是我很多困惑所产生的结果。 –