2016-05-27 11 views
2

Ich habe eine Anwendung für Android in Java erstellt und Cipher Klasse verwendet, um Daten mit AES zu verschlüsseln. Jetzt möchte ich diesen Algorithmus in iOS mit CommonCrypto Klasse nehmen. Der Code funktioniert, hat aber unterschiedliche Ergebnisse.AES CBC Verschlüsselung mit PKCS7Padding hat unterschiedliche Ergebnisse in Java und Objective-C

Dies ist der Code in Java:

+ (NSString*)AES256EncryptData:(NSString*)data WithKey:(NSString*)key { 
    char keyPtr[kCCKeySizeAES128]; // room for terminator (unused) 
    bzero(keyPtr, sizeof(keyPtr)); // fill with zeroes (for padding) 

    // fetch key data 
    [key getCString:keyPtr maxLength:sizeof(keyPtr) encoding:NSUTF8StringEncoding]; 

    NSUInteger dataLength = data.length; 

    size_t bufferSize   = dataLength + kCCBlockSizeAES128; 
    void* buffer    = malloc(bufferSize); 

    size_t numBytesEncrypted = 0; 
    CCCryptorStatus cryptStatus = CCCrypt(kCCEncrypt, kCCAlgorithmAES128, kCCOptionPKCS7Padding, 
              keyPtr, kCCKeySizeAES256, 
              NULL /* initialization vector (optional) */, 
              data.UTF8String, dataLength, /* input */ 
              buffer, bufferSize, /* output */ 
              &numBytesEncrypted); 

    if (cryptStatus == kCCSuccess) { 
     return [[NSData dataWithBytesNoCopy:buffer length:numBytesEncrypted] base64EncodedStringWithOptions:NSDataBase64EncodingEndLineWithCarriageReturn]; 
    } 

    free(buffer); //free the buffer; 
    return nil; 
} 

+ (NSString*)AES256DecryptData:(NSString*)data WithKey:(NSString*)key { 
    char keyPtr[kCCKeySizeAES256 + 1]; // room for terminator (unused) 
    bzero(keyPtr, sizeof(keyPtr)); // fill with zeroes (for padding) 

    // fetch key data 
    [key getCString:keyPtr maxLength:sizeof(keyPtr) encoding:NSUTF8StringEncoding]; 

    NSUInteger dataLength = data.length; 

    size_t bufferSize   = dataLength + kCCBlockSizeAES128; 
    void* buffer    = malloc(bufferSize); 

    size_t numBytesDecrypted = 0; 
    CCCryptorStatus cryptStatus = CCCrypt(kCCDecrypt, kCCAlgorithmAES128, kCCOptionPKCS7Padding, 
              keyPtr, kCCKeySizeAES256, 
              NULL /* initialization vector (optional) */, 
              data.UTF8String, dataLength, /* input */ 
              buffer, bufferSize, /* output */ 
              &numBytesDecrypted); 

    if (cryptStatus == kCCSuccess) { 
     return [[NSData dataWithBytesNoCopy:buffer length:numBytesDecrypted] base64EncodedStringWithOptions:NSDataBase64EncodingEndLineWithCarriageReturn]; 
    } 

    free(buffer); //free the buffer; 
    return nil; 
} 

Update 1:

Daten: text to encrypt

public static String Decrypt(String text, String key) throws Exception { 
    Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding"); 
    byte[] keyBytes = new byte[16]; 
    byte[] b = key.getBytes("UTF-8"); 
    int len = b.length; 
    if (len > keyBytes.length) 
     len = keyBytes.length; 
    System.arraycopy(b, 0, keyBytes, 0, len); 
    SecretKeySpec keySpec = new SecretKeySpec(keyBytes, "AES"); 
    IvParameterSpec ivSpec = new IvParameterSpec(keyBytes); 
    cipher.init(Cipher.DECRYPT_MODE, keySpec, ivSpec); 
    byte[] results = new byte[text.length()]; 
    BASE64Decoder decoder = new BASE64Decoder(); 
    try { 
     results = cipher.doFinal(decoder.decodeBuffer(text)); 
    } catch (Exception e) { 
     System.out.print("Erron in Decryption"); 
    } 
    return new String(results, "UTF-8"); 
} 

public static String Encrypt(String text, String key) throws Exception { 
    Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding"); 
    byte[] keyBytes = new byte[16]; 
    byte[] b = key.getBytes("UTF-8"); 
    int len = b.length; 
    if (len > keyBytes.length) 
     len = keyBytes.length; 
    System.arraycopy(b, 0, keyBytes, 0, len); 
    SecretKeySpec keySpec = new SecretKeySpec(keyBytes, "AES"); 
    IvParameterSpec ivSpec = new IvParameterSpec(keyBytes); 
    System.out.println(keyBytes); 
    System.out.println(keySpec); 
    System.out.println(ivSpec); 
    cipher.init(Cipher.ENCRYPT_MODE, keySpec, ivSpec); 

    byte[] results = cipher.doFinal(text.getBytes("UTF-8")); 
    BASE64Encoder encoder = new BASE64Encoder(); 
    return encoder.encode(results); 
} 

Dies ist der Code in Objective-C ist

Key: testkey

Java (gewünschte) Ergebnis: 7ptTEyImNz9KgC96+JPFXQ==

Objective-C Ergebnis: U7FAVHi01q0Hhf+m9NsKjw==

+0

Bitte senden Sie die Ergebnisse und das gewünschte Ergebnis in ObjC können Sie eine zufällige iv mit SecRandomCopyBytes erstellen. –

+0

@JulienLopez Bearbeiten Sie die Post mit Beispieldaten –

+1

** Super unsicheren Code oben. Benutze niemals deinen Schlüssel oder irgendeinen Teil davon als IV, EVER. ** –

Antwort

1

Ihr Problem ist mit dem Objective-C-Code. Sie sollten dieselbe Methode sowohl in Java als auch in Obj-C verwenden. Sie können diesen Code verwenden, um es die gleichen Ergebnisse zu machen zurückgeben:

AES.h

#import <Foundation/Foundation.h> 
#import <CommonCrypto/CommonCrypto.h> 

@interface AES : NSObject 

+ (NSData *)Encrypt:(NSString *)data WithKey:(NSString *)key; 
+ (NSString *)Decrypt:(NSData *)data WithKey:(NSString *)key; 

+ (NSData *)AESOperation:(CCOperation)operation OnData:(NSData *)data key:(NSString *)key; 

@end 

AES.m

#import "AES.h" 

@implementation AES 

+ (NSData *)Encrypt:(NSString *)data WithKey:(NSString *)key { 
    return [self AESOperation:kCCEncrypt OnData:[data dataUsingEncoding:NSUTF8StringEncoding] key:key]; 
} 
+ (NSString *)Decrypt:(NSData *)data WithKey:(NSString *)key { 
    return [[NSString alloc] initWithData:[self AESOperation:kCCDecrypt OnData:data key:key] encoding:NSUTF8StringEncoding]; 
} 

+ (NSData *)AESOperation:(CCOperation)operation OnData:(NSData *)data key:(NSString *)key { 
    char keyPtr[kCCKeySizeAES128]; 
    bzero(keyPtr, sizeof(keyPtr)); 
    [key getCString:keyPtr maxLength:sizeof(keyPtr) encoding:NSUTF8StringEncoding]; 

    NSUInteger dataLength = [data length]; 
    size_t bufferSize = dataLength + kCCBlockSizeAES128; 
    void *buffer = malloc(bufferSize); 

    size_t numBytesEncrypted = 0; 
    CCCryptorStatus cryptStatus = CCCrypt(operation, 
              kCCAlgorithmAES128, 
              kCCOptionPKCS7Padding, 
              keyPtr, 
              kCCBlockSizeAES128, 
              keyPtr, 
              [data bytes], 
              dataLength, 
              buffer, 
              bufferSize, 
              &numBytesEncrypted); 
    if (cryptStatus == kCCSuccess) { 
     return [NSData dataWithBytesNoCopy:buffer length:numBytesEncrypted]; 
    } 

    free(buffer); 
    return nil; 
} 

@end 
+0

Verwenden Sie nicht den Schlüssel für die iv, müssen sie anders sein und die iv sollte für jede Verschlüsselung anders sein. Der iv muss nicht geheim sein. – zaph

+0

@zaph ich bin damit einverstanden, aber hier, ich habe gerade den Java-Code für ihn übersetzt –

+0

danke es funktioniert für mich – SM18

0

Im Java-Code, erhalten Sie einen IV-Parameter verwenden:

IvParameterSpec ivSpec = new IvParameterSpec(keyBytes); 

In Objective C ist der IV-Parameter auf NULL festgelegt:

CCCrypt(.., NULL /* initialization vector (optional) */, 

Abgesehen davon sollte der IV-Parameter einige zufällige Werte und nicht Sie geheimer Schlüssel (oder ein Teil davon) sein. Die Idee ist es, verschiedene Chiffre Text outpout und Blockmuster-Matching

+0

Wie kann ich diesen IV in Obj-C haben?Entschuldigung, ich bin neu in Kryptographie –

+0

Es gibt viele Beispiele im Internet oder Stackoverflow (dh http://StackOverflow.com/Questions/36229572/How-to-Send-nsdata-as-Skey-and-iv-for-Ccrcrypt). Wenn Sie dasselbe Ergebnis in ObjectiveC und Java möchten, müssen Sie dieselbe Logik anwenden, um Ihre IV zu erhalten. Wie bereits erwähnt, ist es besser, die IV zufällig zu halten –

0

Sie benötigen einen iv hinzufügen der ObjC-Code, nicht NULL.

Verwenden Sie nicht den Schlüssel für die iv, sondern erstellen Sie eine iv zufällige Bytes, vor der verschlüsselten Daten für die Entschlüsselung.

uint8_t iv[kCCBlockSizeAES128]; 
SecRandomCopyBytes(kSecRandomDefault, kCCBlockSizeAES128, iv); 

Ausgabe::

iv: 8617dcf92de01ac2c0b92763b206b3f5