• 隐藏侧边栏
  • 展开分类目录
  • 关注微信公众号
  • 我的GitHub
  • QQ:1753970025
Chen Jiehua

Movies-Server Protocols 

重要更新:此处不再更新,点此查看最新版文档!

加密解密算法

采用AES加密算法/CBC模式/PKCS5Padding补全

密钥:????????????

向量: byte[16],由调用方随机生成

Get请求:

将16位(byte[16])的向量(iv)置于二进制密文头部,再进行base64encode,生成最终的s参数

Post请求:

将16位(byte[16])的向量(iv)置于二进制密文头部,再进行base64encode,最后发送二进制流。

PKCS5Padding规则

1、计算输入长度为L。
2、如果L是16倍数,padding长度为16,padding值为0x10。即在输入后面补齐16字节的0x10。
3、如果L不是16倍数,padding长度为16-L%16,padding值为16-L%16。即在输入后面补齐16-L%16的字节,值为16-L%16。
2和3其实可以根据公式 16-L%16 写成一条规则,这里只是强调2的特殊性,明确并不是不做补齐。

参考:http://www.xjump.me/content.htm?id=72

 

测试用例

接口:http://movies.chenjiehua.me/

原始参数:

token=60035ef9e144c8662591914b219a252d0c93854e

rt=1490000000

加密后生成s参数:

s=XGobIjyl8T4zuiPr+LMGjw07BSBKDC1ecA5PLjmHmUsrR9BhelPl9bmPU40agn6xu4SaCZ2j/jop2LjrAza9NV5F7VoRbeumjRqHxNgL8z4=

GET请求链接:

http://movies.chenjiehua.me/test?s=XGobIjyl8T4zuiPr+LMGjw07BSBKDC1ecA5PLjmHmUsrR9BhelPl9bmPU40agn6xu4SaCZ2j/jop2LjrAza9NV5F7VoRbeumjRqHxNgL8z4=

返回结果:

{
"c": 0,
"d": {
    "rt": "1490000000",
    "token": "60035ef9e144c8662591914b219a252d0c93854e",
    "type": "get"
     }
}

POST请求链接:http://movies.chenjiehua.me/test

Request Body:XGobIjyl8T4zuiPr+LMGjw07BSBKDC1ecA5PLjmHmUsrR9BhelPl9bmPU40agn6xu4SaCZ2j/jop2LjrAza9NV5F7VoRbeumjRqHxNgL8z4=

返回结果:

{
"c": 0,
"d": {
    "rt": "1490000000",
    "token": "60035ef9e144c8662591914b219a252d0c93854e",
    "type": "post"
     }
}

其他返回代码说明:http://chenjiehua.me/?p=507

 

代码示例:

Python

import base64

from Crypto import Random
from Crypto.Cipher import AES

class AESCipher:
    """ AES 加密解密 """

    def __init__(self, key):
        self.bs = 16
        if len(key) >= 16:
            self.key = key[:16]
        else:
            self.key = self._pad(key)

    def encrypt(self, raw):
        raw = self._pad(raw)
        iv = Random.new().read(AES.block_size)
        cipher = AES.new(self.key, AES.MODE_CBC, iv)
        return base64.b64encode(iv + cipher.encrypt(raw))

    def decrypt(self, enc):
        enc = base64.b64decode(enc)
        iv = enc[:AES.block_size]
        cipher = AES.new(self.key, AES.MODE_CBC, iv)
        return self._unpad(cipher.decrypt(enc[AES.block_size:]))

    def _pad(self, s):
        return s + (self.bs - len(s) % self.bs) * chr(self.bs - len(s) % self.bs)

    def _unpad(self, s):
        return s[:-ord(s[len(s) - 1:])]

参考:https://gist.github.com/crmccreary/5610068 

Android

private static String encryptParamsToGet(byte[] PSW, Map<String, String> params) throws Throwable {
    byte[] buff = encryptParamsToPost(PSW, params);
    if (buff == null) {
        return null;
    }
    return Base64.encodeToString(buff, Base64.DEFAULT);
}

private static byte[] encryptParamsToPost(byte[] PSW, Map<String, String> params) throws Throwable {
    if (params == null) {
        return null;
    }
    StringBuilder sb = new StringBuilder();
    Iterator<Map.Entry<String, String>> iter = params.entrySet().iterator();
    while (iter.hasNext()) {
        Map.Entry<String, String> entry = iter.next();
        String key = entry.getKey();
        String value = entry.getValue();
        if (sb.length() > 0) {
            sb.append('&');
        }
        sb.append(key).append('=').append(Uri.encode(value));
    }
    byte[] buff = sb.toString().getBytes("UTF-8");
    byte[] iv = new byte[16];
    Random rd = new Random();
    rd.nextBytes(iv);
    byte[] data = Aes.encrypt(buff, PSW, iv);
    ByteArrayOutputStream baos = new ByteArrayOutputStream();
    baos.write(iv, 0, iv.length);
    baos.write(data, 0, data.length);
    byte[] out = baos.toByteArray();
    try {
        baos.close();
    } catch (Throwable e) {
        }
    return out;
}

iOS

需要NSData+AESCrypt、NSData+CommonCrypto.h

#import "Encryptor.h"
#import "NSData+CommonCrypto.h"
#import "NSData+AESCrypt.h"

static char kRandomCharTable[62] = {
    'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P',
    'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z', 'a', 'b', 'c', 'd', 'e', 'f',
    'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v',
    'w', 'x', 'y', 'z', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9'
};

static NSString *kEncryptKey = @"AjGfpbbQmU7EAnkJ";

@implementation Encryptor

+ (NSData *)AESEncrytAsData:(NSDictionary *)params {
    NSMutableString *str = [NSMutableString new];
    for (NSString *key in params) {
        NSString *value = params[key];
        NSString *vString = [value stringByAddingPercentEscapesUsingEncoding:NSUTF8StringEncoding];

        [str appendFormat:@"&%@=%@", key, vString];
    }
    NSString *line = @"";
    if ([str length] > 0) {
        line = [str substringFromIndex:1];
    }

    NSData *data = [line dataUsingEncoding:NSUTF8StringEncoding];
    NSData *iv = [self randomDataOfLength:16];
    CCCryptorStatus status = kCCSuccess;
    NSData *encrypted = [data dataEncryptedUsingAlgorithm:kCCAlgorithmAES128 key:kEncryptKey initializationVector:iv options:kCCOptionPKCS7Padding error:&status];

    NSMutableData *result = [[NSMutableData alloc] initWithData:iv];
    [result appendData:encrypted];

    return result;

}

+ (NSString *)AESEncryptAsBase64:(NSDictionary *)params {
    NSData *d = [self AESEncrytAsData:params];
    return [d base64Encoding];
}

+ (NSData *)randomDataOfLength:(NSInteger)length {
    char rand_chars[length];
    for (int i = 0; i < length; i++) {
        u_int32_t randChar = arc4random() % 62;
        rand_chars[i] = kRandomCharTable[randChar];
    }

    return [NSData dataWithBytes:rand_chars length:length];
}

@end

 

码字很辛苦,转载请注明来自ChenJiehua《Movies-Server Protocols》

评论