Шифрование данных с помощью Objective-C и дешифрование с помощью Java.

У меня есть решения для iPhone, которые используют XML для передачи данных между клиентом (мобильным) и сервером (Java). Некоторые части сообщения (XML) должны быть зашифрованы из-за типа передаваемой информации. Я планировал использовать AES 128 для шифрования и дешифрования данных между этими двумя конечными точками.

Сначала конфиденциальные данные шифруются с использованием инфраструктуры CommonCrypto Object-C, а затем данные дешифруются внутри Java-сервера (сервлета).

Я новичок в области протоколов и стандартов безопасности, и в основном мой код представляет собой подмножество групп информации, которую я мог бы собрать на форуме / ресурсах Apple для разработчиков и в Интернете (Google):-)

Основной поток:

  1. Данные зашифрованы с использованием AES (с использованием предварительно установленного ключа).
  2. Зашифрованные байты помещаются в XML (используя base64)
  3. Данные собираются из XML и расшифровываются с использованием того же предварительно установленного ключа;

Часть шифрования кода Object-C:

char keyPtr [ kCCKeySizeAES128 +1 ];
bzero( keyPtr, sizeof(keyPtr) );

// The secret key is masked for obvious reason, but you can use "12345678912345678912345678912345"
[key getCString:keyPtr maxLength:sizeof(keyPtr) encoding:NSUTF8StringEncoding];

NSUInteger dataLength = [data length];
// Initialization vector; dummy in this case 0's.
uint8_t iv[ kCCBlockSizeAES128 ];
memset((void *) iv, 0x0, (size_t) sizeof(iv));
/*
 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 bufferSize = (dataLength + kCCBlockSizeAES128);
void  *buffer     = malloc(bufferSize);
memset(buffer, 0x0, bufferSize);

size_t numBytesEncrypted    = 0;
CCCryptorStatus cryptStatus = CCCrypt(kCCEncrypt, kCCAlgorithmAES128, 
                                      kCCOptionECBMode + kCCOptionPKCS7Padding,
                                      keyPtr, kCCKeySizeAES128,
                                      iv, [data bytes], dataLength, /* input */
                                      buffer, bufferSize, /* output */
                                      &numBytesEncrypted);

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

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

Часть кода Java:

Security.addProvider(new org.bouncycastle.jce.provider.BouncyCastleProvider());
byte[] keyBytes = DES_KEY.getBytes(); //<== The same as above

SecretKeySpec keySpec = new SecretKeySpec(keyBytes, "AES");

try {
    // Return the raw bytes 
    byte []data = Base64.decode(encryptedContent);

    // Gets the Cipher...
    final Cipher cipher = Cipher.getInstance("AES/ECB/PKCS7Padding", "BC");
    cipher.init(Cipher.DECRYPT_MODE, keySpec);

    String resultString = new String(cipher.doFinal(data));
} catch (Exception ex) {
    ...
}

Ошибка, которую я получаю при запуске этих решений выше на сервере Java:

15:57:43,671 ERROR [STDERR] com.iteatros.aim.services.ServiceException: javax.crypto.BadPaddingException: pad block corrupted
15:57:43,674 ERROR [STDERR]     at com.iteatros.aim.services.security.SecurityWrapper.decrypt3DESBase64StringData(SecurityWrapper.java:109)
15:57:43,674 ERROR [STDERR]     at com.iteatros.aim.services.db.LoginDAO.login(LoginDAO.java:53)
15:57:43,674 ERROR [STDERR]     at com.iteatros.aim.services.AbstractService.authenticate(AbstractService.java:278)
15:57:43,674 ERROR [STDERR]     at com.iteatros.aim.services.AbstractService.doPost(AbstractService.java:165)
15:57:43,674 ERROR [STDERR]     at javax.servlet.http.HttpServlet.service(HttpServlet.java:637)
15:57:43,674 ERROR [STDERR]     at javax.servlet.http.HttpServlet.service(HttpServlet.java:717)
15:57:43,674 ERROR [STDERR]     at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:290)
15:57:43,675 ERROR [STDERR]     at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:206)
15:57:43,675 ERROR [STDERR]     at org.jboss.web.tomcat.filters.ReplyHeaderFilter.doFilter(ReplyHeaderFilter.java:96)
15:57:43,675 ERROR [STDERR]     at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:235)
15:57:43,676 ERROR [STDERR]     at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:206)
15:57:43,676 ERROR [STDERR]     at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:235)
15:57:43,676 ERROR [STDERR]     at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:191)
15:57:43,676 ERROR [STDERR]     at org.jboss.web.tomcat.security.SecurityAssociationValve.invoke(SecurityAssociationValve.java:190)
15:57:43,676 ERROR [STDERR]     at org.jboss.web.tomcat.security.JaccContextValve.invoke(JaccContextValve.java:92)
15:57:43,676 ERROR [STDERR]     at org.jboss.web.tomcat.security.SecurityContextEstablishmentValve.process(SecurityContextEstablishmentValve.java:126)
15:57:43,676 ERROR [STDERR]     at org.jboss.web.tomcat.security.SecurityContextEstablishmentValve.invoke(SecurityContextEstablishmentValve.java:70)
15:57:43,677 ERROR [STDERR]     at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:127)
15:57:43,677 ERROR [STDERR]     at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:102)
15:57:43,677 ERROR [STDERR]     at org.jboss.web.tomcat.service.jca.CachedConnectionValve.invoke(CachedConnectionValve.java:158)
15:57:43,677 ERROR [STDERR]     at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:109)
15:57:43,677 ERROR [STDERR]     at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:330)
15:57:43,677 ERROR [STDERR]     at org.apache.coyote.http11.Http11Processor.process(Http11Processor.java:829)
15:57:43,677 ERROR [STDERR]     at org.apache.coyote.http11.Http11Protocol$Http11ConnectionHandler.process(Http11Protocol.java:601)
15:57:43,677 ERROR [STDERR]     at org.apache.tomcat.util.net.JIoEndpoint$Worker.run(JIoEndpoint.java:447)
15:57:43,677 ERROR [STDERR]     at java.lang.Thread.run(Thread.java:680)

Я знаю, что полный стек не был нужен, но в любом случае...

Спасибо большое заранее.

Joao

1 ответ

Этот код работает для меня. Посмотрите:

AES 128 IOS

+ (NSString *) encrypt:(NSString *) dataToEncrypt withKey:(NSString*) key{    


NSData *data = [dataToEncrypt dataUsingEncoding:NSUTF8StringEncoding];
NSData *mData = [key dataUsingEncoding:NSUTF8StringEncoding];

CCCryptorStatus ccStatus = kCCSuccess;


// Begin to calculate bytesNeeded....

size_t bytesNeeded = 0;

ccStatus = CCCrypt(kCCEncrypt,
                   kCCAlgorithmAES,
                   kCCOptionECBMode | kCCOptionPKCS7Padding,
                   [mData bytes],
                   [mData length],
                   nil,
                   [data bytes],
                   [data length],
                   NULL,
                   0,
                   &bytesNeeded);

if(kCCBufferTooSmall != ccStatus){

    NSLog(@"Here it must return BUFFER TOO SMALL !!");
    return nil;
}

// .....End
// Now i do the real Crypting

char* cypherBytes = malloc(bytesNeeded);
size_t bufferLength = bytesNeeded;

if(NULL == cypherBytes)
    NSLog(@"cypherBytes NULL");

ccStatus = CCCrypt(kCCEncrypt,
                   kCCAlgorithmAES,
                   kCCOptionECBMode | kCCOptionPKCS7Padding,
                   [mData bytes],
                   [mData length],
                   nil,
                   [data bytes],
                   [data length],
                   cypherBytes,
                   bufferLength,
                   &bytesNeeded);

if(kCCSuccess != ccStatus){
    NSLog(@"kCCSuccess NO!");
    return nil;
}

return [Base64 encode:[NSData dataWithBytes:cypherBytes length:bufferLength]];
}

ДЖАВА

public static void encrypt_AES(String message){

        Cipher ecipher;
        try {
            // generate secret key using DES algorithm
            SecretKeySpec key = new SecretKeySpec(theKey.getBytes("UTF-8"), "AES");

            ecipher = Cipher.getInstance("AES/ECB/PKCS7Padding");

            // initialize the ciphers with the given key
            ecipher.init(Cipher.ENCRYPT_MODE, key);

            byte[] encrypted = ecipher.doFinal(message.getBytes("UTF-8"));

        }catch (Exception e) {
            //    
            e.printStackTrace();
        }

    }

Я нашел класс Base64 здесь: http://www.imthi.com/blog/programming/iphone-sdk-base64-encode-decode.php

Надеюсь, что это может помочь кому-то

Другие вопросы по тегам