iOS 中的 3DES 每次加载时提供不同的加密值



任何人都可以告诉我为什么 iOS 中的 3des 每次在 iOS 中加载时都会产生不同的编码字符串? 最初,我将"key"转换为 MD5 格式的字符串,然后在 3des 中使用相同的键来生成编码值。

这是我的代码:

-(NSData *)tripleDesEncryptString:(NSString *)input key:(NSString* )key error:(NSError **)error{
    //TDES
    NSParameterAssert(input);
    NSParameterAssert(key);
    NSData *inputData = [input dataUsingEncoding:NSUTF8StringEncoding];
    NSData *keyData = [key dataUsingEncoding:NSUTF8StringEncoding];
    size_t outLength;
    //NSAssert(keyData.length == kCCKeySize3DES, @"the keyData is an invalid size");
    NSMutableData *outputData = [NSMutableData dataWithLength:(inputData.length  +  kCCBlockSize3DES)];
    CCCryptorStatus result = CCCrypt(
        kCCEncrypt, // operation
        kCCAlgorithm3DES, // Algorithm
        kCCOptionECBMode | kCCOptionPKCS7Padding, // options
        keyData.bytes, // key
        keyData.length, // keylength
        nil, // iv
        inputData.bytes, // dataIn
        inputData.length, // dataInLength,
        outputData.mutableBytes, // dataOut
        outputData.length, // dataOutAvailable
        &outLength // dataOutMoved
    );
    if (result != kCCSuccess) {
        if (error != NULL) {
            *error = [NSError errorWithDomain:@"com.your_domain.your_project_name.your_class_name." code:result userInfo:nil];
        }
        return nil;
    }
    [outputData setLength:outLength];
    return outputData;
}
-(void) testEncryptionAndDecryption {
    NSString *str =@"ker!@#$%^&*()";
    id md5data =[str MD5];
    NSString *md5dataString =(NSString *)md5data;
    NSData *encrypted = [self tripleDesEncryptString:@"abcdef@dd.com:123" key:md5dataString error:nil];
    NSString *strData = [encrypted  base64EncodedStringWithOptions:0];
    NSLog(@"encrypted data length: %@",strData);
    NSString *str2 = [[NSString alloc] initWithData:encrypted encoding:NSUTF8StringEncoding];
    NSLog(@"%@",str2);
}

测试代码有缺陷。

NSString *str =@"ker!@#$%^&*()";
id md5data =[str MD5];
NSString *md5dataString =(NSString *)md5data;

目前还不清楚MD5是什么,可能是一个类别?

MD5函数生成 16 字节结果,但 3DES 需要 24 字节密钥。

NSString *str2 = [[NSString alloc] initWithData:encrypted encoding:NSUTF8StringEncoding];将失败,因为任意数据可以机器人表示为字符串。这就是使用 Base64 的原因。

实际上,最好编写一个加密方法,该方法获取并返回NSData参数,并在它之外执行任何字符串操作。这就产生了单一责任方法。

这是一个重构的版本 - 但仍然不安全:

-(NSData *)tripleDesEncryptData:(NSData *)data
                            key:(NSData* )key
                          error:(NSError **)error {
    NSParameterAssert(data);
    NSParameterAssert(key);
    NSAssert(key.length == kCCKeySize3DES, @"the keyData is an invalid size");
    size_t outLength;
    NSMutableData *outputData = [NSMutableData dataWithLength:(data.length  +  kCCBlockSize3DES)];
    CCCryptorStatus
    result = CCCrypt(kCCEncrypt, // operation
                     kCCAlgorithm3DES, // Algorithm
                     kCCOptionECBMode | kCCOptionPKCS7Padding , // options
                     key.bytes, // key
                     key.length, // keylength
                     nil,// iv
                     data.bytes, // dataIn
                     data.length, // dataInLength,
                     outputData.mutableBytes, // dataOut
                     outputData.length, // dataOutAvailable
                     &outLength); // dataOutMoved
    if (result != kCCSuccess) {
        if (error != NULL) {
            *error = [NSError errorWithDomain:@"com.your_domain.your_project_name.your_class_name."
                                         code:result
                                     userInfo:nil];
        }
        return nil;
    }
    [outputData setLength:outLength];
    return outputData;
}
- (NSData *)hash192String:(NSString *)inputString {
    NSData *inputData = [inputString dataUsingEncoding:NSUTF8StringEncoding];
    NSMutableData *hash = [NSMutableData dataWithLength:CC_SHA256_DIGEST_LENGTH];
    CC_SHA256(inputData.bytes, (unsigned int)inputData.length, hash.mutableBytes);
    return [hash subdataWithRange:NSMakeRange(0, 24)];
}

-(void) testEncryptionAndDecryption {
    NSString *md5String  = @"ker!@#$%^&*()";
    NSString *stringData = @"abcdef@dd.com:123";
    NSData *keyData   = [self hash192String:md5String];
    NSData *data      = [stringData dataUsingEncoding:NSUTF8StringEncoding];
    NSData *encrypted = [self tripleDesEncryptData:data key:keyData error:nil];
    NSString *encryptedBase64 = [encrypted  base64EncodedStringWithOptions:0];
    NSLog(@"encrypted base64nlength: %lunstring: %@", (unsigned long)encryptedBase64.length, encryptedBase64);
}

输出:

加密底座64
长度: 32
string: +VSdzF4BmAMnGITAWFqaY2mgp8Nr8I13

func testCrypt(data:NSData, keyData:NSData, ivData:NSData) -> String {
    var base64cryptString = String()
    let cryptData    = NSMutableData(length: Int(data.length) + kCCBlockSizeAES128)!
    let keyLength              = size_t(kCCKeySizeAES128)
    let operation: CCOperation = UInt32(kCCEncrypt)
    let algoritm:  CCAlgorithm = UInt32(kCCAlgorithmAES128)
    let options:   CCOptions   = UInt32(kCCOptionPKCS7Padding)
    var numBytesEncrypted :size_t = 0
    let cryptStatus = CCCrypt(operation,
                              algoritm,
                              options,
                              keyData.bytes, keyLength,
                              ivData.bytes,
                              data.bytes, data.length,
                              cryptData.mutableBytes, cryptData.length,
                              &numBytesEncrypted)
    if UInt32(cryptStatus) == UInt32(kCCSuccess) {
        cryptData.length = Int(numBytesEncrypted)
        base64cryptString = cryptData.base64EncodedString(options: .endLineWithLineFeed)
    }
    return base64cryptString
}

您可以通过传递需要加密的数据以及 NSData 格式的密钥和值来调用func testCrypt(data:NSData, keyData:NSData, ivData:NSData)

例如:

let data: NSData! = message.data(using: .utf8) as NSData!; 
let keyData: NSData! = keyValue.data(using: .utf8) as NSData!; 
let ivData: NSData! = ivValue.data(using: .utf8) as NSData!;
var base64cryptString = self.testCrypt(data: data, keyData: keyData, ivData: ivData)

最新更新