最近用到這個東西, 是說密碼學從來沒學過, 只好尋求估狗大師XD
PHP範例程式碼:
轉自 http://www.sanity-free.com/131/triple_des_between_php_and_csharp.html
--
內文:
The past while at work I've been working through some annoyingly overcomplicated encryption issues. The problem is not that Triple DES is all that complicated or annoying, it's just that when you have 2 different technologies (one doing the encrypting and one doing the decrypting) at work; it can be frustrating to get anything accomplished.
Our issues stemmed around the fact that we were using .NET 1.1 and they were using Java (with the standard crypto providers). There are a few subtleties between Microsoft's crypto providers and Java's. .NET provides 3 (ok, really only 2) Padding modes, and Java provides like 5, but they don't provide any in common. One easy padding mode is to append 0x00 bytes to the end of the final block to make it an even 64 bits wide. The Java provider didn't have this, but its easy enough to add ( by appending null char's '\0' to the end of the string then calling getBytes() ). So that's the route we took. After overcoming a few problems with "How do we encode our bytes used for the key and IV and still be compatible" we were off and running.
That made me wonder how compatible PHP and .NET's 3DES were. Since I didn't see any "Padding Mode" for PHP's, I simply hand coded the padding the same way we did with the Java code.
Here's my php script:
<?php if(!isset($_POST['op'])) { ?> <form id="form1" name="form1" method="post" action=""> enter text <input name="data" type="text" /> <input type="hidden" value="op" name="op" /> <input type="submit" name="Submit" value="Submit" /> </form> <?php }else { $buffer = $_POST['data']; // get the amount of bytes to pad $extra = 8 - (strlen($buffer) % 8); // add the zero padding if($extra > 0) { for($i = 0; $i < $extra; $i++) { $buffer .= "\0"; } } // very simple ASCII key and IV $key = "passwordDR0wSS@P6660juht"; $iv = "password"; // hex encode the return value echo "Result: ".bin2hex(mcrypt_cbc(MCRYPT_3DES, $key, $buffer, MCRYPT_ENCRYPT, $iv)); } ?>
Then entered in my text (in this case I used "Test" in both)
Then I wrote up a sample in .NET to try to see if we had to massage the data or not:
using System; using System.Security.Cryptography; using System.Text; using System.IO; namespace TestBed { class Program { static void Main(string[] args) { byte[] key = Encoding.ASCII.GetBytes("passwordDR0wSS@P6660juht"); byte[] iv = Encoding.ASCII.GetBytes("password"); byte[] data = Encoding.ASCII.GetBytes("Test"); byte[] enc = new byte[0]; TripleDES tdes = TripleDES.Create(); tdes.IV = iv; tdes.Key = key; tdes.Mode = CipherMode.CBC; tdes.Padding = PaddingMode.Zeros; ICryptoTransform ict = tdes.CreateEncryptor(); enc = ict.TransformFinalBlock(data, 0, data.Length); Console.WriteLine(Bin2Hex(enc)); Console.ReadLine(); } // my bin2hex implementation static string Bin2Hex(byte[] bin) { StringBuilder sb = new StringBuilder(bin.Length * 2); foreach(byte b in bin) { sb.Append(b.ToString("x").PadLeft(2, '0')); } return sb.ToString(); } } }
"47794945c0230c3d" Wouldn't you know it! It worked like a charm!
Would have been nice if the Java -> .NET solution had been that easy.
For those looking for an example of both encryption and decryption of 3des, check out a user submitted post on the forums here
--
解決key值位數過長的問題:
轉自 http://topic.csdn.net/u/20111128/14/b65b371c-5ee9-4c9a-8873-0b244703a40b.html
--
內文:
网上找的一个。
执行encrypt 3des加密就会报错,
Warning: mcrypt_generic_init() [function.mcrypt-generic-init]: Key size too large; supplied length: 36, max: 24 in D:\AppServ\www\api\3des.php on line 29
加密出来的和Java 加密出来的也不一样。
3DES加密算法:密钥长度不足24字节时,右补ASCII字符“0”;内容采用PKCS5Padding方式填充,即长度以8字节切分,不能被8整除的末尾部分,根据长度不足8字节的部分,填充“0x01”—“0x08”,如不足1字节,则填充1个“0x01”,如不足2字节,则填充2个“0x02”,以此类推,如整除,则填充8个“0x08”
PHP内置的mcrypt库支持多种块状加密算法,包括DES,3DES和Blowfish(默认算法)等。由于是块状加密(Block Ciper),mcrypt支持以下模式对输入字符串进行操作:CBC, OFB, CFB和ECB。
php
3des key的长度为24字节,iv为8字节.
如果提供的key为48位,可以用pack("H48", $key) , 同理iv也可以用pack("H16", $iv);
如果提供的key为32位,可以用base64_decode解码,正好也是24位.
- PHP code
-
function pkcs5_pad($text, $blocksize) { $pad = $blocksize - (strlen($text) % $blocksize); return $text . str_repeat(chr($pad), $pad); } function pkcs5_unpad($text) { $pad = ord($text{strlen($text)-1}); if ($pad > strlen($text)) { return false; } if( strspn($text, chr($pad), strlen($text) - $pad) != $pad) { return false; } return substr($text, 0, -1 * $pad); } $key = "20C86125F86DB932D0139D32D9208CEF52BAEC98F1E9BA2A"; $key = pack("H48", $key); $iv = "0102030405060708"; $iv = pack("H16", $iv); $td = mcrypt_module_open(MCRYPT_3DES, '', MCRYPT_MODE_CBC, ''); mcrypt_generic_init($td, $key, $iv); $str = base64_encode(mcrypt_generic($td,pkcs5_pad("helloworld",8))); echo $str .""; mcrypt_generic_deinit($td); mcrypt_module_close($td); $td = mcrypt_module_open(MCRYPT_3DES, '', MCRYPT_MODE_CBC, ''); mcrypt_generic_init($td, $key, $iv); $ttt = pkcs5_unpad(mdecrypt_generic($td, base64_decode($str))); mcrypt_generic_deinit($td); mcrypt_module_close($td);
--