Crypto

定义Padding

typedef enum : NSUInteger {
    UnicomCryptoNoPadding       = 0, // No Padding to source Data
    UnicomCryptoPKCS7Padding    = 1, // PKCS_7 | Each byte fills in the length of the sequence of the bytes .  ***This Padding Mode  use the system method.***
    UnicomCryptoZeroPadding     = 2, // 0x00 Padding |  Each byte fills 0x00
    UnicomCryptoANSIX923Padding = 3, // The last byte fills the length of the byte sequence, and the remaining bytes are filled with 0x00.
    UnicomCryptoISO10126Padding = 4, // The last byte fills the length of the byte sequence, and the remaining bytes fill the random data.
} UnicomCryptoPadding;

对齐iv和key

static void SettingKeyLengths(CCAlgorithm algorithm, NSMutableData *keyData, NSMutableData *ivData) {
    NSUInteger keyLength = [keyData length];
    switch ( algorithm )
    {
        case kCCAlgorithmAES128:
        {
            // 16
            if ( keyLength <= kCCKeySizeAES128 )
            {
                [keyData setLength: kCCKeySizeAES128];
            }
            // 24
            else if ( keyLength <= kCCKeySizeAES192 )
            {
                [keyData setLength: kCCKeySizeAES192];
            }
            // 32
            else
            {
                [keyData setLength: kCCKeySizeAES256];
            }
            
            break;
        }
            
        case kCCAlgorithmDES:
        {
            // 8
            [keyData setLength: kCCKeySizeDES];
            break;
        }
            
        case kCCAlgorithm3DES:
        {
            //24
            [keyData setLength: kCCKeySize3DES];
            break;
        }
            
        case kCCAlgorithmCAST:
        {
            //[5,16]
            if ( keyLength < kCCKeySizeMinCAST )
            {
                [keyData setLength: kCCKeySizeMinCAST];
            }
            // 16
            else if ( keyLength > kCCKeySizeMaxCAST )
            {
                [keyData setLength: kCCKeySizeMaxCAST];
            }
            
            break;
        }
            
        case kCCAlgorithmRC4:
        {
            // [1,512]
            if ( keyLength >= kCCKeySizeMaxRC4 )
                [keyData setLength: kCCKeySizeMaxRC4 ];
            break;
        }
        case kCCAlgorithmRC2:
        {
            // [1,128]
            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;
                //            case CcCryptorPKCS7Padding:
                //            {
                //                int diff =  blockSize - ([sourceData length] % blockSize);
                //                for (int i = 0; i <diff; i++) {
                //                    [sourceData appendBytes:&diff length:1];
                //                }
                //
                //            }
            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 == CcCryptorZeroPadding && end == 0) || (padding == ccPKCS7Padding && (end > 0 && end < blockSize + 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);
    
    // ensure correct lengths for key and iv data, based on algorithms
    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;
    
    // From Brent Royal-Gordon (Twitter: architechies):
    //  Need to update buf ptr past used bytes when calling CCCryptorFinal()
   
    //  It is not necessary to call CCCryptorFinal() when performing
    //symmetric encryption or decryption if padding is disabled, or
    //   when using a stream cipher.
    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 );
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值