说明
针对上行参数 value,做加密处理,基本思路每个项目拥有有不同的私钥因子(通过定义后台配置),最终的私钥=md5(私钥因子 + uid),得到32位的私钥,客户端与服务端以同样逻辑来处理私钥。
加密处理流程:
aes加密;
针对密文base64编码;
进一步urlencode编码
解密时按(c)(b)(a)顺序依次执行。
每个项目使用不同的秘钥,秘钥长度32位字符串
注意
需要和客户端(iOS+Android)验证三端加密串一致,且互相能够解密。
代码
NodeJs代码
//引入nodejs加密核心库
varcrypto =require('crypto');
//加密公共密钥 32位
varkeys ='9ce62c1836d128cfc875c9026db7564c';
//编码设置
varclearEncoding ='utf8';
//加密方式
varalgorithm ='aes-256-ecb';
//向量
variv ="";
//加密类型 base64/hex...
varcipherEncoding ='hex';
exports.encodeCipher =function(data){
try{
varcipher = crypto.createCipheriv(algorithm, keys, iv);
varcipherChunks = [];
cipherChunks.push(cipher.update(data, clearEncoding, cipherEncoding));
cipherChunks.push(cipher.final(cipherEncoding));
returncipherChunks.join('');
}catch(e){
return10004;
}
}
exports.decodeCipher =function(data){
try{
varcipherChunks = [data];
vardecipher = crypto.createDecipheriv(algorithm, keys, iv);
varplainChunks = [];
for(vari =0;i < cipherChunks.length;i++) {
plainChunks.push(decipher.update(cipherChunks[i], cipherEncoding, clearEncoding));
}
plainChunks.push(decipher.final(clearEncoding));
returneval_r("("+plainChunks.join('')+")");//转成对象,方便程序中使用
}catch(e){
return10003;
}
}
IOS代码
- (NSData*)AES256EncryptWithKey:(NSData*)key //加密
{
//對於塊加密算法,輸出大小總是等於或小於輸入大小加上一個塊的大小
//所以在下邊需要再加上一個塊的大小
NSUIntegerdataLength = [selflength];
size_t bufferSize = dataLength + kCCBlockSizeAES128;
void*buffer = malloc(bufferSize);
size_t numBytesEncrypted =0;
CCCryptorStatus cryptStatus = CCCrypt(kCCEncrypt, kCCAlgorithmAES128,
kCCOptionPKCS7Padding | kCCOptionECBMode,
[key bytes], kCCKeySizeAES256,
NULL,
[selfbytes], dataLength,
buffer, bufferSize,
&numBytesEncrypted);
if(cryptStatus == kCCSuccess) {
return[NSDatadataWithBytesNoCopy:buffer length:numBytesEncrypted];
}
free(buffer);//釋放buffer
returnnil;
}
- (NSData*)AES256DecryptWithKey:(NSData*)key //解密
{
//同理,解密中,密鑰也是32位的
constvoid* keyPtr2 = [key bytes];
constchar(*keyPtr)[32] = keyPtr2;
//對於塊加密算法,輸出大小總是等於或小於輸入大小加上一個塊的大小
//所以在下邊需要再加上一個塊的大小
NSUIntegerdataLength = [selflength];
size_t bufferSize = dataLength + kCCBlockSizeAES128;
void*buffer = malloc(bufferSize);
size_t numBytesDecrypted =0;
CCCryptorStatus cryptStatus = CCCrypt(kCCDecrypt, kCCAlgorithmAES128,
kCCOptionPKCS7Padding | kCCOptionECBMode,
keyPtr, kCCKeySizeAES256,
NULL,
[selfbytes], dataLength,
buffer, bufferSize,
&numBytesDecrypted);
if(cryptStatus == kCCSuccess) {
return[NSDatadataWithBytesNoCopy:buffer length:numBytesDecrypted];
}
free(buffer);
returnnil;
}
JAVA代码
packagecom.cityfore.smarthome.hd.util;
importjava.security.Key;
importjava.security.Security;
importjavax.crypto.Cipher;
importjavax.crypto.SecretKey;
importjavax.crypto.spec.SecretKeySpec;
importorg.bouncycastle.jce.provider.BouncyCastleProvider;
publicclassAES256{
privatestaticfinalString KEY_ALGORITHM ="AES";
privatestaticfinalString CIPHER_ALGORITHM ="AES/ECB/PKCS7Padding";
privatestaticKeytoKey(byte[] key)throwsException{
//实例化DES密钥
//生成密钥
SecretKey secretKey =newSecretKeySpec(key, KEY_ALGORITHM);
returnsecretKey;
}
publicstaticStringbytes2String(bytebuf[]){
StringBuffer sb =newStringBuffer();
for(inti =0; i < buf.length; i++) {
String hex = Integer.toHexString(buf[i] &0xFF);
if(hex.length() ==1) {
hex ='0'+ hex;
}
sb.append(hex);
}
returnsb.toString();
}
publicstaticbyte[] string2Bytes(String hexString) {
intlen = hexString.length() /2;
byte[] result =newbyte[len];
for(inti =0; i < len; i++) {
result[i] = Integer.valueOf(hexString.substring(2* i,2* i +2),16).byteValue();
}
returnresult;
}
publicstaticStringencrypt(String data, String key){
try{
//还原密钥
Key k = toKey(key.getBytes());
Security.addProvider(newBouncyCastleProvider());
Cipher cipher = Cipher.getInstance(CIPHER_ALGORITHM,"BC");
//初始化,设置为加密模式
cipher.init(Cipher.ENCRYPT_MODE, k);
//执行操作
returnbytes2String(cipher.doFinal(data.getBytes()));
}catch(Exception e) {
}
returnnull;
}
publicstaticStringdecrypt(String data, String key){
try{
Key k = toKey(key.getBytes());
Cipher cipher = Cipher.getInstance(CIPHER_ALGORITHM);
//初始化,设置为解密模式
cipher.init(Cipher.DECRYPT_MODE, k);
//执行操作
returnnewString(cipher.doFinal(string2Bytes(data)));
}catch(Exception e) {
}
returnnull;
}
}
PHP代码
classOpensslAES
{
// PHP >= 5.3.0
constMETHOD ='aes-256-ecb';
publicstaticfunctionencrypt($message,$key)
{
if(mb_strlen($key,'8bit') !==32) {
thrownewException("Needs a 256-bit key!");
}
$ivsize= openssl_cipher_iv_length(self::METHOD);
$iv= openssl_random_pseudo_bytes($ivsize);
$ciphertext= openssl_encrypt(
$message,
self::METHOD,
$key,
OPENSSL_RAW_DATA,
$iv
);
return$iv.$ciphertext;
}
publicstaticfunctiondecrypt($message,$key)
{
if(mb_strlen($key,'8bit') !==32) {
thrownewException("Needs a 256-bit key!");
}
$ivsize= openssl_cipher_iv_length(self::METHOD);
$iv= mb_substr($message,0,$ivsize,'8bit');
$ciphertext= mb_substr($message,$ivsize,null,'8bit');
returnopenssl_decrypt(
$ciphertext,
self::METHOD,
$key,
OPENSSL_RAW_DATA,
$iv
);
}
}
// string
$original='9.9';
// encrypt key
$key='9642f6b792d86dadf1144367111964b9';
// uid
$uid='1133317534580800';
// 加密
$toEnc= OpensslAES::encrypt($original, md5($key.$uid);
$toEnc= bin2hex($toEnc);
$toEnc= base64_encode($toEnc);
$toEnc= urlencode($toEnc);
print_r($toEnc);// NmI5ODI0ZjgyMWZiZDM1NTkzOThkYzY1NWIxZjE1OGQ%3D
// 解密
$toDec='NmI5ODI0ZjgyMWZiZDM1NTkzOThkYzY1NWIxZjE1OGQ%3D';
$toDec= urldecode($toDec);
$toDec= base64_decode($toDec);
$toDec= hex2bin($toDec);
$original= OpensslAES::decrypt($toDec, md5($key.$uid));
print_r($original);// 9.9