RNCryptor: get public key as NSString - ios

I'm successfully encrypting/decrypting data in iOS using RNCryptor.
I'm trying to get the public key to send to a server, so it can encrypt some data.
NSString *saltString = #"salt'n'peppa";
NSData *salt = [saltString dataUsingEncoding:NSUTF8StringEncoding];
NSData *key = [RNCryptor keyForPassword:password
salt:salt
settings:kRNCryptorAES256Settings.keySettings];
At this point, key has some data in it. However, I can't seem to work out how to get the public key as a string:
NSString *publicKey = [[NSString alloc] initWithData:key encoding:NSUTF8StringEncoding];
I've tried different encodings but nothing seems to work.
Here is the keyForPassword method from RNCryptor:
+ (NSData *)keyForPassword:(NSString *)password salt:(NSData *)salt settings:(RNCryptorKeyDerivationSettings)keySettings
{
NSMutableData *derivedKey = [NSMutableData dataWithLength:keySettings.keySize];
// See Issue #77. V2 incorrectly calculated key for multi-byte characters.
NSData *passwordData;
if (keySettings.hasV2Password) {
passwordData = [NSData dataWithBytes:[password UTF8String] length:[password length]];
}
else {
passwordData = [password dataUsingEncoding:NSUTF8StringEncoding];
}
// Use the built-in PBKDF2 if it's available. Otherwise, we have our own. Hello crazy function pointer.
int result;
int (*PBKDF)(CCPBKDFAlgorithm algorithm, const char *password, size_t passwordLen,
const uint8_t *salt, size_t saltLen,
CCPseudoRandomAlgorithm prf, uint rounds,
uint8_t *derivedKey, size_t derivedKeyLen);
PBKDF = CCKeyDerivationPBKDF ?: RN_CCKeyDerivationPBKDF;
result = PBKDF(keySettings.PBKDFAlgorithm, // algorithm
passwordData.bytes, // password
passwordData.length, // passwordLength
salt.bytes, // salt
salt.length, // saltLen
keySettings.PRF, // PRF
keySettings.rounds, // rounds
derivedKey.mutableBytes, // derivedKey
derivedKey.length); // derivedKeyLen
// Do not log password here
NSAssert(result == kCCSuccess, #"Unable to create AES key for password: %d", result);
return derivedKey;
}
I get the feeling I'm doing something majorly wrong as googling comes up with very little.

The key isn't a string, it's data. Just a random (sort of) series of bytes. The only real way to convert it to a string to send to a server would be to encode the bytes. A common method would be to use a base 64 encoding. Then the server could covert the base 64 encoded string back into the raw bytes of the key.

Related

Objective C- RSA digital signature from objective c sent to JAVA server can't be verified

Im generating and signing data with RSA private key from objective C,
and sending signed data with string RSA public key to JAVA server,
then the server must be verifying the signed data with the public key I provided,
but it always fails.
Can anyone tell me what is wrong with the codes on Objective C side.
Here's how I'm generating RSA key pairs
KeyChainWrapper* keychainTemp = [[KeyChainWrapper alloc] initWithService:[NSString stringWithFormat:#"SS%#TEMP", KEYCHAINSERVICEID] withGroup:nil];
NSDictionary* attributes =
#{ (id)kSecAttrKeyType: (id)kSecAttrKeyTypeRSA,
(id)kSecAttrKeySizeInBits: #2048
};
CFErrorRef cfError = NULL;
SecKeyRef privateKeySec = SecKeyCreateRandomKey((__bridge CFDictionaryRef)attributes, &cfError);
if (!privateKeySec) {
CFBridgingRelease(cfError);
return;
}
SecKeyRef publicKeySec = SecKeyCopyPublicKey(privateKeySec);
NSData* dataPublicKey = (__bridge_transfer NSData *)SecKeyCopyExternalRepresentation(publicKeySec, &cfError);
NSData* dataPrivateKey = (__bridge_transfer NSData *)SecKeyCopyExternalRepresentation(privateKeySec, &cfError);
if (dataPublicKey && dataPrivateKey) {
[keychainTemp insert:[NSString stringWithFormat:#"%#RSAPUBKEYTEMP", strType] DATA:dataPublicKey];
[keychainTemp insert:[NSString stringWithFormat:#"%#RSAPRIKEYTEMP", strType] DATA:dataPrivateKey];
}
if (publicKeySec) { CFRelease(publicKeySec); }
if (privateKeySec) { CFRelease(privateKeySec); }
then convert dataPublicKey to strPublicKey to send to the server,
and here's how I sign the data.
strRsaSign = [self sha256HashFor:[NSString stringWithFormat:#"%#%#%#%#", userId, systemId, [self SSGET_UNIQUE_DEVICE], strPublicKey]];
NSData* dataStrRSASign = [strRsaSign dataUsingEncoding:NSUTF8StringEncoding];
size_t signatureBytesSize = SecKeyGetBlockSize(privateKey);
uint8_t *signatureBytes = (uint8_t *)malloc(signatureBytesSize * sizeof(uint8_t));
memset((void *)signatureBytes, 0x0, signatureBytesSize);
OSStatus status = SecKeyRawSign(privateKey,
kSecPaddingPKCS1,
(unsigned char *)dataStrRSASign.bytes,
dataStrRSASign.length,
signatureBytes,
&signatureBytesSize
);
base64StrRSASign = [[NSData dataWithBytes:signatureBytes length:signatureBytesSize] base64EncodedStringWithOptions:0];
And then, I send the base64StrRSASign and strPublicKey to the server,
to let server verifies the base64StrRSASign with strPublicKey.
What can I possibly be missing here if anyone can tell me...

AES encryption on iOS and android, output and buffer size is different

Implementing AES256 on iOS using CCCrypt function. But output and output buffer length is different than Android.
Cipher class in Android produces 48 bytes data where in iOS we get 80 bytes data.
In IOS using kCCAlgorithmAES, kCCOptionPKCS7Padding and in android using AES/CBC/PKCS5Padding.
in IOS IV is NULL and in android creating iv as new 16 bytes array.
Please help.
please find input and code for reference.
- (void)viewDidLoad {
[super viewDidLoad];
NSString *message = [NSString stringWithFormat:#"com.myapp.com|355004059196637|911111111111|11341e5e-9643-4559-bbb7-34d40555e96c"];
NSString *key = [NSString stringWithFormat:#"4f28d5901b4b7b80d33fda76ca372c2a20bd1a6c2aad7fa215dc79d507330678"];
NSString *shaEncryptMessage = [self sha256:message length:0];
NSData *aesEncryptData = [self aesEncrypt:[shaEncryptMessage dataUsingEncoding:NSUTF8StringEncoding] key:key iv:nil];
NSString *hMac = [aesEncryptData base64EncodedStringWithOptions:NSDataBase64Encoding64CharacterLineLength];
NSLog(#"hMac = %#",hMac);
// IOS output : Can+oQR79D3/lsQGctzY/d2VBNZbWWtJxGI8iRIu80R2yTskn9gf2oKHaRESX73u
// LpJHLx1Xr6iH11jFPlmqwW7mQz0xAW4uACNAMEoZ0kY=
// Android output : MiMDkdo5cGsPMj2qCnNobgp7dr5KMvBhGuKTonrqr1lCYte/kKegGMtI/4TPhUNI
}
- (NSString*) sha256:(NSString *)key length:(NSInteger) length{
const char *s=[key cStringUsingEncoding:NSASCIIStringEncoding];
NSData *keyData=[NSData dataWithBytes:s length:strlen(s)];
uint8_t digest[CC_SHA256_DIGEST_LENGTH]={0};
CC_SHA256(keyData.bytes, (unsigned int)keyData.length, digest);
NSData *out=[NSData dataWithBytes:digest length:CC_SHA256_DIGEST_LENGTH];
NSString *hash=[out description];
hash = [hash stringByReplacingOccurrencesOfString:#" " withString:#""];
hash = [hash stringByReplacingOccurrencesOfString:#"<" withString:#""];
hash = [hash stringByReplacingOccurrencesOfString:#">" withString:#""];
return hash;
}
- (NSData *)aesEncrypt:(NSData *)plainText key:(NSString *)key iv:(NSString *)iv {
char keyPointer[kCCKeySizeAES256+2],// room for terminator (unused) ref: https://devforums.apple.com/message/876053#876053
ivPointer[kCCBlockSizeAES128];
BOOL patchNeeded;
bzero(keyPointer, sizeof(keyPointer)); // fill with zeroes for padding
//key = [[StringEncryption alloc] md5:key];
key = [self stringFromHex:key];
patchNeeded= ([key length] > kCCKeySizeAES256+1);
if(patchNeeded)
{
key = [key substringToIndex:kCCKeySizeAES256]; // Ensure that the key isn't longer than what's needed (kCCKeySizeAES256)
}
[key getCString:keyPointer maxLength:sizeof(keyPointer) encoding:NSUTF8StringEncoding];
[iv getCString:ivPointer maxLength:sizeof(ivPointer) encoding:NSUTF8StringEncoding];
// if (patchNeeded) {
// keyPointer[0] = '\0'; // Previous iOS version than iOS7 set the first char to '\0' if the key was longer than kCCKeySizeAES256
// }
NSUInteger dataLength = [plainText length];
// For block ciphers, the output size will always be less than or equal to the input size plus the size of one block.
size_t buffSize = dataLength + kCCBlockSizeAES128;
void *buff = malloc(buffSize);
size_t numBytesEncrypted = 0;
CCCryptorStatus status = CCCrypt(kCCEncrypt, /* kCCEncrypt, etc. */
kCCAlgorithmAES128, /* kCCAlgorithmAES128, etc. */
kCCOptionPKCS7Padding, /* kCCOptionPKCS7Padding, etc. */
keyPointer, kCCKeySizeAES256, /* key and its length */
NULL, /* initialization vector - use random IV everytime */
[plainText bytes], [plainText length], /* input */
buff, buffSize,/* data RETURNED here */
&numBytesEncrypted);
if (status == kCCSuccess) {
return [NSData dataWithBytesNoCopy:buff length:numBytesEncrypted];
}
free(buff);
return nil;
}
- (NSString *) stringFromHex:(NSString *)str
{
NSMutableData *stringData = [[NSMutableData alloc] init];
unsigned char whole_byte;
char byte_chars[3] = {'\0','\0','\0'};
int i;
for (i=0; i < [str length] / 2; i++) {
byte_chars[0] = [str characterAtIndex:i*2];
byte_chars[1] = [str characterAtIndex:i*2+1];
whole_byte = strtol(byte_chars, NULL, 16);
[stringData appendBytes:&whole_byte length:1];
}
return [[NSString alloc] initWithData:stringData encoding:NSASCIIStringEncoding];
}
Please find android code also,
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
generateHMAC();
}
String K0 = "4f28d5901b4b7b80d33fda76ca372c2a20bd1a6c2aad7fa215dc79d507330678";
String generatedString = "com.myapp.com|355004059196637|911111111111|11341e5e-9643-4559-bbb7-34d40555e96c";
private void generateHMAC() {
Log.d("Message of Hash", generatedString);
byte[] var14 = new byte[0];
try {
var14 = SHA256(generatedString);
byte[] var15 = new byte[0];
var15 = encrypt(var14, hexStringToByteArray(K0));
String var4 = Base64.encodeToString(var15, 2);
Log.d("Existing K0", K0);
Log.d("HMAC", var4);
} catch (Exception e) {
e.printStackTrace();
}
}
public byte[] SHA256(String paramString) throws Exception {
MessageDigest md = MessageDigest.getInstance("SHA-256");
md.update(paramString.getBytes("UTF-8"));
byte[] digest = md.digest();
return digest;
}
public byte[] encrypt(byte[] var1, byte[] var2) throws Exception {
SecretKeySpec var3 = new SecretKeySpec(var2, "AES");
byte[] var4 = new byte[16];
IvParameterSpec var5 = new IvParameterSpec(var4);
Cipher var6 = Cipher.getInstance("AES/CBC/PKCS5Padding");
var6.init(1, var3, var5);
byte[] var7 = var6.doFinal(var1);
return var7;
}
public byte[] hexStringToByteArray(String var1) {
byte[] var2 = new byte[var1.length() / 2];
for (int var3 = 0; var3 < var2.length; ++var3) {
int var4 = var3 * 2;
int var5 = Integer.parseInt(var1.substring(var4, var4 + 2), 16);
var2[var3] = (byte) var5;
}
return var2;
}
Updates after you provided iOS code:
The aesEncryptData should be your output. Get rid of the hmac, that has nothing to do with AES encryption (instead, it is for message integrity).
The only way you are going to match your Android code is if you are using the same IV that the Android code is using.
Earlier reply:
How long is the input? Providing source code and sample data may help us solve the problem quicker.
Without the requested information, I don't have your answer, but I have a few pointers that might help you get to the bottom of it:
Your padding is okay. PKCS5Padding in Java is wrongly named implementation of PKCS#7, so it should be compatible with Apple's kCCOptionPKCS7Padding.
Apple by default uses CBC mode under the hood if no mode is specified, so that agrees with the Android code. So that cannot be the problem either.
When you encrypt, the ciphertext will be a multiple of 16 bytes (because AES has N=16 bytes block size and according to defn of PKCS #7). Specifically:
If the input is a multiple of 16 bytes, then the output should be exactly 16 bytes more than the input.
If the input is not a multiple of 16 bytes, then the output should be 16*Ceiling(Input length/16). Example: 47 byte input should be 16*Ceiling(17/16) = 16*3 = 48 byte output.
It is possible that one of the implementations is outputting the IV as part of the ciphertext. If this is happening, it should be at the beginning of the ciphertext. You should be able to test to see if this is happening. (Let me know if that is happening please)
Having said that, something is weird and likely implemented wrong, and we need the code to get to the bottom of it. It makes no sense that the Android code results in 3 blocks of 16 whereas the Apple code results in 5 blocks of 16.
Also, as I commented above, even though Apple tells you that the IV is optional, they mean that it is optional in terms of getting the code to work. It is not optional for security. IVs are required and must be unpredictable for CBC mode of operation, and they should never be repeated. If you ignore that, you leak information about your data, and in some situations, an attacker may be able to decrypt the data (padding oracle attacks).

Decrypting data with CCCryptor in Objective-C that was encrypted with CFB in Go

I've been working on this for a long time, but am stuck.
I'm writing an iOS app that takes AES encrypted data form a Go server-side application and decrypts it. I'm using CCCryptor for the decryption on the iOS side. However, I cannot, for the life of me, get plaintext out. There is a working Java/Android implementation, and it decrypts fine on the Go side, so I'm pretty sure it's to do with my CCCryptor settings.
I'm actually getting a 0 success status on decryption, but taking the output and doing a NSString initWithBytes gives me a null string.
Note: I'm only writing the iOS side.
Go code that encrypts:
func encrypt(key, text []byte) []byte {
block, err := aes.NewCipher(key)
if err != nil {
panic(err)
}
b := encodeBase64(text)
ciphertext := make([]byte, aes.BlockSize+len(b))
iv := ciphertext[:aes.BlockSize]
if _, err := io.ReadFull(rand.Reader, iv); err != nil {
panic(err)
}
cfb := cipher.NewCFBEncrypter(block, iv)
cfb.XORKeyStream(ciphertext[aes.BlockSize:], []byte(b))
return ciphertext
}
Objective-C code that decrypts
+ (NSData *)decrypt:(NSData*)data withPassword:(NSString*)password{
NSData * key = [password dataUsingEncoding:NSUTF8StringEncoding];
size_t dataLength = [data length] - kCCBlockSizeAES128;
NSData *iv = [data subdataWithRange:NSMakeRange(0, kCCBlockSizeAES128)];
NSData *encrypted = [data subdataWithRange:NSMakeRange(kCCBlockSizeAES128, dataLength)];
//See the doc: For block ciphers, the output size will always be less than or
//equal to the input size plus the size of one block.
//That's why we need to add the size of one block here
// size_t bufferSize = dataLength + kCCBlockSizeAES128;
// void *buffer = malloc(dataLength);
NSMutableData *ret = [NSMutableData dataWithLength:dataLength + kCCBlockSizeAES128];
size_t numBytesDecrypted = 0;
CCCryptorStatus status = CCCrypt(kCCDecrypt, kCCAlgorithmAES,
0x0000, // change to 0 solve the problem
[key bytes],
kCCKeySizeAES256,
[iv bytes],
[encrypted bytes], dataLength, /* input */
[ret mutableBytes], [ret length], /* output */
&numBytesDecrypted
);
NSLog(#"err: %d", status);
NSLog(#"dataLength: %d, num: %d", (int)dataLength, (int)numBytesDecrypted);
if (status == kCCSuccess) {
//the returned NSData takes ownership of the buffer and will free it on deallocation
return ret;
}
// free(buffer); //free the buffer;
return nil;
}
My recommendation is to use RNCryptor, there is an iOS and a Go implementation available.
RNCryptor combines all the necessary cryptographic primitives for your needs including:
AES-256 encryption (Advanced Encryption Standard)
CBC mode (Cipher Block Chaining)
Password stretching with PBKDF2 (Password Based Key Derivation Function 2)
Password salting
Random IV (Initialization Vector)
Encrypt-then-hash HMAC (Authentication)
It has been extensively deployed and vetted.
It is all to easy to get cryptography wrong and using RNCryptor will avoid the potential pitfalls.
If I had the cryptographic needs you have I would use it.

Encrypt and decrypt a random NSString with AES128 CTR in iOS with a given key

I'm not sure how secure is my solution.
Rob Napier has an extraordinary Framework (RNCryptor) to encrypt and decrypt in iOS and other systems.
As far as I know, he is using AES-CBC, that in fact is the standard of CommonCryptor.h
However, my requirements, has forced me to use AES-CTR. Both are really similar, so in theory it had to be something easy. But was not.
There is a lack of information around CommonCryptor.h. It is one of the worst explained frameworks ever.
Working with CBC you just need to call CCCrypt(). However, to work with CTR you should call: CCCrytorCreate(), CCCryptorUpdate(), CCCryptorFinal() and CCCryptorRelease()
Trying to encrypt my data, I was receiving different data every time, of course decrypting it had incorrect results.
I had 2 big problems in my first approach: the length of the key and the number of bytes written to dataOut.
I sorted the problems with:
1.- A NSString key of 32 characters
NSString *key = #"1234567890ABCDEFGHIJKLMNOPQRSTUV";
2.- To cut dataOut with needed length
Finally this is my code to Encrypt and Decrypt:
#import <CommonCrypto/CommonCryptor.h>
#import <CommonCrypto/CommonKeyDerivation.h>
#import <Security/Security.h>
+ (NSMutableData*) encryptString: (NSString*) stringToEncrypt withKey: (NSString*) keyString
{
//Key to Data
NSData *key = [keyString dataUsingEncoding:NSUTF8StringEncoding];
//String to encrypt to Data
NSData *data = [stringToEncrypt dataUsingEncoding:NSUTF8StringEncoding];
// Init cryptor
CCCryptorRef cryptor = NULL;
// Alloc Data Out
NSMutableData *cipherData = [NSMutableData dataWithLength:data.length + kCCBlockSizeAES128];
//Empty IV: initialization vector
NSMutableData *iv = [NSMutableData dataWithLength:kCCBlockSizeAES128];
//Create Cryptor
CCCryptorStatus create = CCCryptorCreateWithMode(kCCEncrypt,
kCCModeCTR,
kCCAlgorithmAES,
ccPKCS7Padding,
iv.bytes, // can be NULL, because null is full of zeros
key.bytes,
key.length,
NULL,
0,
0,
kCCModeOptionCTR_BE,
&cryptor);
if (create == kCCSuccess)
{
//alloc number of bytes written to data Out
size_t outLength;
//Update Cryptor
CCCryptorStatus update = CCCryptorUpdate(cryptor,
data.bytes,
data.length,
cipherData.mutableBytes,
cipherData.length,
&outLength);
if (update == kCCSuccess)
{
//Cut Data Out with nedded length
cipherData.length = outLength;
//Final Cryptor
CCCryptorStatus final = CCCryptorFinal(cryptor, //CCCryptorRef cryptorRef,
cipherData.mutableBytes, //void *dataOut,
cipherData.length, // size_t dataOutAvailable,
&outLength); // size_t *dataOutMoved)
if (final == kCCSuccess)
{
//Release Cryptor
//CCCryptorStatus release =
CCCryptorRelease(cryptor ); //CCCryptorRef cryptorRef
}
return cipherData;
}
}
else
{
//error
}
return nil;
}
+ (NSString*) decryptData: (NSData*) data withKey: (NSString*) keyString
{
//Key to Data
NSData *key = [keyString dataUsingEncoding:NSUTF8StringEncoding];
// Init cryptor
CCCryptorRef cryptor = NULL;
//Empty IV: initialization vector
NSMutableData *iv = [NSMutableData dataWithLength:kCCBlockSizeAES128];
// Create Cryptor
CCCryptorStatus createDecrypt = CCCryptorCreateWithMode(kCCDecrypt, // operation
kCCModeCTR, // mode CTR
kCCAlgorithmAES, // Algorithm
ccPKCS7Padding, // padding
iv.bytes, // can be NULL, because null is full of zeros
key.bytes, // key
key.length, // keylength
NULL, //const void *tweak
0, //size_t tweakLength,
0, //int numRounds,
kCCModeOptionCTR_BE, //CCModeOptions options,
&cryptor); //CCCryptorRef *cryptorRef
if (createDecrypt == kCCSuccess)
{
// Alloc Data Out
NSMutableData *cipherDataDecrypt = [NSMutableData dataWithLength:data.length + kCCBlockSizeAES128];
//alloc number of bytes written to data Out
size_t outLengthDecrypt;
//Update Cryptor
CCCryptorStatus updateDecrypt = CCCryptorUpdate(cryptor,
data.bytes, //const void *dataIn,
data.length, //size_t dataInLength,
cipherDataDecrypt.mutableBytes, //void *dataOut,
cipherDataDecrypt.length, // size_t dataOutAvailable,
&outLengthDecrypt); // size_t *dataOutMoved)
if (updateDecrypt == kCCSuccess)
{
//Cut Data Out with nedded length
cipherDataDecrypt.length = outLengthDecrypt;
// Data to String
NSString* cipherFinalDecrypt = [[NSString alloc] initWithData:cipherDataDecrypt encoding:NSUTF8StringEncoding];
//Final Cryptor
CCCryptorStatus final = CCCryptorFinal(cryptor, //CCCryptorRef cryptorRef,
cipherDataDecrypt.mutableBytes, //void *dataOut,
cipherDataDecrypt.length, // size_t dataOutAvailable,
&outLengthDecrypt); // size_t *dataOutMoved)
if (final == kCCSuccess)
{
//Release Cryptor
//CCCryptorStatus release =
CCCryptorRelease(cryptor); //CCCryptorRef cryptorRef
}
return cipherFinalDecrypt;
}
}
else
{
//error
}
return nil;
}
To call it:
NSString *key = #"1234567890ABCDEFGHIJKLMNOPQRSTUV";
NSString *stringToEncrypt = #"Gabriel.Massana";
NSData* encrypted = [GM_AES128_CTR encryptString:stringToEncrypt withKey:key];
NSString *decrypted = [GM_AES128_CTR decryptData:encrypted withKey:key];
I'm posting my solution because there are not to much questions for AES CTR in Stackoverflow. Likewise, if someone want to check it and tell me if something is wrong will be very appreciated.
My example in GitHub
How secure is this solution? It is easy to crack the system? What are my possibilities to add more security to AES-CTR?
I'm listing this as a separate answer, but I'm just amplifying what Zaph has already said:
This is totally broken encryption.
It's not surprising that this has happened to you. It is a very common problem when you try to build your own scheme. There are just a lot of places you can mess up. But I don't want to understate just how insecure this scheme is. It is really, really broken.
CTR cannot ever repeat the same nonce+key, and you reuse the nonce every time. This is very different from CBC. In CBC if you reuse the IV, then you make it somewhat easier on the attacker to break your encryption. In CTR, if you reuse the nonce+key it is pretty easy to decrypt the message once you have a few ciphertexts. Some good discussion can be found in RFC3686.
When used correctly, AES-CTR provides a high level of
confidentiality. Unfortunately, AES-CTR is easy to use incorrectly.
Being a stream cipher, any reuse of the per-packet value, called the
IV, with the same nonce and key is catastrophic. An IV collision
immediately leaks information about the plaintext in both packets.
For this reason, it is inappropriate to use this mode of operation
with static keys. Extraordinary measures would be needed to prevent
reuse of an IV value with the static key across power cycles. To be
safe, implementations MUST use fresh keys with AES-CTR. The Internet
Key Exchange (IKE) [IKE] protocol can be used to establish fresh
keys. IKE can also provide the nonce value.
Note that RNCryptor originally used CTR. I moved back to CBC on the recommendation of Apple after talking with them about how hard easy it is to screw up CTR. If you can avoid CTR, you absolutely should. It is extremely useful for certain problems, but for general file encryption it is seldom appropriate.
That said, I understand you have a problem in the chip. How is your chip going to get its key? It seems strange to use symmetric encryption with a chip this way. In any case, RNCryptor v1 may meet your needs. You'd likely need to use encryptFromStream:toStream:encryptionKey:HMACKey:error: since I assume the chip can't handle PBKDF2.
Trying to encrypt my data, I was receiving different data every time, of course decrypting it had incorrect results.
Any good encryption system will have this property. That's why you need to send your nonce/IV (and if you use passwords, salts) along with the ciphertext.
NSString *key = #"1234567890ABCDEFGHIJKLMNOPQRSTUV";
This is not a key. This is a password and dramatically reduces your available keyspace. Keys are typically going to be NSData since they need to be chosen over all possible values, not just ASCII.

3DES Encryption / Decryption using ECB in iOS

i'm making an application , in which i have to encrypt a string using 3DES encryption in ECB mode. i m using "mykey" as a key.
+ (NSData *)tripleDesEncryptData:(NSData *)inputData
key:(NSData *)keyData
error:(NSError **)error
{
NSParameterAssert(inputData);
NSParameterAssert(keyData);
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
0, // 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];
NSLog(#"here is my output %#",outputData);
return outputData;
}
i am getting an exception because of invalid Key size. (i'm using this 'mykey' as my key). I'm not expert in encryption. Any kind of Help will be highly appreciated.
You're getting "invalid key size" because, well, your key is an invalid size. I'm not sure what else you were expecting the system to tell you. The 3DES algorithm expects a key size of 24 bytes and "mykey" is too short.
Even apart from the length issue, in general it is a bad idea to directly use strings as cryptographic keys. Instead you should use an accepted password-to-key algorithm such as PBKDF2.

Resources