问题
I am using the CommonCrypto CCCryptorCreate to decrypt a message. I am using a password and an IV but it always returns nil.
If I use the CCCryptorCreate to decrypt, but don't use an IV on during encryption on the RUBY side and don't use the IV on the obj-c decrypt side then decryption works perfectly and I can see the message.
But if I use an IV on the RUBY and IV on the obj-c side decryption ends with a nil message object.
I am using this Encrypt in Objective-C / Decrypt in Ruby using anything
OBJ-C method:
- (NSData *) decryptedDataUsingAlgorithm: (CCAlgorithm) algorithm
key: (id) key // data or string
initializationVector: (id) iv // data or string
options: (CCOptions) options
error: (CCCryptorStatus *) error
{
CCCryptorRef cryptor = NULL;
CCCryptorStatus status = kCCSuccess;
NSParameterAssert([key isKindOfClass: [NSData class]] || [key isKindOfClass: [NSString class]]);
NSParameterAssert(iv == nil || [iv isKindOfClass: [NSData class]] || [iv isKindOfClass: [NSString class]]);
NSMutableData * keyData, * ivData;
if ( [key isKindOfClass: [NSData class]] )
keyData = (NSMutableData *) [key mutableCopy];
else
keyData = [[key dataUsingEncoding: NSUTF8StringEncoding] mutableCopy];
if ( [iv isKindOfClass: [NSString class]] )
ivData = [[iv dataUsingEncoding: NSUTF8StringEncoding] mutableCopy];
else
ivData = (NSMutableData *) [iv mutableCopy]; // data or nil
#if !__has_feature(objc_arc)
[keyData autorelease];
[ivData autorelease];
#endif
// ensure correct lengths for key and iv data, based on algorithms
FixKeyLengths( algorithm, keyData, ivData );
status = CCCryptorCreate( kCCDecrypt, algorithm, options,
[keyData bytes], [keyData length], [ivData bytes],
&cryptor );
if ( status != kCCSuccess )
{
if ( error != NULL )
*error = status;
return ( nil );
}
NSData * result = [self _runCryptor: cryptor result: &status];
if ( (result == nil) && (error != NULL) )
*error = status;
CCCryptorRelease( cryptor );
return ( result );
}
=== DOES NOT WORK ====
NSData * result = [self decryptedDataUsingAlgorithm: kCCAlgorithmAES128
key: [[password dataUsingEncoding:NSUTF8StringEncoding] SHA256Hash]
initializationVector: [anIV dataUsingEncoding:NSUTF8StringEncoding]
options: kCCOptionPKCS7Padding
error: &status];
=== DOES WORK ===
NSData * result = [self decryptedDataUsingAlgorithm: kCCAlgorithmAES128
key: [[password dataUsingEncoding:NSUTF8StringEncoding] SHA256Hash]
initializationVector: nil
options: kCCOptionPKCS7Padding
error: &status];
回答1:
Looks like the iv may be different, ensure that the data bytes are the same and the length is correct.
You want CCCrypt
to do one-shot encryption.
From Apple: CCCrypt
is a Stateless, one-shot encrypt or decrypt operation. This basically performs a sequence of CCCrytorCreate()
, CCCryptorUpdate()
, CCCryptorFinal()
, and CCCryptorRelease()
.
Since you are not using CCCrypt
then you will have to at least add CCCryptorFinal()
to your example.
Also note that the key and iv really need to be exactly the correct size in bytes. Using NSUTF8StringEncoding
may not produce the number of bytes expected if there are some characters that require multiple byte encodings. Note: "i" can be encoded as a surrogate pair.
Do not use a password string without using PBKDF2
to generate a good key.
Consider using RNCryptor unless you really know what you are doing with crypto.
Here is simple example code of a one-shot encrypt/decrypy method
The key and iv must be exactly the required length.
Any encoding (Base64, NSString, etc) is done outside of this method.
+ (NSData *)doCipher:(NSData *)dataIn
iv:(NSData *)iv
key:(NSData *)symmetricKey
context:(CCOperation)encryptOrDecrypt // kCCEncrypt or kCCDecrypt
error:(NSError **)error
{
CCCryptorStatus ccStatus = kCCSuccess;
size_t cryptBytes = 0;
NSMutableData *dataOut = [NSMutableData dataWithLength:dataIn.length + kCCBlockSizeAES128];
ccStatus = CCCrypt( encryptOrDecrypt,
kCCAlgorithmAES128,
kCCOptionPKCS7Padding,
symmetricKey.bytes,
kCCKeySizeAES128,
iv.bytes,
dataIn.bytes,
dataIn.length,
dataOut.mutableBytes,
dataOut.length,
&cryptBytes);
if (ccStatus == kCCSuccess) {
dataOut.length = cryptBytes;
}
else {
if (error) {
*error = [NSError errorWithDomain:@"kEncryptionError"
code:ccStatus
userInfo:nil];
}
dataOut = nil;
}
return dataOut;
}
来源:https://stackoverflow.com/questions/24456020/using-commoncrypto-with-an-iv-but-always-returning-nil