翻墙代理的加密部分
就是怎么在 PHP/mcrypt 和 PyCrypto 之间 DES(或其他加密算法,比如3DES/RSA/..) 通信的问题,我这里还额外考察了下 .NET 平台的算法
网上询问相关问题的还挺多,尤其是 PHP 和 .NET 之间的 DES 转换。主要是 PHP/mcrypt 隐藏了 padding 的细节,且只保留了 ZERO_PADDING 模式,所以不明白cyrpto原理的不太容易找到症结所在。我的传输方案统一用 pkcs#7 padding.
首先是给服务器端增加的 PKCS#7 PADDING 函数,来自PHP官方函数手册上某人的注释
-
function padding_pkcs7($crypto, $mode, $dat)
-
{
-
$block = mcrypt_get_block_size($crypto, $mode);
-
$len = strlen($dat);
-
$padding = $block - ($len % $block);
-
$dat .= str_repeat(chr($padding),$padding);
-
return $dat;
-
}
-
-
function strip_pkcs7($crypto, $mode, $text)
-
{
-
$block = mcrypt_get_block_size($crypto, $mode);
-
$packing = ord($text{strlen($text) - 1});
-
if($packing and ($packing < $block)){
-
for($P = strlen($text) - 1; $P >= strlen($text) - $packing; $P--){
-
if(ord($text{$P}) != $packing){
-
$packing = 0;
-
}
-
}
-
}
-
return substr($text,0,strlen($text) - $packing);
-
}
本地端 .NET 平台的 descrypto 封装
-
# -*- coding: utf-8 -*-
-
# ipcrypto.py
-
from System import Array, Byte
-
from System.Security.Cryptography import DESCryptoServiceProvider, CryptoStream, CryptoStreamMode, PaddingMode
-
from System.IO import MemoryStream, StreamWriter, StreamReader
-
-
from hashlib import md5
-
-
def s2ab(s):
-
return Array[Byte](tuple(Byte(ord(c)) for c in s))
-
-
def ab2s(ab, len=0):
-
if len == 0: len = ab.Length
-
return ''.join([chr(ab[i]) for i in range(len)])
-
-
class descrypto():
-
def __init__(self, password):
-
pwmd5 = md5(password).digest()
-
self.key = s2ab(pwmd5[:8])
-
self.iv = s2ab(pwmd5[8:])
-
self.des = DESCryptoServiceProvider() # 缺省 des.Mode = CipherMode.CBC
-
-
def enc(self, input):
-
ms = MemoryStream()
-
encStream = CryptoStream(ms, self.des.CreateEncryptor(self.key, self.iv), CryptoStreamMode.Write)
-
sw = StreamWriter(encStream)
-
sw.Write(input)
-
sw.Flush()
-
encStream.FlushFinalBlock()
-
return ab2s(ms.GetBuffer(), ms.Length)
-
-
def dec(self, input):
-
ms = MemoryStream(s2ab(input))
-
length = len(input)
-
decStream = CryptoStream(ms, self.des.CreateDecryptor(self.key, self.iv), CryptoStreamMode.Read)
-
byteArray = Array.CreateInstance(Byte, length)
-
length = decStream.Read(byteArray, 0, length)
-
return ab2s(byteArray, length)
本地端 PyCrypto 的封装
-
# -*- coding: utf-8 -*-
-
# pycrypto.py
-
from hashlib import md5
-
from Crypto.Cipher import DES
-
-
class descrypto():
-
def __init__(self, password):
-
pwmd5 = md5(password).digest()
-
self.key = pwmd5[:8]
-
self.iv = pwmd5[8:]
-
-
def enc(self, input):
-
des = DES.new(self.key, DES.MODE_CBC, self.iv)
-
lastblock = len(input) % 8
-
if lastblock > 0:
-
padding = 8 - lastblock
-
input += padding * chr(padding)
-
-
return des.encrypt(input)
-
-
def dec(self, input):
-
des = DES.new(self.key, DES.MODE_CBC, self.iv)
-
ret = des.decrypt(input)
-
padding = ord(ret[-1])
-
for i in range(padding):
-
if ord(ret[-1 - i]) != padding:
-
padding = 0
-
break
-
if padding > 0:
-
ret = ret[:-padding]
-
return ret
最新评论