Appearance
加密算法指南
优先使用 SDK
官方 SDK 已内置全部加密算法,强烈建议直接使用 SDK 进行对接。如果找不到你的开发语言的 SDK,可参考以下代码自行实现,具体细节请参考 SDK 源码。
RSA 非对称加密
加密方向与常规相反
- 请求加密:客户端用 公钥加密 → 服务器用 私钥解密
- 响应解密:服务器用 私钥加密 → 客户端用 公钥解密
RSA 加密有数据长度限制,超过需要分段处理:
| 密钥长度 | 加密分段大小 | 解密分段大小 |
|---|---|---|
| 1024 位 | 117 字节(128 - 11) | 128 字节 |
| 2048 位 | 245 字节(256 - 11) | 256 字节 |
公钥加密(请求参数)
python
from Crypto.PublicKey import RSA
from Crypto.Cipher import PKCS1_v1_5
def rsa_encrypt(data, public_key_pem):
key = RSA.import_key(public_key_pem)
cipher = PKCS1_v1_5.new(key)
key_size = key.size_in_bytes()
block_size = key_size - 11
data_bytes = data.encode('utf-8')
encrypted = b''
offset = 0
while offset < len(data_bytes):
block = data_bytes[offset:offset + block_size]
encrypted += cipher.encrypt(block)
offset += block_size
return encrypted.hex().upper()javascript
const crypto = require('crypto');
function rsaEncrypt(data, publicKeyPem) {
const dataBytes = Buffer.from(data, 'utf-8');
const keySize = 128; // 1024位密钥
const blockSize = keySize - 11;
const blocks = [];
let offset = 0;
while (offset < dataBytes.length) {
const block = dataBytes.slice(offset, offset + blockSize);
blocks.push(crypto.publicEncrypt(
{ key: publicKeyPem, padding: crypto.constants.RSA_PKCS1_PADDING },
block
));
offset += blockSize;
}
return Buffer.concat(blocks).toString('hex').toUpperCase();
}java
import javax.crypto.Cipher;
import java.io.ByteArrayOutputStream;
public static String rsaEncrypt(String data, PublicKey publicKey, int keySize) throws Exception {
Cipher cipher = Cipher.getInstance("RSA/ECB/PKCS1Padding");
cipher.init(Cipher.ENCRYPT_MODE, publicKey);
int blockSize = keySize - 11;
byte[] dataBytes = data.getBytes("UTF-8");
ByteArrayOutputStream out = new ByteArrayOutputStream();
int offset = 0;
while (offset < dataBytes.length) {
int len = Math.min(blockSize, dataBytes.length - offset);
out.write(cipher.doFinal(dataBytes, offset, len));
offset += len;
}
return bytesToHex(out.toByteArray()).toUpperCase();
}c
// 使用内置 RSA 实现(不依赖 OpenSSL)
unsigned char* rsa_encrypt(const char* data, int data_len,
const BIGNUM* n, const BIGNUM* e,
int key_size, int* out_len) {
int block_size = key_size - 11;
int blocks = (data_len + block_size - 1) / block_size;
unsigned char* result = malloc(blocks * key_size);
*out_len = 0;
int offset = 0;
while (offset < data_len) {
int chunk = (data_len - offset < block_size) ? data_len - offset : block_size;
// PKCS1 填充 + 模幂运算: pow(padded_block, e, n)
rsa_pkcs1_encrypt(data + offset, chunk, n, e, key_size,
result + *out_len);
*out_len += key_size;
offset += chunk;
}
return result;
}公钥解密(响应数据)
python
from Crypto.Util.number import bytes_to_long, long_to_bytes
def rsa_decrypt(hex_data, public_key_pem):
key = RSA.import_key(public_key_pem)
n, e = key.n, key.e
key_size = key.size_in_bytes()
encrypted = bytes.fromhex(hex_data)
decrypted = b''
offset = 0
while offset < len(encrypted):
block = encrypted[offset:offset + key_size]
block_int = bytes_to_long(block)
dec_int = pow(block_int, e, n) # 模幂运算
dec_block = long_to_bytes(dec_int, key_size)
pad_end = dec_block.index(b'\x00', 2) # 去除 PKCS1 填充
decrypted += dec_block[pad_end + 1:]
offset += key_size
return decrypted.decode('utf-8')javascript
function rsaDecrypt(hexData, n, e, keySize) {
const encrypted = Buffer.from(hexData, 'hex');
const blocks = [];
let offset = 0;
while (offset < encrypted.length) {
const block = encrypted.slice(offset, offset + keySize);
let blockInt = bufferToBigInt(block);
let decInt = modPow(blockInt, e, n); // 模幂运算
let decBlock = bigIntToBuffer(decInt, keySize);
// 去除 PKCS1 填充
let padEnd = -1;
for (let i = 2; i < decBlock.length; i++) {
if (decBlock[i] === 0x00) { padEnd = i; break; }
}
blocks.push(padEnd !== -1 ? decBlock.slice(padEnd + 1) : decBlock);
offset += keySize;
}
return Buffer.concat(blocks).toString('utf-8');
}java
public static String rsaDecrypt(String hexData, BigInteger n, BigInteger e, int keySize) {
byte[] encrypted = hexToBytes(hexData);
ByteArrayOutputStream out = new ByteArrayOutputStream();
int offset = 0;
while (offset < encrypted.length) {
byte[] block = Arrays.copyOfRange(encrypted, offset, offset + keySize);
BigInteger blockInt = new BigInteger(1, block);
BigInteger decInt = blockInt.modPow(e, n); // 模幂运算
byte[] decBlock = bigIntToBytes(decInt, keySize);
// 去除 PKCS1 填充
int padEnd = 2;
while (padEnd < decBlock.length && decBlock[padEnd] != 0x00) padEnd++;
out.write(decBlock, padEnd + 1, decBlock.length - padEnd - 1);
offset += keySize;
}
return out.toString("UTF-8");
}RC4 对称流式加密
加密和解密使用同一函数、同一密钥。
python
def rc4(data, key):
S = list(range(256))
j = 0
for i in range(256):
j = (j + S[i] + ord(key[i % len(key)])) % 256
S[i], S[j] = S[j], S[i]
i = j = 0
result = []
for char in data:
i = (i + 1) % 256
j = (j + S[i]) % 256
S[i], S[j] = S[j], S[i]
result.append(chr(ord(char) ^ S[(S[i] + S[j]) % 256]))
return ''.join(result)javascript
function rc4(data, key) {
const S = Array.from({ length: 256 }, (_, i) => i);
let j = 0;
for (let i = 0; i < 256; i++) {
j = (j + S[i] + key.charCodeAt(i % key.length)) % 256;
[S[i], S[j]] = [S[j], S[i]];
}
let i = 0; j = 0;
let result = '';
for (const char of data) {
i = (i + 1) % 256;
j = (j + S[i]) % 256;
[S[i], S[j]] = [S[j], S[i]];
result += String.fromCharCode(char.charCodeAt(0) ^ S[(S[i] + S[j]) % 256]);
}
return result;
}java
public static String rc4(String data, String key) {
int[] S = new int[256];
for (int i = 0; i < 256; i++) S[i] = i;
int j = 0;
for (int i = 0; i < 256; i++) {
j = (j + S[i] + key.charAt(i % key.length())) % 256;
int tmp = S[i]; S[i] = S[j]; S[j] = tmp;
}
int ii = 0; j = 0;
StringBuilder result = new StringBuilder();
for (char c : data.toCharArray()) {
ii = (ii + 1) % 256;
j = (j + S[ii]) % 256;
int tmp = S[ii]; S[ii] = S[j]; S[j] = tmp;
result.append((char)(c ^ S[(S[ii] + S[j]) % 256]));
}
return result.toString();
}c
void rc4(const char* data, int data_len, const char* key, int key_len, char* out) {
unsigned char S[256];
for (int i = 0; i < 256; i++) S[i] = i;
int j = 0;
for (int i = 0; i < 256; i++) {
j = (j + S[i] + key[i % key_len]) % 256;
unsigned char tmp = S[i]; S[i] = S[j]; S[j] = tmp;
}
int i = 0; j = 0;
for (int k = 0; k < data_len; k++) {
i = (i + 1) % 256;
j = (j + S[i]) % 256;
unsigned char tmp = S[i]; S[i] = S[j]; S[j] = tmp;
out[k] = data[k] ^ S[(S[i] + S[j]) % 256];
}
}DES-ECB 对称分组加密
使用 ECB 模式 + PKCS7 填充,密钥固定 8 字节。
python
from Crypto.Cipher import DES
import base64
def des_encrypt(data, key):
cipher = DES.new(key.encode(), DES.MODE_ECB)
pad_len = 8 - len(data.encode()) % 8
padded = data + chr(pad_len) * pad_len
return base64.b64encode(cipher.encrypt(padded.encode())).decode()
def des_decrypt(data, key):
cipher = DES.new(key.encode(), DES.MODE_ECB)
decrypted = cipher.decrypt(base64.b64decode(data))
return decrypted[:-decrypted[-1]].decode()javascript
const crypto = require('crypto');
function desEncrypt(data, key) {
const cipher = crypto.createCipheriv('des-ecb', key, null);
cipher.setAutoPadding(true); // PKCS7
let encrypted = cipher.update(data, 'utf8', 'base64');
encrypted += cipher.final('base64');
return encrypted;
}
function desDecrypt(data, key) {
const decipher = crypto.createDecipheriv('des-ecb', key, null);
let decrypted = decipher.update(data, 'base64', 'utf8');
decrypted += decipher.final('utf8');
return decrypted;
}自定义 Base64 编码
使用后台配置的 64 个字符替换标准 Base64 编码表,编码集必须恰好 64 个不重复字符。
python
import base64
class CustomBase64:
STANDARD_CHARSET = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/'
def __init__(self, custom_charset):
if len(custom_charset) != 64:
raise ValueError("自定义字符集必须是64位字符")
self.custom_charset = custom_charset
self.encode_trans = str.maketrans(self.STANDARD_CHARSET, self.custom_charset)
self.decode_trans = str.maketrans(self.custom_charset, self.STANDARD_CHARSET)
def encode(self, data):
if isinstance(data, str):
data = data.encode('utf-8')
standard_b64 = base64.b64encode(data).decode('ascii')
return standard_b64.translate(self.encode_trans)
def decode(self, data):
standard_b64 = data.translate(self.decode_trans)
return base64.b64decode(standard_b64).decode('utf-8')javascript
class CustomBase64 {
constructor(customCharset) {
if (customCharset.length !== 64)
throw new Error('自定义字符集必须是64位字符');
this.standardCharset = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/';
this.customCharset = customCharset;
}
encode(data) {
let standardB64 = Buffer.from(data, 'utf-8').toString('base64');
let result = '';
for (let i = 0; i < standardB64.length; i++) {
const idx = this.standardCharset.indexOf(standardB64[i]);
result += idx !== -1 ? this.customCharset[idx] : standardB64[i];
}
return result;
}
decode(data) {
let standardB64 = '';
for (let i = 0; i < data.length; i++) {
const idx = this.customCharset.indexOf(data[i]);
standardB64 += idx !== -1 ? this.standardCharset[idx] : data[i];
}
return Buffer.from(standardB64, 'base64').toString('utf-8');
}
}java
public class CustomBase64 {
private static final String STANDARD = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
private final String customCharset;
public CustomBase64(String customCharset) {
if (customCharset.length() != 64)
throw new IllegalArgumentException("自定义字符集必须是64位字符");
this.customCharset = customCharset;
}
public String encode(String data) {
String standard = java.util.Base64.getEncoder().encodeToString(data.getBytes());
StringBuilder sb = new StringBuilder();
for (char c : standard.toCharArray()) {
int idx = STANDARD.indexOf(c);
sb.append(idx != -1 ? customCharset.charAt(idx) : c);
}
return sb.toString();
}
public String decode(String data) {
StringBuilder sb = new StringBuilder();
for (char c : data.toCharArray()) {
int idx = customCharset.indexOf(c);
sb.append(idx != -1 ? STANDARD.charAt(idx) : c);
}
return new String(java.util.Base64.getDecoder().decode(sb.toString()));
}
}c
static const char STANDARD[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
char* custom_b64_encode(const char* data, int len, const char* charset) {
char* standard = base64_encode(data, len); // 标准 Base64 编码
for (int i = 0; standard[i]; i++) {
const char* p = strchr(STANDARD, standard[i]);
if (p) standard[i] = charset[p - STANDARD];
}
return standard;
}
char* custom_b64_decode(const char* data, const char* charset) {
char* buf = strdup(data);
for (int i = 0; buf[i]; i++) {
const char* p = strchr(charset, buf[i]);
if (p) buf[i] = STANDARD[p - charset];
}
return base64_decode(buf); // 标准 Base64 解码
}