Ok, I'm using the SSCrypto framework and I've added the relevant Cocoa code below...
We're using the test code that comes with SSCrpyto (in particular des3):
// Test 2: Symmetric encryption and decryption using various ciphers
//NSData *seedData1 = [SSCrypto getKeyDataWithLength:32];
NSData *seedData1 = [@"passwordDR0wSS@P6660juht" dataUsingEncoding:NSUTF8StringEncoding];
crypto = [[SSCrypto alloc] initWithSymmetricKey:seedData1];
NSArray *ciphers = [NSArray arrayWithObjects:@"aes256", @"aes128", @"blowfish", @"aes192",
@"RC4", @"blowfish", @"RC5", @"des3", @"des", nil];
NSString *password = @"secret";
[crypto setClearTextWithString:password];
for(n = 0; n < [ciphers count]; n++)
{
NSData *cipherText = [crypto encrypt:[ciphers objectAtIndex:n]];
NSData *clearText = [crypto decrypt:[ciphers objectAtIndex:n]];
NSLog(@"Original password: %@", password);
NSLog(@"Cipher text: '%@' using %@", [cipherText encodeBase64WithNewlines:NO], [ciphers objectAtIndex:n]);
NSLog(@"Clear text: '%s' using %@", [clearText bytes], [ciphers objectAtIndex:n]);
NSLog(@" ");
}
NSLog(@" ");
NSLog(@" ");
[crypto release];
And then here is the actual encrypt function in the SSCrypto framework that we're using... We have made modifications like I mentioned above to skip EVP_BytesToKey():
// If there is no clear text set, or the clear text is an empty string (zero length data)
// then there is nothing to encrypt, and we may as well return nil
if(clearText == nil || [clearText length] == 0)
{
return nil;
}
unsigned char *input = (unsigned char *)[clearText bytes];
//unsigned char *outbuf, iv[EVP_MAX_IV_LENGTH];
unsigned char *outbuf;
int outlen, templen, inlen;
inlen = [clearText length];
if([self isSymmetric])
{
// Perform symmetric encryption...
// unsigned char evp_key[EVP_MAX_KEY_LENGTH] = {"\0"};
EVP_CIPHER_CTX cCtx;
const EVP_CIPHER *cipher;
if (cipherName){
cipher = EVP_get_cipherbyname((const char *)[cipherName UTF8String]);
if (!cipher){
NSLog(@"cannot get cipher with name %@", cipherName);
return nil;
}
} else {
cipher = EVP_bf_cbc();
if (!cipher){
NSLog(@"cannot get cipher with name %@", @"EVP_bf_cbc");
return nil;
}
}
EVP_CIPHER_CTX_init(&cCtx);
NSData *testEVPKeyData = [self symmetricKey];
NSString *testEVPKeyString = [testEVPKeyData encodeBase64];
NSData *testIvData = [@"password" dataUsingEncoding:NSUTF8StringEncoding];
NSString *testIvString = [testIvData encodeBase64];
NSLog(@"\nevp_key: %@\niv: %@", testEVPKeyString, testIvString);
if (!EVP_EncryptInit(&cCtx, cipher, [testEVPKeyData bytes], [testIvData bytes])) {
NSLog(@"EVP_EncryptInit() failed!");
EVP_CIPHER_CTX_cleanup(&cCtx);
return nil;
}
EVP_CIPHER_CTX_set_key_length(&cCtx, EVP_MAX_KEY_LENGTH);
// add a couple extra blocks to the outbuf to be safe
outbuf = (unsigned char *)calloc(inlen + EVP_CIPHER_CTX_block_size(&cCtx), sizeof(unsigned char));
NSAssert(outbuf, @"Cannot allocate memory for buffer!");
if (!EVP_EncryptUpdate(&cCtx, outbuf, &outlen, input, inlen)){
NSLog(@"EVP_EncryptUpdate() failed!");
EVP_CIPHER_CTX_cleanup(&cCtx);
return nil;
}
if (!EVP_EncryptFinal(&cCtx, outbuf + outlen, &templen)){
NSLog(@"EVP_EncryptFinal() failed!");
EVP_CIPHER_CTX_cleanup(&cCtx);
return nil;
}
outlen += templen;
EVP_CIPHER_CTX_cleanup(&cCtx);
}
else
{
// Irrelevant code
}
// Store the encrypted data as the cipher text
[self setCipherText:[NSData dataWithBytes:outbuf length:outlen]];
// Release the outbuf, since it was malloc'd
if(outbuf) {
free(outbuf);
}
return [self cipherTextAsData];