android、ios、php之間AES加密解密
阿新 • • 發佈:2018-12-24
使用原因:
因為在專案中,需要在與客戶端
(IOS,Android)互動的時候,儲存一些私有資訊,不被別人看到,所以,使用了比較流行的可以反向加解密
的AES。
PHP 原始碼
<?php
$aes = new aes;
echo $aes->aes128cbcEncrypt("11122222");
echo "\n";
echo $aes->aes128cbcEncrypt("中文aes演示");
echo "\n";
class aes{
const KEY="625202f9149e061d";
const IV ="5efd3f6060e20330";
/**
* pkcs7補碼
* @param string $string 明文
* @param int $blocksize Blocksize , 以 byte 為單位
* @return String
*/
private function addPkcs7Padding($string, $blocksize = 32) {
$len = strlen($string); //取得字串長度
$pad = $blocksize - ($len % $blocksize); //取得補碼的長度
$string .= str_repeat(chr($pad ), $pad); //用ASCII碼為補碼長度的字元, 補足最後一段
return $string;
}
/**
* 加密然後base64轉碼
*
* @param String 明文
* @param 加密的初始向量(IV的長度必須和Blocksize一樣, 且加密和解密一定要用相同的IV)
* @param $key 金鑰
*/
function aes256cbcEncrypt($str, $iv, $key ) {
return base64_encode(mcrypt_encrypt(MCRYPT_RIJNDAEL_256, $key , $this->addPkcs7Padding($str) , MCRYPT_MODE_CBC, $iv));
}
/**
* 除去pkcs7 padding
*
* @param String 解密後的結果
*
* @return String
*/
private function stripPkcs7Padding($string){
$slast = ord(substr($string, -1));
$slastc = chr($slast);
$pcheck = substr($string, -$slast);
if(preg_match("/$slastc{".$slast."}/", $string)){
$string = substr($string, 0, strlen($string)-$slast);
return $string;
} else {
return false;
}
}
/**
* 解密
*
* @param String $encryptedText 二進位制的密文
* @param String $iv 加密時候的IV
* @param String $key 金鑰
* @return String
*/
function aes256cbcDecrypt($encryptedText, $iv, $key) {
$encryptedText =base64_decode($encryptedText);
return $this->stripPkcs7Padding(mcrypt_decrypt(MCRYPT_RIJNDAEL_256, $key, $encryptedText, MCRYPT_MODE_CBC, $iv));
}
function aes128cbcDecrypt($encryptedText, $iv=self::IV, $key=self::KEY) {
$encryptedText =base64_decode($encryptedText);
return $this->stripPkcs7Padding(mcrypt_decrypt(MCRYPT_RIJNDAEL_128, $key, $encryptedText, MCRYPT_MODE_CBC, $iv));
}
function hexToStr($hex)//十六進位制轉字串
{
$string="";
for($i=0;$i<strlen($hex)-1;$i+=2)
$string.=chr(hexdec($hex[$i].$hex[$i+1]));
return $string;
}
function strToHex($string)//字串轉十六進位制
{
$hex="";
$tmp="";
for($i=0;$i<strlen($string);$i++)
{
$tmp = dechex(ord($string[$i]));
$hex.= strlen($tmp) == 1 ? "0".$tmp : $tmp;
}
$hex=strtoupper($hex);
return $hex;
}
function aes128cbcHexDecrypt($encryptedText, $iv=self::IV, $key=self::KEY) {
$str = $this->hexToStr($encryptedText);
return $this->stripPkcs7Padding(mcrypt_decrypt(MCRYPT_RIJNDAEL_128, $key, $str, MCRYPT_MODE_CBC, $iv));
}
function aes128cbcEncrypt($str, $iv=self::IV, $key=self::KEY ) { // $this->addPkcs7Padding($str,16)
$base = (mcrypt_encrypt(MCRYPT_RIJNDAEL_128, $key,$this->addPkcs7Padding($str,16) , MCRYPT_MODE_CBC, $iv));
return $this->strToHex($base);
}
}
執行結果
線上驗證加解密結果
驗證地址http://www.seacha.com/tools/aes.html
IOS 原始碼
@implementation NSString (AES256)
-(NSString *) aes256_encrypt:(NSString *)key
{
const char *cstr = [self cStringUsingEncoding:NSUTF8StringEncoding];
NSData *data = [NSData dataWithBytes:cstr length:self.length];
//對資料進行加密
NSData *result = [data aes256_encrypt:key];
//轉換為2進位制字串
if (result && result.length > 0) {
Byte *datas = (Byte*)[result bytes];
NSMutableString *output = [NSMutableString stringWithCapacity:result.length * 2];
for(int i = 0; i < result.length; i++){
[output appendFormat:@"%02x", datas[i]];
}
return output;
}
return nil;
}
-(NSString *) aes256_decrypt:(NSString *)key
{
//轉換為2進位制Data
NSMutableData *data = [NSMutableData dataWithCapacity:self.length / 2];
unsigned char whole_byte;
char byte_chars[3] = {'\0','\0','\0'};
int i;
for (i=0; i < [self length] / 2; i++) {
byte_chars[0] = [self characterAtIndex:i*2];
byte_chars[1] = [self characterAtIndex:i*2+1];
whole_byte = strtol(byte_chars, NULL, 16);
[data appendBytes:&whole_byte length:1];
}
//對資料進行解密
NSData* result = [data aes256_decrypt:key];
if (result && result.length > 0) {
return [[NSString alloc] initWithData:result encoding:NSUTF8StringEncoding];
}
return nil;
}
@end
@implementation NSData (AES256)
- (NSData *)aes256_encrypt:(NSString *)key //加密
{
char keyPtr[kCCKeySizeAES256+1];
bzero(keyPtr, sizeof(keyPtr));
[key getCString:keyPtr maxLength:sizeof(keyPtr) encoding:NSUTF8StringEncoding];
NSUInteger dataLength = [self length];
size_t bufferSize = dataLength + kCCBlockSizeAES128;
void *buffer = malloc(bufferSize);
size_t numBytesEncrypted = 0;
CCCryptorStatus cryptStatus = CCCrypt(kCCEncrypt, kCCAlgorithmAES128,
kCCOptionPKCS7Padding ,
keyPtr, kCCBlockSizeAES128,
[AES_IV UTF8String],
[self bytes], dataLength,
buffer, bufferSize,
&numBytesEncrypted);
if (cryptStatus == kCCSuccess) {
return [NSData dataWithBytesNoCopy:buffer length:numBytesEncrypted];
}
free(buffer);
return nil;
}
- (NSData *)aes256_decrypt:(NSString *)key //解密
{
char keyPtr[kCCKeySizeAES256+1];
bzero(keyPtr, sizeof(keyPtr));
[key getCString:keyPtr maxLength:sizeof(keyPtr) encoding:NSUTF8StringEncoding];
NSUInteger dataLength = [self length];
size_t bufferSize = dataLength + kCCBlockSizeAES128;
void *buffer = malloc(bufferSize);
size_t numBytesDecrypted = 0;
CCCryptorStatus cryptStatus = CCCrypt(kCCDecrypt, kCCAlgorithmAES128,
kCCOptionPKCS7Padding ,
keyPtr, kCCBlockSizeAES128,
[AES_IV UTF8String],
[self bytes], dataLength,
buffer, bufferSize,
&numBytesDecrypted);
if (cryptStatus == kCCSuccess) {
return [NSData dataWithBytesNoCopy:buffer length:numBytesDecrypted];
}
free(buffer);
return nil;
}
@end
Android
package com.example.aes;
import java.io.UnsupportedEncodingException;
import javax.crypto.Cipher;
import javax.crypto.spec.IvParameterSpec;
import javax.crypto.spec.SecretKeySpec;
/**
* AES加密解密演算法
*/
public class AesEncryptionUtil {
/** 演算法/模式/填充 **/
private static final String CipherMode = "AES/CBC/PKCS5Padding";
/** 建立金鑰 **/
private static SecretKeySpec createKey(String key) {
byte[] data = null;
if (key == null) {
key = "";
}
StringBuffer sb = new StringBuffer(16);
sb.append(key);
while (sb.length() < 16) {
sb.append("0");
}
if (sb.length() > 16) {
sb.setLength(16);
}
try {
data = sb.toString().getBytes("UTF-8");
} catch (UnsupportedEncodingException e) {
e.printStackTrace();
}
return new SecretKeySpec(data, "AES");
}
private static IvParameterSpec createIV(String password) {
byte[] data = null;
if (password == null) {
password = "";
}
StringBuffer sb = new StringBuffer(16);
sb.append(password);
while (sb.length() < 16) {
sb.append("0");
}
if (sb.length() > 16) {
sb.setLength(16);
}
try {
data = sb.toString().getBytes("UTF-8");
} catch (UnsupportedEncodingException e) {
e.printStackTrace();
}
return new IvParameterSpec(data);
}
/** 加密位元組資料 **/
public static byte[] encrypt(byte[] content, String password, String iv) {
try {
SecretKeySpec key = createKey(password);
Cipher cipher = Cipher.getInstance(CipherMode);
cipher.init(Cipher.ENCRYPT_MODE, key, createIV(iv));
byte[] result = cipher.doFinal(content);
return result;
} catch (Exception e) {
e.printStackTrace();
}
return null;
}
/** 加密(結果為16進位制字串) **/
public static String encrypt(String content, String password, String iv) {
byte[] data = null;
try {
data = content.getBytes("UTF-8");
} catch (Exception e) {
e.printStackTrace();
}
data = encrypt(data, password, iv);
String result = byte2hex(data);
return result;
}
/** 解密位元組陣列 **/
public static byte[] decrypt(byte[] content, String password, String iv) {
try {
SecretKeySpec key = createKey(password);
Cipher cipher = Cipher.getInstance(CipherMode);
cipher.init(Cipher.DECRYPT_MODE, key, createIV(iv));
byte[] result = cipher.doFinal(content);
return result;
} catch (Exception e) {
e.printStackTrace();
}
return null;
}
/** 解密(輸出結果為字串) **/
public static String decrypt(String content, String password, String iv) {
byte[] data = null;
try {
data = hex2byte(content);
} catch (Exception e) {
e.printStackTrace();
}
data = decrypt(data, password, iv);
if (data == null)
return null;
String result = null;
try {
result = new String(data, "UTF-8");
} catch (UnsupportedEncodingException e) {
e.printStackTrace();
}
return result;
}
/** 位元組陣列轉成16進位制字串 **/
public static String byte2hex(byte[] b) { // 一個位元組的數,
StringBuffer sb = new StringBuffer(b.length * 2);
String tmp = "";
for (int n = 0; n < b.length; n++) {
// 整數轉成十六進位制表示
tmp = (java.lang.Integer.toHexString(b[n] & 0XFF));
if (tmp.length() == 1) {
sb.append("0");
}
sb.append(tmp);
}
return sb.toString().toUpperCase(); // 轉成大寫
}
/** 將hex字串轉換成位元組陣列 **/
private static byte[] hex2byte(String inputString) {
if (inputString == null || inputString.length() < 2) {
return new byte[0];
}
inputString = inputString.toLowerCase();
int l = inputString.length() / 2;
byte[] result = new byte[l];
for (int i = 0; i < l; ++i) {
String tmp = inputString.substring(2 * i, 2 * i + 2);
result[i] = (byte) (Integer.parseInt(tmp, 16) & 0xFF);
}
return result;
}
}