IT技术博客大学习 共学习 共进步

代理的加密部分

BT的花 blogs 2010-04-01 08:51:34 浏览 8,244 次

就是怎么在 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

建议继续学习

  1. 让安卓手机通过代理翻墙的方法 (阅读 8,801)
  2. 网址加密(URL加密)(RC4、PHP、密钥长度可变) (阅读 8,001)
  3. 关于 SOCKS 代理的远端 DNS 解析 (阅读 7,743)
  4. 使用bcompiler对PHP文件进行加密 (阅读 5,381)
  5. 在浏览器中加密Cookie (阅读 5,382)
  6. 使用系统命令实现文件的压缩与加密 (阅读 5,184)
  7. 公钥私钥加密解密数字证书数字签名详解 (阅读 5,122)
  8. HTTP 正向代理与反向代理 (阅读 4,980)
  9. 关于不得不在python中使用代理访问网络的方法 (阅读 4,941)
  10. 加密你的shell (阅读 4,845)