在多端協同開發中,數據加密傳輸是基礎需求。本文提供一套經過驗證的 3DES (Triple DES) 加解密方案,涵蓋 PHP 服務端、Java/Android 客戶端與 iOS 客戶端,確保各平台加密數據能夠無縫互通。核心參數統一為:CBC 模式、PKCS5/7 填充、Base64 編碼輸出,密鑰與向量(IV)在各端保持一致。
my.oschina.net/penngo?#@(不足 24 字節以 0 補齊)01234567(8 字節)<?php
class DES3 {
private $key = "my.oschina.net/penngo?#@";
private $iv = "01234567";
public function encrypt($input) {
$size = mcrypt_get_block_size(MCRYPT_3DES, MCRYPT_MODE_CBC);
$input = $this->pkcs5_pad($input, $size);
$key = str_pad($this->key, 24, '0');
$td = mcrypt_module_open(MCRYPT_3DES, '', MCRYPT_MODE_CBC, '');
$iv = $this->iv ?: mcrypt_create_iv(mcrypt_enc_get_iv_size($td), MCRYPT_RAND);
mcrypt_generic_init($td, $key, $iv);
$data = mcrypt_generic($td, $input);
mcrypt_generic_deinit($td);
mcrypt_module_close($td);
return base64_encode($data);
}
public function decrypt($encrypted) {
$encrypted = base64_decode($encrypted);
$key = str_pad($this->key, 24, '0');
$td = mcrypt_module_open(MCRYPT_3DES, '', MCRYPT_MODE_CBC, '');
$iv = $this->iv ?: mcrypt_create_iv(mcrypt_enc_get_iv_size($td), MCRYPT_RAND);
mcrypt_generic_init($td, $key, $iv);
$decrypted = mdecrypt_generic($td, $encrypted);
mcrypt_generic_deinit($td);
mcrypt_module_close($td);
return $this->pkcs5_unpad($decrypted);
}
private function pkcs5_pad($text, $blocksize) {
$pad = $blocksize - (strlen($text) % $blocksize);
return $text . str_repeat(chr($pad), $pad);
}
private function pkcs5_unpad($text) {
$pad = ord($text[strlen($text)-1]);
if ($pad > strlen($text)) return false;
if (strspn($text, chr($pad), strlen($text) - $pad) != $pad) return false;
return substr($text, 0, -1 * $pad);
}
}
// 測試
$des = new DES3();
$plain = "來自https://jb51.net的博客";
$encrypted = $des->encrypt($plain);
echo "加密: $encrypted\n";
echo "解密: " . $des->decrypt($encrypted) . "\n";
?>
import javax.crypto.Cipher;
import javax.crypto.SecretKeyFactory;
import javax.crypto.spec.DESedeKeySpec;
import javax.crypto.spec.IvParameterSpec;
import java.io.UnsupportedEncodingException;
import java.security.Key;
public class DES3 {
private static final String SECRET_KEY = "my.oschina.net/penngo?#@";
private static final String IV = "01234567";
private static final String ENCODING = "utf-8";
private static final String TRANSFORMATION = "desede/CBC/PKCS5Padding";
public static String encode(String plainText) throws Exception {
Key deskey = SecretKeyFactory.getInstance("desede")
.generateSecret(new DESedeKeySpec(SECRET_KEY.getBytes()));
Cipher cipher = Cipher.getInstance(TRANSFORMATION);
cipher.init(Cipher.ENCRYPT_MODE, deskey, new IvParameterSpec(IV.getBytes()));
byte[] encryptData = cipher.doFinal(plainText.getBytes(ENCODING));
return Base64.encode(encryptData); // 使用自帶或第三方 Base64
}
public static String decode(String encryptText) throws Exception {
Key deskey = SecretKeyFactory.getInstance("desede")
.generateSecret(new DESedeKeySpec(SECRET_KEY.getBytes()));
Cipher cipher = Cipher.getInstance(TRANSFORMATION);
cipher.init(Cipher.DECRYPT_MODE, deskey, new IvParameterSpec(IV.getBytes()));
byte[] decryptData = cipher.doFinal(Base64.decode(encryptText));
return new String(decryptData, ENCODING);
}
// 內建 Base64 工具類(略,建議使用 android.util.Base64 或 Java 8+ java.util.Base64)
public static class Base64 { /* ... 完整實現見原文 ... */ }
}
依賴 CommonCrypto 與 GTMBase64(Google Toolbox for Mac)。
// DES3Util.h
#import <Foundation/Foundation.h>
@interface DES3Util : NSObject
+ (NSString*)encrypt:(NSString*)plainText;
+ (NSString*)decrypt:(NSString*)encryptText;
@end
// DES3Util.m
#import "DES3Util.h"
#import <CommonCrypto/CommonCryptor.h>
#import "GTMBase64.h"
#define kKey @"my.oschina.net/penngo?#@"
#define kIV @"01234567"
@implementation DES3Util
+ (NSString*)encrypt:(NSString*)plainText {
NSData *data = [plainText dataUsingEncoding:NSUTF8StringEncoding];
size_t bufferSize = data.length + kCCBlockSize3DES;
void *buffer = malloc(bufferSize);
size_t movedBytes = 0;
CCCryptorStatus status = CCCrypt(kCCEncrypt, kCCAlgorithm3DES, kCCOptionPKCS7Padding,
[kKey UTF8String], kCCKeySize3DES,
[kIV UTF8String],
[data bytes], data.length,
buffer, bufferSize, &movedBytes);
NSData *encryptedData = [NSData dataWithBytes:buffer length:movedBytes];
free(buffer);
return [GTMBase64 stringByEncodingData:encryptedData];
}
+ (NSString*)decrypt:(NSString*)encryptText {
NSData *encryptedData = [GTMBase64 decodeData:[encryptText dataUsingEncoding:NSUTF8StringEncoding]];
size_t bufferSize = encryptedData.length + kCCBlockSize3DES;
void *buffer = malloc(bufferSize);
size_t movedBytes = 0;
CCCryptorStatus status = CCCrypt(kCCDecrypt, kCCAlgorithm3DES, kCCOptionPKCS7Padding,
[kKey UTF8String], kCCKeySize3DES,
[kIV UTF8String],
[encryptedData bytes], encryptedData.length,
buffer, bufferSize, &movedBytes);
NSData *decryptedData = [NSData dataWithBytes:buffer length:movedBytes];
free(buffer);
return [[NSString alloc] initWithData:decryptedData encoding:NSUTF8StringEncoding];
}
@end
0 補齊,Java/iOS 直接取字節陣列前 24 位,確保一致。PKCS5Padding,iOS 用 kCCOptionPKCS7Padding,兩者對 8 字節塊大小等效。mcrypt 已移除,建議改用 openssl_encrypt / openssl_decrypt,參數對應 OPENSSL_RAW_DATA + base64_encode。統一算法、模式、填充、編碼、密鑰與 IV,即可實現 PHP、Java/Android、iOS 三端 3DES 數據的無縫加解密互通。實際項目中建議優先考慮 AES-GCM 等更現代的認證加密方案,但若受限於歷史系統,本方案經過實測可靠可用。