Objective C - Encryption with AES256 GCM - ios

Currently I'm using the below method for Encryption
+ (NSData*) encrypt:(NSData*)plainText key:(NSData*)key iv:(NSData*)iv {
NSUInteger dataLength = [plainText length];
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. */
key.bytes, kCCKeySizeAES256, /* key and its length */
iv.bytes, /* initialization vector - use random IV everytime */
[plainText bytes], [plainText length], /* input */
buff, buffSize,/* data RETURNED */
&numBytesEncrypted);
if (status == kCCSuccess) {
return [NSData dataWithBytesNoCopy:buff length:numBytesEncrypted];
} else {
// Encryption Failed
}
free(buff);
return nil;
}
I need to use now AES256 GCM for encrypting, I don't see kCCAlgorithmAES256 in CCCrypt. Someone please guide me, I'm using the framework pod 'RNCryptor-objc'.
Below is the decrypt logic handled in backend.
public static byte[] decrypt(byte[] key, byte[] data) {
// TODO utilize GCMAES#decrypt method
try {
if (data.length < NONCE_LENGTH + TAG_LENGTH) {
throw new IllegalArgumentException("data packet too short");
}
int cipherTextLength = data.length - NONCE_LENGTH - TAG_LENGTH;
byte[] nonce = Arrays.copyOf(data, NONCE_LENGTH);
GCMBlockCipher cipher = new GCMBlockCipher(new AESFastEngine());
AEADParameters parameters = new AEADParameters(new KeyParameter(key), TAG_LENGTH * 8, nonce);
cipher.init(false, parameters);
byte[] out = new byte[cipher.getOutputSize(cipherTextLength + TAG_LENGTH)];
int pos = cipher.processBytes(data, NONCE_LENGTH, data.length - NONCE_LENGTH, out, 0);
pos += cipher.doFinal(out, pos);
return Arrays.copyOf(out, pos);
} catch (IllegalStateException | InvalidCipherTextException ex) {
throw new IllegalArgumentException(ex);
}}}

Related

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).

how to generate hash key by predefine phrase and salt value in IOS?

I have some .net code to generate hash key for encryption, i want to that code in iOS but i can't found appropriate solution, If anyone have the proper solution please help me
i add the my .net code and it is working fine, i want to convert that code in iOS with same result
Public Shared Function Encrypt(ByVal plainText As String) As String
Dim passPhrase As String = "passPhrase"
Dim saltValue As String = "saltValue"
Dim hashAlgorithm As String = "SHA256"
Dim passwordIterations As Integer = 2
Dim initVector As String = "abc123def456gh78"
Dim keySize As Integer = 256
Dim initVectorBytes As Byte() = Encoding.ASCII.GetBytes(initVector)
Dim saltValueBytes As Byte() = Encoding.ASCII.GetBytes(saltValue)
Dim plainTextBytes As Byte() = Encoding.UTF8.GetBytes(plainText)
Dim password As New PasswordDeriveBytes(passPhrase, saltValueBytes, hashAlgorithm, passwordIterations)
Dim keyBytes As Byte() = password.GetBytes(keySize \ 8)
End Function
I have also facing same issue like this and i found the solution may be it will help full for you.
Get FBEncryptorAES library from Github.
Define IV and Key as per your .net algorithms.
Use this method for encrypt and decrypt your text
+ (NSData*)encryptData:(NSData*)data
{
NSData* result = nil;
// setup output buffer
size_t bufferSize = [data length] + FBENCRYPT_BLOCK_SIZE;
void *buffer = malloc(bufferSize);
// do encrypt
size_t encryptedSize = 0;
CCCryptorStatus cryptStatus = CCCrypt(kCCEncrypt,
FBENCRYPT_ALGORITHM,
kCCOptionPKCS7Padding,
cKey,
FBENCRYPT_KEY_SIZE,
cIv,
[data bytes],
[data length],
buffer,
bufferSize,
&encryptedSize);
if (cryptStatus == kCCSuccess) {
result = [NSData dataWithBytesNoCopy:buffer length:encryptedSize];
} else {
free(buffer);
NSLog(#"[ERROR] failed to encrypt|CCCryptoStatus: %d", cryptStatus);
}
return result;
}
+ (NSData*)decryptData:(NSData*)data
{
NSData* result = nil;
// setup output buffer
size_t bufferSize = [data length] + FBENCRYPT_BLOCK_SIZE;
void *buffer = malloc(bufferSize);
// do decrypt
size_t decryptedSize = 0;
CCCryptorStatus cryptStatus = CCCrypt(kCCDecrypt,
FBENCRYPT_ALGORITHM,
kCCOptionPKCS7Padding,
cKey,
FBENCRYPT_KEY_SIZE,
cIv,
[data bytes],
[data length],
buffer,
bufferSize,
&decryptedSize);
if (cryptStatus == kCCSuccess) {
result = [NSData dataWithBytesNoCopy:buffer length:decryptedSize];
} else {
free(buffer);
NSLog(#"[ERROR] failed to decrypt| CCCryptoStatus: %d", cryptStatus);
}
return result;
}

AES Encryption not the same result iOS and Android

I've been struggling for many days now finding out how to achieve a same result when encrypting plaintext password using AES.
I have codes below in Java (Android) and Objective-C (iOS). Honestly, the ideal result is the one produced by Java because our existing passwords are encrypted with this implementation.
Hopefully someone can pin-point my error for Objective-C. I am a super newbie on this programming language, so please bear with and don't be so hard on me. :)
Many thanks!
The plain text password is:
12345abc
The Java code:
Encrypted text result is:
BS/WyqmZ6AD68YbmFERn9w==
private static String encryptionKey="ERVwiiYMFlDcZ0wp";
private static String decryptionKey="ERVwiiYMFlDcZ0wp";
JSONObject resultJSON=new JSONObject();
private static byte[] initializationVector = new byte[] { 0x01, 0x02, 0x03,
0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e,
0x0f, 0x10 };
public JSONObject encryptMethod(JSONObject jObject)
{
try {
textToEncrypt = jObject.getString("text");
textToEncrypt = replaceSlashes(textToEncrypt);
Log.d("STATE", "textToEncrypt: "+textToEncrypt);
try {
cipherText = encryptData(textToEncrypt);
Log.d("STATE", "cipherText: "+cipherText);
resultType=true;
resultData=cipherText;
resultMessage="Encryption success";
}
catch(Exception e)
{
e.printStackTrace();
resultMessage="Encryption is Not Possible, Please try some other text";
}
}
catch(Exception e)
{
e.printStackTrace();
resultMessage="Wrong Text Input, Please try again";
}
try {
resultJSON.put("type", resultType);
resultJSON.put("message", resultMessage);
resultJSON.put("data", resultData);
} catch (JSONException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
return resultJSON;
}
public static String encryptData(String plainText) {
String cipherText = null;
byte[] encryptedBytes = null;
String skeySpecString = null;
if (plainText == null || "".equals(plainText)) {
return null;
}
try {
if(encryptionKey==null || encryptionKey.equals("")) {
return null;
}
SecretKeySpec skeySpec = new SecretKeySpec(encryptionKey.getBytes(), "AES");
IvParameterSpec ivps = new IvParameterSpec(initializationVector);
Cipher cipher = Cipher.getInstance("AES/CBC/PKCS7Padding");
cipher.init(Cipher.ENCRYPT_MODE, skeySpec, ivps);
encryptedBytes = cipher.doFinal(plainText.getBytes());
encryptedBytes = Base64.encode(encryptedBytes, 0);
cipherText = new String(encryptedBytes);
} catch (BadPaddingException bpe) {
Log.e("Plain", "<===== BadPaddingException =====>", bpe);
return null;
} catch (IllegalBlockSizeException ibse) {
Log.e("Plain", "<===== BadPaddingException =====>", ibse);
return null;
} catch (InvalidAlgorithmParameterException iape) {
Log.e("Plain", "<===== InvalidAlgorithmParameterException =====>",
iape);
return null;
} catch (InvalidKeyException ike) {
Log.e("Plain", "<===== InvalidKeyException =====>", ike);
return null;
} catch (NoSuchAlgorithmException nae) {
Log.e("Plain", "<===== NoSuchAlgorithmException =====>", nae);
return null;
} catch (NoSuchPaddingException nspe) {
Log.e("Plain", "<===== NoSuchPaddingException =====>", nspe);
return null;
} catch (Exception ex) {
Log.e("Plain", "<===== Exception: {0} =====>", ex);
return null;
}
return cipherText;
}
The Objective-C code:
Encrypted text result is:
V+RZjcXVE+J1aG9kwt7CTA==
Encrypt.m file
-(NSString *) encryptData:(NSString *)plainText
{
NSString *passphrase = #"ERVwiiYMFlDcZ0wp";
NSData *key=[passphrase dataUsingEncoding:NSUTF8StringEncoding];
NSData *password = [plainText dataUsingEncoding:NSUTF8StringEncoding];
StringEncryption *crypt = [[StringEncryption alloc] init];
NSData *encryptedData = [crypt AES256EncryptWithKey:passphrase password:plainText];
NSString *ciphertext =[encryptedData base64EncodingWithLineLength:0];
return ciphertext;
}
Crypt.m file
- (NSData *)AES256EncryptWithKey:(NSString *)key password:(NSString *)plainText {
char keyPtr[kCCKeySizeAES128+1]; // room for terminator (unused)
bzero(keyPtr, sizeof(keyPtr)); // fill with zeroes (for padding)
[key getCString:keyPtr maxLength:sizeof(keyPtr) encoding:NSUTF8StringEncoding];
NSUInteger dataLength = [plainText length];
NSData *myData = [plainText dataUsingEncoding:NSUTF8StringEncoding];
const char myByteArray[] = {
0x01,0x02,0x03,0x04,
0x05,0x06,0x07,0x08,
0x09,0x0a,0x0b,0x0c,
0x0d,0x0e,0x0f,0x10 };
NSData *vector = [NSData dataWithBytes: myByteArray length:16];
size_t bufferSize = dataLength + kCCBlockSizeAES128;
void *buffer = malloc(bufferSize);
size_t numBytesEncrypted = 0;
CCCryptorStatus cryptStatus = CCCrypt(kCCEncrypt, kCCAlgorithmAES128, kCCOptionPKCS7Padding,
keyPtr, kCCKeySizeAES128,
(__bridge const void *)(vector),
myData.bytes, dataLength,
buffer, bufferSize,
&numBytesEncrypted);
if (cryptStatus == kCCSuccess) {
return [NSData dataWithBytesNoCopy:buffer length:numBytesEncrypted];
}
free(buffer);
return nil;
}

DES encrypted value mismatching android and ios

IOS code is
#import "DESCodec.h"
#import <CommonCrypto/CommonCryptor.h>
#implementation DESCodec
{
NSString *key;
}
-(id) init{
self=[super init];
if(self){
key=#"12345678";
}
return self;
}
-(NSString *) decode:(NSString *)encoded{
NSData *inputData = [[NSData alloc] initWithBase64EncodedString:encoded options:0];
NSData *keyData = [key dataUsingEncoding:NSUTF8StringEncoding];
size_t outLength;
NSMutableData *outputData = [NSMutableData dataWithLength:(inputData.length +
kCCBlockSizeDES)];
CCCryptorStatus
result = CCCrypt(kCCDecrypt, // operation
kCCAlgorithmDES, // Algorithm
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) {
return nil;
}
[outputData setLength:outLength];
return [[NSString alloc] initWithData:outputData `encoding:NSUTF8StringEncoding];`
}
-(NSString *) encode:(NSString *)decoded{
NSData *inputData = [decoded dataUsingEncoding:NSUTF8StringEncoding];
NSData *keyData = [key dataUsingEncoding:NSUTF8StringEncoding];
size_t outLength;
NSMutableData *outputData = [NSMutableData dataWithLength:(inputData.length + kCCBlockSizeDES)];
CCCryptorStatus result = CCCrypt(kCCEncrypt, // operation
kCCAlgorithmDES, // Algorithm
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) {
return nil;
}
[outputData setLength:outLength];
NSString *r = [outputData base64EncodedStringWithOptions:0];
return r;
}
#end
DESCodec *codec=[[DESCodec alloc] init];
NSString *encoded=[codec encode:#"12345678"];
NSString decoded=[codec decode:encoded];
NSLog(#" %# %#",encoded,decoded);
value is ltACiHjVjImOJQ1fTHZkSw== and 12345678
but in java encypted text is "ltACiHjVjIn+uVm31GQvyw=="
I not good in Objective C and I can't able to trigger out the problem.
can anybody please help me. Thanks and regards
Java code is
public class DESCodec {
/**
* Secret key that shall be used for encryption and decryption.
*/
private String strSecretKey = "12345678";
private static final String UNICODE_FORMAT = "UTF-8";
private static final String DES_ENCRYPTION_SCHEME = "DES";
private static final String TAG = "DESCodec";
private Cipher cipher;
private SecretKey key;
public DESCodec() {
try {
this.strSecretKey = strSecretKey;
String myEncryptionScheme = DES_ENCRYPTION_SCHEME;
byte[] keyAsBytes = strSecretKey.getBytes(UNICODE_FORMAT);
DESKeySpec myKeySpec = new DESKeySpec(keyAsBytes);
SecretKeyFactory mySecretKeyFactory = SecretKeyFactory.getInstance(myEncryptionScheme);
cipher = Cipher.getInstance(myEncryptionScheme);
key = mySecretKeyFactory.generateSecret(myKeySpec);
} catch (Exception e) {
e.printStackTrace();
}
}
public String desEncrypt(String message) {
String encryptedString = null;
try {
cipher.init(Cipher.ENCRYPT_MODE, key);
byte[] plainText = message.getBytes(UNICODE_FORMAT);
byte[] encryptedText = cipher.doFinal(plainText);
encryptedString = Base64.encodeToString(encryptedText, Base64.DEFAULT);
} catch (Exception e) {
e.printStackTrace();
}
return encryptedString;
}
public String desDecrypt(String message) {
String decryptedText = null;
try {
cipher.init(Cipher.DECRYPT_MODE, key);
byte[] encryptedText = Base64.decode(message, Base64.DEFAULT);
byte[] plainText = cipher.doFinal(encryptedText);
decryptedText = bytes2String(plainText);
} catch (Exception e) {
e.printStackTrace();
}
return decryptedText;
}
private String bytes2String(byte[] bytes) {
try {
return new String(bytes, UNICODE_FORMAT);
} catch (UnsupportedEncodingException e) {
e.printStackTrace();
}
return null;
}
}
It's obviously only a problem with the mode of operation, because the first block matches. In Java you're using ECB mode, because "DES" defaults to "DES/ECB/PKCS5Padding". I think that CCCryptor defaults to CBC.
Don't ever use ECB mode. It's not semantically secure. You need to use at least CBC mode with a random IV. The IV doesn't have to be secret, so you can prepend it to the ciphertext. Please look at RNCryptor that has additional security features like authentication of ciphertext. It also has a Java implementation.
Don't use DES anymore. It's not secure anymore. You should use AES. Triple DES is also not that bad.
I hava the same problem when i develop an iOS app.And the android client is used by many people, so i couldn't change the algorithm to AES or others.As Artjom B. said in Java 'DES' defaults to 'DES/ECB/PKCS5Padding', in the source you can find that
Cipher c1 = Cipher.getInstance("DES/ECB/PKCS5Padding");
but unfortunately in iOS you just find that
enum {
kCCOptionPKCS7Padding = 0x0001,
kCCOptionECBMode = 0x0002
}
But finally i find a solution like this
CCCryptorStatus cryptStatus = CCCrypt(kCCDecrypt,
kCCAlgorithmDES,
kCCOptionPKCS7Padding | kCCOptionECBMode,
[key UTF8String],
kCCKeySizeDES,
nil,
[cipherData bytes],
[cipherData length],
buffer,
1024,
&numBytesDecrypted);
The importance is kCCOptionPKCS7Padding | kCCOptionECBMode, you can try this method.

Reading an Encrypted data from a txt file and decrypting it in ios

I Using AES128 Encryption and Decryption Technique for reading an encrypted text from a Text File
and Decrypting but i am unable to decrypt it.
The Data in Text file is Encrypted using AES128 in C#
I am using the following code to decrypt it
Kindly help i am new to Encryption and Decryption in AES12*
- (NSData *)doCipher:(NSData *)plainText key:(NSData *)aSymmetricKey
context:(CCOperation)encryptOrDecrypt padding:(CCOptions *)pkcs7
{
CCCryptorStatus ccStatus = kCCSuccess;
// Symmetric crypto reference.
CCCryptorRef thisEncipher = NULL;
// Cipher Text container.
NSData * cipherOrPlainText = nil;
// Pointer to output buffer.
uint8_t * bufferPtr = NULL;
// Total size of the buffer.
size_t bufferPtrSize = 0;
// Remaining bytes to be performed on.
size_t remainingBytes = 0;
// Number of bytes moved to buffer.
size_t movedBytes = 0;
// Length of plainText buffer.
size_t plainTextBufferSize = 0;
// Placeholder for total written.
size_t totalBytesWritten = 0;
// A friendly helper pointer.
uint8_t * ptr;
// Initialization vector; dummy in this case 0's.
uint8_t iv[kChosenCipherBlockSize];
memset((void *) iv, 0x0, (size_t) sizeof(iv));
NSLog(#"doCipher: plaintext: %#", plainText);
NSLog(#"doCipher: key length: %d", [aSymmetricKey length]);
//LOGGING_FACILITY(plainText != nil, #"PlainText object cannot be nil." );
//LOGGING_FACILITY(aSymmetricKey != nil, #"Symmetric key object cannot be nil." );
//LOGGING_FACILITY(pkcs7 != NULL, #"CCOptions * pkcs7 cannot be NULL." );
//LOGGING_FACILITY([aSymmetricKey length] == kChosenCipherKeySize, #"Disjoint choices for key size." );
plainTextBufferSize = [plainText length];//+kCCBlockSizeAES128;
//LOGGING_FACILITY(plainTextBufferSize > 0, #"Empty plaintext passed in." );
NSLog(#"pkcs7: %d", *pkcs7);
// We don't want to toss padding on if we don't need to
if(encryptOrDecrypt == kCCEncrypt)
{
if(*pkcs7 != kCCOptionECBMode)
{
if((plainTextBufferSize % kChosenCipherBlockSize) == 0)
{
*pkcs7 = 0x0000;
}
else
{
*pkcs7 = kCCOptionPKCS7Padding;
}
}
}
else if(encryptOrDecrypt != kCCDecrypt)
{
NSLog(#"Invalid CCOperation parameter [%d] for cipher context.", *pkcs7 );
}
// Create and Initialize the crypto reference.
ccStatus = CCCryptorCreate(encryptOrDecrypt,
kCCAlgorithmAES128,
*pkcs7,
(const void *)[aSymmetricKey bytes],
kChosenCipherKeySize,
(const void *)iv,
&thisEncipher
);
//LOGGING_FACILITY1( ccStatus == kCCSuccess, #"Problem creating the context, ccStatus == %d.", ccStatus );
// Calculate byte block alignment for all calls through to and including final.
bufferPtrSize = CCCryptorGetOutputLength(thisEncipher, plainTextBufferSize, true);
// Allocate buffer.
bufferPtr = malloc( bufferPtrSize * sizeof(uint8_t) );
// Zero out buffer.
memset((void *)bufferPtr, 0x0, bufferPtrSize);
// Initialize some necessary book keeping.
ptr = bufferPtr;
// Set up initial size.
remainingBytes = bufferPtrSize;
// Actually perform the encryption or decryption.
ccStatus = CCCryptorUpdate(thisEncipher,
(const void *) [plainText bytes],
plainTextBufferSize,
ptr,
remainingBytes,
&movedBytes
);
//LOGGING_FACILITY1( ccStatus == kCCSuccess, #"Problem with CCCryptorUpdate, ccStatus == %d.", ccStatus );
// Handle book keeping.
ptr += movedBytes;
remainingBytes -= movedBytes;
totalBytesWritten += movedBytes;
/* From CommonCryptor.h:
#enum CCCryptorStatus
#abstract Return values from CommonCryptor operations.
#constant kCCSuccess Operation completed normally.
#constant kCCParamError Illegal parameter value.
#constant kCCBufferTooSmall Insufficent buffer provided for specified operation.
#constant kCCMemoryFailure Memory allocation failure.
#constant kCCAlignmentError Input size was not aligned properly.
#constant kCCDecodeError Input data did not decode or decrypt properly.
#constant kCCUnimplemented Function not implemented for the current algorithm.
enum {
kCCSuccess = 0,
kCCParamError = -4300,
kCCBufferTooSmall = -4301,
kCCMemoryFailure = -4302,
kCCAlignmentError = -4303,
kCCDecodeError = -4304,
kCCUnimplemented = -4305
};
typedef int32_t CCCryptorStatus;
*/
// Finalize everything to the output buffer.
ccStatus = CCCryptorFinal(thisEncipher,
ptr,
remainingBytes,
&movedBytes
);
totalBytesWritten += movedBytes;
if(thisEncipher) {
(void) CCCryptorRelease(thisEncipher);
thisEncipher = NULL;
}
//LOGGING_FACILITY1( ccStatus == kCCSuccess, #"Problem with encipherment ccStatus == %d", ccStatus );
if (ccStatus == kCCSuccess)
cipherOrPlainText = [NSData dataWithBytes:(const void *)bufferPtr length:(NSUInteger)totalBytesWritten];
else
cipherOrPlainText = nil;
if(bufferPtr) free(bufferPtr);
NSString *string = [[NSString alloc] initWithData:cipherOrPlainText encoding:NSUTF8StringEncoding];
return cipherOrPlainText;
/*
Or the corresponding one-shot call:
ccStatus = CCCrypt( encryptOrDecrypt,
kCCAlgorithmAES128,
typeOfSymmetricOpts,
(const void *)[self getSymmetricKeyBytes],
kChosenCipherKeySize,
iv,
(const void *) [plainText bytes],
plainTextBufferSize,
(void *)bufferPtr,
bufferPtrSize,
&movedBytes
);
*/
}

Resources