AES-256-CBC Verschlüsselung Java/Objective-C

Diese Seite verwendet Cookies. Durch die Nutzung unserer Seite erklären Sie sich damit einverstanden, dass wir Cookies setzen. Weitere Informationen

  • AES-256-CBC Verschlüsselung Java/Objective-C

    Hallo zusammen,
    ich muß Dateien/Text verschlüsseln bzw. entschlüsseln die mit folgenden Java Code generiert bzw. wieder entschlüsselt werden (MacOSX <=> java Applikation): Hier der Java-Code:

    Quellcode

    1. try {
    2. String text = "Test";
    3. String pw = "1234567812345678";
    4. String iv = "1234567812345678";
    5. byte[] data = text.getBytes("UTF-8");
    6. Cipher cipher = Cipher.getInstance( "AES/CBC/PKCS5Padding" );
    7. Key key = new SecretKeySpec( pw.getBytes("UTF-8"),0,16, "AES" ); // key muss 16 Byte lang sein !
    8. IvParameterSpec ivParameterSpec = new IvParameterSpec(iv.getBytes("UTF-8") );
    9. cipher.init(Cipher.ENCRYPT_MODE, key , ivParameterSpec);
    10. byte[] verschlüsselt = cipher.doFinal( text.getBytes("UTF8") );
    11. String encryptedString = new String(Base64.getEncoder().encode(verschlüsselt),"UTF-8");
    12. System.out.println(encryptedString);
    13. //outout: yhkFI8IuDFpT62URI28XlQ==
    14. }
    15. catch(Exception e) {
    16. System.out.println("Es ist ein Fehler aufgetreten:");
    17. e.printStackTrace();
    18. }
    Alles anzeigen



    In Objective-C versuche ich jetzt die gleiche Verschlüsselung/Entschlüsselung hinzubekommen, bei der Verschlüsselung bekomme ein Anderen Ausgabe String: Hier der Objective-C Code:

    Quellcode

    1. @implementation NSData (MyCrypt)
    2. #define key @"1234567812345678"
    3. #define iv @"1234567812345678"
    4. - (NSData *) cryptOperation:(CCOperation)operation
    5. {
    6. // 'key' should be 32 bytes for AES256, will be null-padded otherwise
    7. //char keys[kCCKeySizeAES256 + 1];
    8. char keys[16 + 1];
    9. [key getCString:keys maxLength:sizeof(keys) encoding:NSUTF8StringEncoding];
    10. // Perform PKCS7Padding on the key.
    11. unsigned long bytes_to_pad = sizeof(keys) - [key length];
    12. if (bytes_to_pad > 0)
    13. {
    14. char byte = bytes_to_pad;
    15. for (unsigned long i = sizeof(keys) - bytes_to_pad; i < sizeof(keys); i++)
    16. keys[i] = byte;
    17. }
    18. NSUInteger dataLength = [self length];
    19. //See the doc: For block ciphers, the output size will always be less than or
    20. //equal to the input size plus the size of one block.
    21. //That's why we need to add the size of one block here
    22. size_t bufferSize = dataLength + kCCBlockSizeAES128;
    23. void *buffer = malloc(bufferSize);
    24. size_t numBytesDecrypted = 0;
    25. CCCryptorStatus status = CCCrypt(operation, kCCAlgorithmAES128,kCCOptionPKCS7Padding,
    26. keys,kCCKeySizeAES256,
    27. [iv UTF8String],
    28. [self bytes], dataLength, /* input */
    29. buffer, bufferSize, /* output */
    30. &numBytesDecrypted);
    31. if (status == kCCSuccess)
    32. {
    33. //the returned NSData takes ownership of buffer and will free it on dealloc
    34. return [NSData dataWithBytesNoCopy:buffer length:numBytesDecrypted];
    35. }
    36. free(buffer); //free the buffer;
    37. return nil;
    38. }
    39. - (NSData *)AES256Encrypt
    40. {
    41. return [self cryptOperation:kCCEncrypt];
    42. }
    43. - (NSData *)AES256Decrypt
    44. {
    45. return [self cryptOperation:kCCDecrypt];
    46. }
    Alles anzeigen

    (Erweiterung für NSData) und rufe folgende Funktionen auf:

    Quellcode

    1. // Auszug ...
    2. + (NSString *)encrypt:(NSString *)string
    3. {
    4. NSData *data = [string dataUsingEncoding:NSUTF8StringEncoding];
    5. NSData *dataEncrypted = [data AES256Encrypt];
    6. NSString *strRecordEncrypted = [dataEncrypted base64EncodedStringWithOptions:0];
    7. return strRecordEncrypted;
    8. }
    9. + (NSString *)decrypt:(NSString *)string
    10. {
    11. if([string containsString:@"\n"] || [string containsString:@"\t"])
    12. {
    13. string = [[string componentsSeparatedByCharactersInSet:[NSCharacterSet newlineCharacterSet]] componentsJoinedByString:@""];
    14. string = [string stringByReplacingOccurrencesOfString:@"\t" withString:@""];
    15. }
    16. NSData *keyData = [[NSData alloc] initWithBase64EncodedString:string options:0];
    17. NSData *dataDecrypted = [keyData AES256Decrypt];
    18. NSString *receivedDataDecryptString = [[NSString alloc]initWithData:dataDecrypted encoding:NSUTF8StringEncoding];
    19. return receivedDataDecryptString;
    20. }
    21. - (IBAction)doCryptAction:(id)sender {
    22. NSString *text = [self.textField stringValue];
    23. NSString *crypt = [MyCrypt encrypt:text];
    24. [self.cryptTextField setStringValue:crypt];
    25. }
    26. - (IBAction)decyrpytAction:(id)sender {
    27. NSString *crypt = [self.cryptTextField stringValue];
    28. NSString *decrypt = [MyCrypt decrypt:crypt];
    29. [self.decrypttextField setStringValue:decrypt];
    30. }
    Alles anzeigen

    Ausgabe Obj-C: tyjRv4y7aIE2fMlFRHje9w==
    Mein Problem jetzt, Java und Objective-C liefern mir unterschiedliche Ausgaben für das Verschlüsseln. Die Anforderungen laut Java-Code: AES-256-CBC, mit einem Key von 16Byte und dem IV mit 16Byte, diese Angaben sind auf beiden Seiten gleich, meine ich ...

    Hat jemand schon ein ähnlichen problem gehabt oder sieht den Fehler, den ich vor lauter Bäumen wahrscheinlich nicht sehe ... :/
    Danke ...
    Si tacuisses, philosophus mansisses !
  • FRing schrieb:


    Ausgabe Obj-C: tyjRv4y7aIE2fMlFRHje9w==
    Mein Problem jetzt, Java und Objective-C liefern mir unterschiedliche Ausgaben für das Verschlüsseln. Die Anforderungen laut Java-Code: AES-256-CBC, mit einem Key von 16Byte und dem IV mit 16Byte, diese Angaben sind auf beiden Seiten gleich, meine ich ...
    Ich denke, dass die Angaben nicht auf beiden Seiten gleich sind:
    Der Java-Code verwendet offenbar AES/CBC/PKCS5Padding.
    Der Objective-C Code AES-128 (statt 256 wie der Betreff andeutet) und PKCS7Padding.

    Da im Objective-C Code
    // 'key' should be 32 bytes for AES256, will be null-padded otherwise
    steht, vermute ich, dass auch der Java-Code AES-128 nutzt.
    Bleibt die Abweichung beim Padding und evtl. ist CBC im Objective-C Code auch nicht
    aktiv - wird zumindest nicht aus den Argumenten her klar.
  • Hallo marco,
    das hatte ich mir auch schon gedacht. Ich habe 'gegoogelt' und es ist wahrscheinlich wirklich so, das hier die Angabe in Java richtig ist, den PKCS7Padding mit PKCS5Padding gleichbehandelt wird ... Ich weiß, das sieht komisch aus ...
    Aber danke erstmal für den Hinweis.
    Gruß
    Si tacuisses, philosophus mansisses !
  • Hallo MCDan,
    ich habe die Lösung von deinem erste Link benutzt, musste aber ein wenig Hand anlegen, weil nur Keys mit einer Länge von 16 Byte funktionieren (IV und Keys 16 Byte lang). Was auch schlecht dokumentiert ist die Verwendung des iv. Default ist dieser Null (nil) auf der Objective-C Seite. Ich setze diesen zusätzlich mit der Verwendung eines 256-Hash. Wenn jemand interessiert ist, stelle ich den Code für Java und Objective-C gerne zur verfügung.
    Danke nochmal und grüße !

    Auszug AES-Crypt (NSData+CommonCrypto.m)

    Quellcode

    1. @implementation NSData (CommonCryptor)
    2. - (NSData *) AES256EncryptedDataUsingKey: (id) key error: (NSError **) error
    3. {
    4. CCCryptorStatus status = kCCSuccess;
    5. /*
    6. NSData * result = [self dataEncryptedUsingAlgorithm: kCCAlgorithmAES128
    7. key: key
    8. options: kCCOptionPKCS7Padding
    9. error: &status];
    10. */
    11. NSString *_t = @"1234567812345678";
    12. NSData *iv = [[_t dataUsingEncoding:NSUTF8StringEncoding] SHA256Hash];
    13. NSData *result = [self dataEncryptedUsingAlgorithm:kCCAlgorithmAES128
    14. key:key
    15. initializationVector:iv
    16. options:kCCOptionPKCS7Padding
    17. error:&status];
    18. if ( result != nil )
    19. return ( result );
    20. if ( error != NULL )
    21. *error = [NSError errorWithCCCryptorStatus: status];
    22. return ( nil );
    23. }
    24. - (NSData *) decryptedAES256DataUsingKey: (id) key error: (NSError **) error
    25. {
    26. CCCryptorStatus status = kCCSuccess;
    27. /*
    28. NSData * result = [self decryptedDataUsingAlgorithm: kCCAlgorithmAES128
    29. key: key
    30. options: kCCOptionPKCS7Padding
    31. error: &status];
    32. */
    33. NSString *_t = @"1234567812345678";
    34. NSData *iv = [[_t dataUsingEncoding:NSUTF8StringEncoding] SHA256Hash];
    35. NSData *result = [self decryptedDataUsingAlgorithm:kCCAlgorithmAES128
    36. key:key
    37. initializationVector:iv
    38. options:kCCOptionPKCS7Padding
    39. error:&status];
    40. if ( result != nil )
    41. return ( result );
    42. if ( error != NULL )
    43. *error = [NSError errorWithCCCryptorStatus: status];
    44. return ( nil );
    45. }
    Alles anzeigen
    Java:


    Java-Quellcode

    1. import java.io.UnsupportedEncodingException;
    2. import java.security.Key;
    3. import java.security.MessageDigest;
    4. import java.security.NoSuchAlgorithmException;
    5. import java.security.spec.AlgorithmParameterSpec;
    6. import javax.crypto.Cipher;
    7. import javax.crypto.spec.IvParameterSpec;
    8. import javax.crypto.spec.SecretKeySpec;
    9. public enum AESUtil {
    10. ;
    11. /**
    12. *
    13. * @param src
    14. * @param pw
    15. * @param iv
    16. * @return
    17. */
    18. public static String encrypt(String src,String pw,String iv) {
    19. try {
    20. Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
    21. cipher.init(Cipher.ENCRYPT_MODE, makeKey(pw), makeIv(iv));
    22. // Encrypt:
    23. // 1. cipher encrypt
    24. // 2. Base64 encode
    25. byte[] encrypt = cipher.doFinal( src.getBytes() );
    26. return testmp3.Base64.encodeBytes( encrypt );
    27. }
    28. catch (Exception e) {
    29. throw new RuntimeException(e);
    30. }
    31. }
    32. /**
    33. *
    34. * @param src
    35. * @param pw
    36. * @param iv
    37. * @return
    38. */
    39. public static String decrypt(String src,String pw,String iv) {
    40. String decrypted = "";
    41. try {
    42. Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
    43. cipher.init(Cipher.DECRYPT_MODE, makeKey(pw), makeIv(iv) );
    44. // Decrypt:
    45. // 1. Base64 decode
    46. // 2. cipher decrypt
    47. byte[] buffer = Base64.decode(src);
    48. decrypted = new String(cipher.doFinal(buffer));
    49. }
    50. catch (Exception e) {
    51. throw new RuntimeException(e);
    52. }
    53. return decrypted;
    54. }
    55. /**
    56. *
    57. * @param data
    58. * @param pw
    59. * @param iv
    60. * @return
    61. */
    62. public static byte[] encrypt(byte[] data,String pw,String iv) {
    63. byte[] buffer = null;
    64. try {
    65. Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
    66. cipher.init(Cipher.ENCRYPT_MODE, makeKey(pw), makeIv(iv)); // key and iv 16Bytes
    67. // Encrypt:
    68. // 1. cipher encrypt
    69. // 2. Base64 encode
    70. buffer = cipher.doFinal(data);
    71. byte[] encrypt = Base64.encodeBytesToBytes(buffer);
    72. return encrypt;
    73. }
    74. catch (Exception e) {
    75. throw new RuntimeException(e);
    76. }
    77. }
    78. /**
    79. *
    80. * @param data
    81. * @param pw
    82. * @param iv
    83. * @return
    84. */
    85. public static byte[] decrypt(byte[] data,String pw,String iv) {
    86. byte[] decrypted = null;
    87. try {
    88. Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
    89. cipher.init(Cipher.DECRYPT_MODE, makeKey(pw), makeIv(iv) );
    90. // Decrypt:
    91. // 1. Base64 decode
    92. // 2. cipher decrypt
    93. byte[] buffer = Base64.decode(data);
    94. decrypted = cipher.doFinal(buffer);
    95. }
    96. catch (Exception e) {
    97. throw new RuntimeException(e);
    98. }
    99. return decrypted;
    100. }
    101. /**
    102. *
    103. * @param ivp
    104. * @return
    105. * @throws NoSuchAlgorithmException
    106. */
    107. static AlgorithmParameterSpec makeIv(String ivp) throws NoSuchAlgorithmException {
    108. try {
    109. MessageDigest md = MessageDigest.getInstance("SHA-256");
    110. byte[] iv = md.digest(ivp.getBytes("UTF-8"));
    111. return new IvParameterSpec(iv,0,16);
    112. }
    113. catch (UnsupportedEncodingException e) {
    114. e.printStackTrace();
    115. }
    116. return null;
    117. }
    118. /**
    119. *
    120. * @param pw
    121. * @return
    122. */
    123. static Key makeKey(String pw) {
    124. try {
    125. MessageDigest md = MessageDigest.getInstance("SHA-256");
    126. byte[] key = md.digest(pw.getBytes("UTF-8"));
    127. return new SecretKeySpec(key,0,16, "AES");
    128. }
    129. catch (NoSuchAlgorithmException e) {
    130. e.printStackTrace();
    131. }
    132. catch (UnsupportedEncodingException e) {
    133. e.printStackTrace();
    134. }
    135. return null;
    136. }
    137. }
    Alles anzeigen
    Si tacuisses, philosophus mansisses !

    Dieser Beitrag wurde bereits 1 mal editiert, zuletzt von FRing ()