Home  >  Article  >  Backend Development  >  IOS 与 PHP 通信加密,使用AES 128 CBC no padding

IOS 与 PHP 通信加密,使用AES 128 CBC no padding

WBOY
WBOYOriginal
2016-06-23 13:39:111071browse

这个网上的资料真实浩如烟海,但是真正有价值的屈指可数

自己尝试了一天多,终于还是搞定了。

再次要感谢网上的前辈么。

比如下面这个关于php和java端的实现:

关于php和java端的实现。

再比如下面这个关于ios端的实现:

为何要采用 no padding 这种形式:

AES加密如果原输入数据不够16字节的整数位,就要补齐,如果采用

pkcs7或者pkcs5这种加密方式,末端添加的数据可能是0x1,0x2,0x3,不固定,

在解码后需要把末端多余的字符去掉,就显得比较棘手。

如果不管补齐多少位,末端都是'\0',去掉的话比较容易操作。

 

好了,再次确认一下,这里使用的是  AES128 CBC no padding加密解密方式。

先上ios端的代码:

 <pre class="objc" name="code">////  AES128.m//  login////  Created by wangdan on 15-3-3.//  Copyright (c) 2015年 wangdan. All rights reserved.//#import "AES128.h"#import <CommonCrypto/CommonCryptor.h>#import "GTMBase64.h"@implementation AES128+(NSString *)AES128Encrypt:(NSString *)plainText withKey:(NSString *)key{        if( ![self validKey:key] ){        return nil;    }        char keyPtr[kCCKeySizeAES128+1];    memset(keyPtr, 0, sizeof(keyPtr));    [key getCString:keyPtr maxLength:sizeof(keyPtr) encoding:NSUTF8StringEncoding];            char ivPtr[kCCBlockSizeAES128+1];    memset(ivPtr, 0, sizeof(ivPtr));    [key getCString:ivPtr maxLength:sizeof(ivPtr) encoding:NSUTF8StringEncoding];        NSData* data = [plainText dataUsingEncoding:NSUTF8StringEncoding];    NSUInteger dataLength = [data length];        int diff = kCCKeySizeAES128 - (dataLength % kCCKeySizeAES128);    unsigned long newSize = 0;        if(diff > 0)    {        newSize = dataLength + diff;        NSLog(@"diff is %d",diff);    }        char dataPtr[newSize];    memcpy(dataPtr, [data bytes], [data length]);    for(int i = 0; i < diff; i++)    {        dataPtr[i + dataLength] =0x0000;    }        size_t bufferSize = newSize + kCCBlockSizeAES128;    void *buffer = malloc(bufferSize);    memset(buffer, 0, bufferSize);        size_t numBytesCrypted = 0;        CCCryptorStatus cryptStatus = CCCrypt(kCCEncrypt,                                          kCCAlgorithmAES128,                                          0x0000,                                          [key UTF8String],                                          kCCKeySizeAES128,                                          [key UTF8String],                                          dataPtr,                                          sizeof(dataPtr),                                          buffer,                                          bufferSize,                                          &numBytesCrypted);        if (cryptStatus == kCCSuccess) {        NSData *resultData = [NSData dataWithBytesNoCopy:buffer length:numBytesCrypted];        return [GTMBase64 stringByEncodingData:resultData];    }    free(buffer);    return nil;}+(NSString *)processDecodedString:(NSString *)decoded{    if( decoded==nil || decoded.length==0 ){        return nil;    }    const char *tmpStr=[decoded UTF8String];    int i=0;        while( tmpStr[i]!='\0' )    {        i++;    }    NSString *final=[[NSString alloc]initWithBytes:tmpStr length:i encoding:NSUTF8StringEncoding];    return final;    }+(NSString *)AES128Decrypt:(NSString *)encryptText withKey:(NSString *)key{        if( ![self validKey:key] ){        return nil;    }        char keyPtr[kCCKeySizeAES128 + 1];    memset(keyPtr, 0, sizeof(keyPtr));    [key getCString:keyPtr maxLength:sizeof(keyPtr) encoding:NSUTF8StringEncoding];        char ivPtr[kCCBlockSizeAES128 + 1];    memset(ivPtr, 0, sizeof(ivPtr));    [key getCString:ivPtr maxLength:sizeof(ivPtr) encoding:NSUTF8StringEncoding];        NSData *data = [GTMBase64 decodeData:[encryptText dataUsingEncoding:NSUTF8StringEncoding]];    NSUInteger dataLength = [data length];    size_t bufferSize = dataLength + kCCBlockSizeAES128;    void *buffer = malloc(bufferSize);        size_t numBytesCrypted = 0;    CCCryptorStatus cryptStatus = CCCrypt(kCCDecrypt,                                          kCCAlgorithmAES128,                                          0x0000,                                          [key UTF8String],                                          kCCBlockSizeAES128,                                          [key UTF8String],                                          [data bytes],                                          dataLength,                                          buffer,                                          bufferSize,                                          &numBytesCrypted);    if (cryptStatus == kCCSuccess) {        NSData *resultData = [NSData dataWithBytesNoCopy:buffer length:numBytesCrypted];                NSString *decoded=[[NSString alloc] initWithData:resultData encoding:NSUTF8StringEncoding];        return [self processDecodedString:decoded];    }        free(buffer);    return nil;    }+(BOOL)validKey:(NSString*)key{    if( key==nil || key.length !=16 ){        return NO;    }    return YES;}-(NSString *)processDecodedString:(NSString *)decoded{    if( decoded==nil || decoded.length==0 ){        return nil;    }    const char *tmpStr=[decoded UTF8String];    int i=0;        while( tmpStr[i]!='\0' )    {        i++;    }    NSString *final=[[NSString alloc]initWithBytes:tmpStr length:i encoding:NSUTF8StringEncoding];    return final;    }@end


上述代码需要说明的是,进行AES编码时,输入编码必须是16字节的整数倍,不然调用ios 的系统api会报错 -4003

补齐的字节数全部填充为0

 

另外  processDecodedString这个函数为了把解码后的字符串,末尾去掉'\0'

 

下面是PHP端的代码,这个代码是大神些写的啊,经过实际实验是能使用的:

<?php$privateKey = "1234567812345678";$iv     = "1234567812345678";$data   = "Test String"; //加密$encrypted = mcrypt_encrypt(MCRYPT_RIJNDAEL_128, $privateKey, $data, MCRYPT_MODE_CBC, $iv);echo(base64_encode($encrypted));echo '<br/>'; //解密$encryptedData = base64_decode("2fbwW9+8vPId2/foafZq6Q==");$decrypted = mcrypt_decrypt(MCRYPT_RIJNDAEL_128, $privateKey, $encryptedData, MCRYPT_MODE_CBC, $iv);echo($decrypted);?>


 

 

 

Statement:
The content of this article is voluntarily contributed by netizens, and the copyright belongs to the original author. This site does not assume corresponding legal responsibility. If you find any content suspected of plagiarism or infringement, please contact admin@php.cn