定义Padding
typedef enum : NSUInteger {
UnicomCryptoNoPadding = 0 ,
UnicomCryptoPKCS7Padding = 1 ,
UnicomCryptoZeroPadding = 2 ,
UnicomCryptoANSIX923Padding = 3 ,
UnicomCryptoISO10126Padding = 4 ,
} UnicomCryptoPadding;
对齐iv和key
static void SettingKeyLengths ( CCAlgorithm algorithm, NSMutableData * keyData, NSMutableData * ivData) {
NSUInteger keyLength = [ keyData length] ;
switch ( algorithm )
{
case kCCAlgorithmAES128:
{
if ( keyLength <= kCCKeySizeAES128 )
{
[ keyData setLength: kCCKeySizeAES128] ;
}
else if ( keyLength <= kCCKeySizeAES192 )
{
[ keyData setLength: kCCKeySizeAES192] ;
}
else
{
[ keyData setLength: kCCKeySizeAES256] ;
}
break ;
}
case kCCAlgorithmDES:
{
[ keyData setLength: kCCKeySizeDES] ;
break ;
}
case kCCAlgorithm3DES:
{
[ keyData setLength: kCCKeySize3DES] ;
break ;
}
case kCCAlgorithmCAST:
{
if ( keyLength < kCCKeySizeMinCAST )
{
[ keyData setLength: kCCKeySizeMinCAST] ;
}
else if ( keyLength > kCCKeySizeMaxCAST )
{
[ keyData setLength: kCCKeySizeMaxCAST] ;
}
break ;
}
case kCCAlgorithmRC4:
{
if ( keyLength >= kCCKeySizeMaxRC4 )
[ keyData setLength: kCCKeySizeMaxRC4 ] ;
break ;
}
case kCCAlgorithmRC2:
{
if ( keyLength >= kCCKeySizeMaxRC2 )
[ keyData setLength: kCCKeySizeMaxRC2 ] ;
break ;
}
default :
break ;
}
[ ivData setLength: [ keyData length] ] ;
}
3. 补全数据
static NSData * bitPadding ( CCOperation operation, CCAlgorithm algorithm, UnicomCryptoPadding padding, NSData * data) {
if ( padding == UnicomCryptoPKCS7Padding) {
return data;
}
if ( operation == kCCEncrypt && ( algorithm != kCCAlgorithmRC4) ) {
NSMutableData * sourceData = data. mutableCopy;
int blockSize = 8 ;
switch ( algorithm) {
case kCCAlgorithmAES:
blockSize = kCCBlockSizeAES128;
break ;
case kCCAlgorithmDES:
case kCCAlgorithm3DES:
case kCCAlgorithmCAST:
case kCCAlgorithmBlowfish:
default :
blockSize = 8 ;
break ;
}
switch ( padding) {
case UnicomCryptoZeroPadding:
{
int pad = 0x00 ;
int diff = blockSize - ( sourceData. length % blockSize) ;
for ( int i = 0 ; i < diff; i++ ) {
[ sourceData appendBytes: & pad length: 1 ] ;
}
}
break ;
case UnicomCryptoANSIX923Padding:
{
int pad = 0x00 ;
int diff = blockSize - ( sourceData. length % blockSize) ;
for ( int i = 0 ; i < diff - 1 ; i++ ) {
[ sourceData appendBytes: & pad length: 1 ] ;
}
[ sourceData appendBytes: & diff length: 1 ] ;
}
break ;
case UnicomCryptoISO10126Padding:
{
int diff = blockSize - ( sourceData. length % blockSize) ;
for ( int i = 0 ; i < diff - 1 ; i++ ) {
int pad = arc4random ( ) % 254 + 1 ;
[ sourceData appendBytes: & pad length: 1 ] ;
}
[ sourceData appendBytes: & diff length: 1 ] ;
}
break ;
default :
break ;
}
return sourceData;
}
return data;
}
4. 移除补全
static NSData * removeBitPadding ( CCOperation operation, CCAlgorithm algorithm, UnicomCryptoPadding padding, NSData * sourceData) {
if ( padding == UnicomCryptoPKCS7Padding) {
return sourceData;
}
if ( operation == kCCDecrypt && ( algorithm != kCCAlgorithmRC4) ) {
int correctLength = 0 ;
int blockSize = 8 ;
switch ( algorithm) {
case kCCAlgorithmAES:
blockSize = kCCBlockSizeAES128;
break ;
case kCCAlgorithmDES:
case kCCAlgorithm3DES:
case kCCAlgorithmCAST:
case kCCAlgorithmBlowfish:
default :
blockSize = 8 ;
break ;
}
Byte * testByte = ( Byte * ) [ sourceData bytes] ;
char end = testByte[ sourceData. length - 1 ] ;
if ( padding == UnicomCryptoZeroPadding && end == 0 ) {
for ( int i = ( short ) sourceData. length - 1 ; i > 0 ; i-- ) {
if ( testByte[ i] != end) {
correctLength = i + 1 ;
break ;
}
}
}
else if ( ( padding == UnicomCryptoANSIX923Padding || padding == UnicomCryptoISO10126Padding) && ( end > 0 && end < blockSize + 1 ) ) {
if ( padding == UnicomCryptoISO10126Padding || ( testByte[ sourceData. length - 2 ] == 0 && testByte[ sourceData. length - end] == 0 ) ) {
correctLength = ( short ) sourceData. length - end;
}
}
NSData * data = [ NSData dataWithBytes: testByte length: correctLength] ;
return data;
}
return sourceData;
}
5. 完成加密
- ( NSData * ) unicom_cryptoWithOperation: ( CCOperation) operation
mode: ( CCMode) mode
algorithm: ( CCAlgorithm) algorithm
padding: ( UnicomCryptoPadding) padding
iv: ( NSData * ) iv
key: ( NSData * ) key
status: ( CCCryptorStatus * ) status {
CCCryptorRef cryptor = NULL ;
CCCryptorStatus cryptorStatus = kCCSuccess;
NSMutableData * ivData = [ NSMutableData dataWithData: iv] ;
NSMutableData * keyData = [ NSMutableData dataWithData: key] ;
# if ! __has_feature ( objc_arc)
[ ivData autorelease] ;
[ keyData autorelease] ;
# endif
CCPadding cryptorPadding = ( ( padding == UnicomCryptoPKCS7Padding) ? ccPKCS7Padding : ccNoPadding) ;
SettingKeyLengths ( algorithm, keyData, ivData ) ;
NSData * sourceData = bitPadding ( operation, algorithm, padding, self ) ;
cryptorStatus = CCCryptorCreateWithMode ( operation,
mode,
algorithm,
cryptorPadding,
ivData. bytes,
keyData. bytes,
keyData. length,
NULL ,
0 ,
0 ,
kCCModeOptionCTR_BE,
& cryptor) ;
if ( cryptorStatus != kCCSuccess )
{
* status = cryptorStatus;
return ( nil ) ;
}
size_t bufsize = CCCryptorGetOutputLength ( cryptor,
( size_t) [ sourceData length] ,
true) ;
void * buf = malloc ( bufsize ) ;
size_t bufused = 0 ;
size_t bytesTotal = 0 ;
cryptorStatus = CCCryptorUpdate ( cryptor,
[ sourceData bytes] ,
( size_t) [ sourceData length] ,
buf,
bufsize,
& bufused) ;
if ( cryptorStatus != kCCSuccess )
{
free ( buf ) ;
* status = cryptorStatus;
return ( nil ) ;
}
bytesTotal + = bufused;
if ( padding == UnicomCryptoPKCS7Padding) {
cryptorStatus = CCCryptorFinal ( cryptor, buf + bufused, bufsize - bufused, & bufused ) ;
if ( cryptorStatus != kCCSuccess )
{
free ( buf ) ;
* status = cryptorStatus;
return ( nil ) ;
}
bytesTotal + = bufused;
}
NSData * result = [ NSData dataWithBytesNoCopy: buf length: bytesTotal] ;
result = removeBitPadding ( operation, algorithm, padding, result) ;
CCCryptorRelease ( cryptor ) ;
return ( result ) ;
}