a场景是现有的几个项目,微信企业号是PHP,广告数据处理平台是Python,其中的Web API部分是NodeJS。现在这几个应用之间要传递数据,基于安全考虑先用AES加密,接收后做解密处理。本来预想是一个很简单的工作,库都是现成的,但发现网上的代码要么是不全,要么是padding处理不一致,所以最后还是自己看文档来写的,分享其中的核心代码,有类似需求可以直接拿去用。
AES
AES的介绍可以参看Wikipedia: 高级加密标准。这种加密方式需要指定Key(密钥)和IV(初始化向量),解密时使用同样的Key和IV进行解密。其次需要padding(填充字符),网上一些代码是用空格或者大括号做padding,解密后再用rstrip/rtrim/replace清掉,但用标准的PKCS会更好。
使用256位的AES,Python会根据传入的Key长度自动选择,在PHP5在mcrypt里是MCRYPT_RIJNDAEL_128,Nodejs/PHP7.1是aes-256-cbc。
使用AES的CBC模式,因为ECB模式用不到IV。
使用PKCS的方式来padding,因为NodeJS的库在auto_padding的状态下使用的也是PKCS。Key用AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA(32个,256位),IV用AAAAAAAAAAAAAAAA(16个,128位)。
Python使用pycrypto(pip install pycrypto),NodeJS使用crypto(npm install crypto),PHP需要mcrypt模块。
Python
Python
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
from Crypto.Cipher import AES
import base64
def _pad(s): return s + (AES.block_size - len(s) % AES.block_size) * chr(AES.block_size - len(s) % AES.block_size)
def _cipher():
key = 'AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA'
iv = 'AAAAAAAAAAAAAAAA'
return AES.new(key=key, mode=AES.MODE_CBC, IV=iv)
def encrypt_token(data):
return _cipher().encrypt(_pad(data))
def decrypt_token(data):
return _cipher().decrypt(data)
if __name__ == '__main__':
print('Python encrypt: ' + base64.b64encode(encrypt_token('dmyz.org')))
print('Python decrypt: ' + decrypt_token(base64.b64decode('FSfhJ/gk3iEJOPVLyFVc2Q==')))
Javascript(NodeJS)
JavaScript
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
var crypto = require('crypto'),
key = 'AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA',
iv = 'AAAAAAAAAAAAAAAA';
function encrypt_token(data) {
var cipher = crypto.createCipheriv('aes-256-cbc', key, iv);
cipher.update(data, 'binary', 'base64');
return cipher.final('base64');
}
function decrypt_token(data) {
var decipher = crypto.createDecipheriv('aes-256-cbc', key, iv);
decipher.update(data, 'base64', 'binary');
return decipher.final('binary');
}
console.log('NodeJS encrypt: ', encrypt_token('dmyz.org'));
console.log('NodeJS decrypt: ', decrypt_token('FSfhJ/gk3iEJOPVLyFVc2Q=='));
JavaScript
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
// NodeJS V0.8+ https://github.com/joyent/node/wiki/Api-changes-between-v0.8-and-v0.10
var crypto = require('crypto'),
key = 'AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA',
iv = 'AAAAAAAAAAAAAAAA';
function encrypt_token(data) {
var encipher = crypto.createCipheriv('aes-256-cbc', key, iv),
buffer = Buffer.concat([
encipher.update(data),
encipher.final()
]);
return buffer.toString('base64');
}
function decrypt_token(data) {
var decipher = crypto.createDecipheriv('aes-256-cbc', key, iv),
buffer = Buffer.concat([
decipher.update(Buffer.from(data, 'base64')),
decipher.final()
]);
return buffer.toString();
}
console.log('NodeJS encrypt: ', encrypt_token('dmyz.org'));
console.log('NodeJS decrypt: ', decrypt_token('FSfhJ/gk3iEJOPVLyFVc2Q=='));
PHP
PHP
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
class AES
{
var $key = 'AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA';
var $iv = 'AAAAAAAAAAAAAAAA';
function encryptToken($data)
{
$padding = 16 - (strlen($data) % 16);
$data .= str_repeat(chr($padding), $padding);
return mcrypt_encrypt(MCRYPT_RIJNDAEL_128, $this->key, $data, MCRYPT_MODE_CBC, $this->iv);
}
function decryptToken($data)
{
$data = mcrypt_decrypt(MCRYPT_RIJNDAEL_128, $this->key, base64_decode($data), MCRYPT_MODE_CBC, $this->iv);
$padding = ord($data[strlen($data) - 1]);
return substr($data, 0, -$padding);
}
}
if (php_sapi_name() === 'cli')
{
$aes = new AES();
echo ('PHP encrypt: '.base64_encode($aes->encryptToken('dmyz.org')))."\n";
echo ('PHP decrypt: '.$aes->decryptToken('FSfhJ/gk3iEJOPVLyFVc2Q=='))."\n";
}
标签: JS Python
顶一下
(0)
0%
踩一下
(0)
0%