微信小程式及各種平臺對接常用可逆加密演算法aes256

冷侃發表於2018-09-26

不同程式之間經常會交換資料,我們經常採用的套路是:

假設要傳輸的資訊是json,我們假設其為json_data,通過http傳遞資訊為

json_data_encode=json_data&sign=md5(json_data+key)

接收方通過驗證sign就知道內容有沒有被篡改.

但是,這樣json_data作為明碼傳送會讓我們不太開心,所以今天的我們要介紹的aes256出馬了,他是一強度很高的可逆加密演算法!

aes256加密出來的內容是二進位制的,不好通過http協議傳輸,所以我們再配合上base64轉成ascii碼

加密前,aes256要求位元組數必須是32位元組的倍數,所以使用pkcs7進行填充可以解決問題..介紹完原理,直接貼程式碼

寫了3個版本,openresty及python和php的...請查收

local aes = require 'resty.aes'
 local base64_encode = ngx.encode_base64
 local base64_decode = ngx.decode_base64
 
 local key = "a12e93c9edadeaa47eb1aeabe27dabef"
 local iv = "a12e93c9edadeaa4"
 -- AES 128 CBC with IV and no SALT
 local cipher = aes.cipher(256,"cbc")
 local aes_256_cbc_with_iv = aes:new(key,nil,cipher,{iv=iv})
 
 local function decrypt(input)
     input = base64_decode(input)
     input = aes_256_cbc_with_iv:decrypt(input)
     -- 取最後一個字元的ascii值
     --local padding = string.byte(input,-1)
     --return string.sub(input,-padding)
     return input
 end
 
 local function pkcs7_padding(text)
     local text_length = string.len(text)
     local amount_to_pad = 32 - (text_length % 32)
 
     if amount_to_pad == 0 then
         amount_to_pad = 32
     end
     local pad = string.char(amount_to_pad) return text .. string.rep(pad,amount_to_pad)
 end
 
 local function encrypt (text)
     text = pkcs7_padding(text)
     text = aes_256_cbc_with_iv:encrypt(text)
     return base64_encode(text)
 end
 
 print(decrypt(encrypt('linbc')))

接著是python版本的

#!/usr/bin/env python
# -*- coding: utf-8 -*-

import base64

from Crypto.Cipher import AES


import binascii
import StringIO

class PKCS7Encoder(object):
    '''
    RFC 2315: PKCS#7 page 21
    Some content-encryption algorithms assume the
    input length is a multiple of k octets, where k > 1, and
    let the application define a method for handling inputs
    whose lengths are not a multiple of k octets. For such
    algorithms, the method shall be to pad the input at the
    trailing end with k - (l mod k) octets all having value k -
    (l mod k), where l is the length of the input. In other
    words, the input is padded at the trailing end with one of
    the following strings:

             01 -- if l mod k = k-1
            02 02 -- if l mod k = k-2
                        .
                        .
                        .
          k k ... k k -- if l mod k = 0

    The padding can be removed unambiguously since all input is
    padded and no padding string is a suffix of another. This
    padding method is well-defined if and only if k < 256;
    methods for larger k are an open issue for further study.
    '''
    def __init__(self, k=16):
        self.k = k

    ## @param text The padded text for which the padding is to be removed.
    # @exception ValueError Raised when the input padding is missing or corrupt.
    def decode(self, text):
        '''
        Remove the PKCS#7 padding from a text string
        '''
        nl = len(text)
        val = int(binascii.hexlify(text[-1]), 16)

        if val > self.k:
            raise ValueError('Input is not padded or padding is corrupt')

        l = nl - val

        return text[:l]

    ## @param text The text to encode.
    def encode(self, text):
        '''
        Pad an input string according to PKCS#7
        '''
        l = len(text)
        output = StringIO.StringIO()
        val = self.k - (l % self.k)

        for _ in xrange(val):
            output.write('%02x' % val)

        return text + binascii.unhexlify(output.getvalue())



# 使用256位的AES,Python會根據傳入的Key長度自動選擇,長度為16時使用128位的AES
key = 'a12e93c9edadeaa47eb1aeabe27dabef'
mode = AES.MODE_CBC
#iv = '1234567812345678'  # AES的CBC模式使用IV
iv = 'a12e93c9edadeaa4'  # AES的CBC模式使用IV

encoder = PKCS7Encoder()
text = "This is for test."

def encrypt(data):
    encryptor = AES.new(key, AES.MODE_CBC, iv)
    padded_text = encoder.encode(data)
    encrypted_data = encryptor.encrypt(padded_text)

    return base64.b64encode(encrypted_data)

def decrypt(data):
    cipher = base64.b64decode(data)
    decryptor = AES.new(key, AES.MODE_CBC, iv)
    plain = decryptor.decrypt(cipher)

    return encoder.decode(plain)

#encrypted_text = encrypt(text)
encrypted_text = 'MD1ZOvuyvut4VEed4rf+8YKaOHyECJK/RWLcfVsJwjAEZp8Hhi1zi7oH3PLSygjFCAxCRJqMBzm/qhreznkg34Vgbho+zwprTgl4M0c0lRkvLzWzXmSYG8pcqth1qnbNSwQeS3MPuofgVXR0SGMTIzicCXDlmwQV9uvIJekgES2LMse4pVndcrftI9f6UbIiT085DhAaiV9yGsV3r4FES+LnwP9ZNi58TButNC9owyKh9RuRn7z04LfNy++7iLjzk/HurOkBkJewHSchLER+pK94qhg6Lj8mW7dl+y5j3wbXY9SodNK+S8LDRYCa1JyZ/w8rffUK8YCY+jCT3ZmV8G5vdUENTqsrB4jX87C+XQCY9WEG+VQ5MK5XlhhvMPZyn2NLZUi6gW1HjqE6i/uefzq/LFl47cL2Hmr/cLbfI5rF+d1hMAIZGNnRxjYkVVvipEwRSlkD47ZVFLiWRKPusB7Lke3mnGJ1O+5eQnREL7Q/xpRT+3JuCcOqZIZJFFrJXMj9CXsJGMXxFkfnKT3UAhOi/lRA65Vwt1BEswHuZzLLHquyEYQMc3cOW1vy1Fv4zpYkjHYmxB1g50gwVryrEW2kY58sDdxwDYua3jLwERk='

clean_text = decrypt(encrypted_text)

print "encrypted_text:", encrypted_text
print "clean_text: ", clean_text

再來個php版本的

<?php

//function aes256EcbPkcs7PaddingEncrypt($key, $data) {
//    $padding = 16 - (strlen($data) % 16);
//    $data .= str_repeat(chr($padding), $padding);
//    return mcrypt_encrypt(MCRYPT_RIJNDAEL_256, hash('SHA256', $key, true), $data, MCRYPT_MODE_ECB);
//}
//
//function aes256EcbPkcs7PaddingDecrypt($key, $data) {
//    $data = mcrypt_decrypt(MCRYPT_RIJNDAEL_256, hash('SHA256', $key, true), $data, MCRYPT_MODE_ECB);
//    $padding = ord($data[strlen($data) - 1]); 
//    return substr($data, 0, -$padding); 
//}

$txt="MD1ZOvuyvut4VEed4rf+8YKaOHyECJK/RWLcfVsJwjAEZp8Hhi1zi7oH3PLSygjFCAxCRJqMBzm/qhreznkg34Vgbho+zwprTgl4M0c0lRkvLzWzXmSYG8pcqth1qnbNSwQeS3MPuofgVXR0SGMTIzicCXDlmwQV9uvIJekgES2LMse4pVndcrftI9f6UbIiT085DhAaiV9yGsV3r4FES+LnwP9ZNi58TButNC9owyKh9RuRn7z04LfNy++7iLjzk/HurOkBkJewHSchLER+pK94qhg6Lj8mW7dl+y5j3wbXY9SodNK+S8LDRYCa1JyZ/w8rffUK8YCY+jCT3ZmV8G5vdUENTqsrB4jX87C+XQCY9WEG+VQ5MK5XlhhvMPZyn2NLZUi6gW1HjqE6i/uefzq/LFl47cL2Hmr/cLbfI5rF+d1hMAIZGNnRxjYkVVvipEwRSlkD47ZVFLiWRKPusB7Lke3mnGJ1O+5eQnREL7Q/xpRT+3JuCcOqZIZJFFrJXMj9CXsJGMXxFkfnKT3UAhOi/lRA65Vwt1BEswHuZzLLHquyEYQMc3cOW1vy1Fv4zpYkjHYmxB1g50gwVryrEW2kY58sDdxwDYua3jLwERk=";
$txt=base64_decode($txt);
$key="a12e93c9edadeaa47eb1aeabe27dabef";
$iv ='a12e93c9edadeaa4';

$module = mcrypt_module_open(MCRYPT_RIJNDAEL_128, '', MCRYPT_MODE_CBC, '');
mcrypt_generic_init($module, $key, $iv);
$data = mdecrypt_generic($module, $txt);
mcrypt_generic_deinit($module);
mcrypt_module_close($module);

$padding = ord($data[strlen($data) - 1]); 
$result = substr($data, 0, -$padding); 
echo $result;

exit();

?>

 

php果然是...很省事的語言..看他多簡短啊.

相關文章