2016-01-21 42 views
0

我試圖發送aes加密數據到javaee服務器,發送後獲取不同的字節。當我使用ios和javaee上相同的密鑰對相同的字符串進行加密時,我得到的字節相同,但是當我將加密的字節發送到服務器時,它們稍微關閉。這裏是我的加密方法....iOS,java ee:aes加密,發送後字節發生變化

***** iOS的AES加密*****

- (NSData*)AES256EncryptWithKey:(NSString*)key { 
    char keyPtr[kCCKeySizeAES128 + 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/*NSUTF8StringEncoding*/]; 

    NSUInteger dataLength = [self length]; 

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


    size_t numBytesEncrypted = 0; 
    CCCryptorStatus cryptStatus = CCCrypt(kCCEncrypt, kCCAlgorithmAES128, 

             kCCOptionPKCS7Padding, 

             keyPtr, kCCKeySizeAES128, 
             NULL /* initialization vector (optional) */, 
             [self bytes], dataLength, /* input */ 
             buffer, bufferSize, /* output */ 
             &numBytesEncrypted); 

    if (cryptStatus == kCCSuccess) 
    { 


     return [NSData dataWithBytesNoCopy:buffer length:numBytesEncrypted]; 
    } 

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

這是對的NSData的「AESAdditions的榜樣。所以我實現的,這是...

NSData *encryptedData = [self encryptString:@"test" withKey:@"abcdef"]; 

其中 'encryptString:withKey:' 是....

- (NSData*) encryptString:(NSString*)plaintext withKey:(NSString*)key { 
    return [[plaintext dataUsingEncoding:NSUTF8StringEncoding] AES256EncryptWithKey:key]; 
} 

,這是返回字節 (d24374ca 9c7adedd 26d3d285 8d42e69c)

我然後設置以此爲主體爲URL請求這樣....

NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:[NSURL URLWithString:@"http://myurl.com"]]; 
[request setHTTPBody:encryptedData]; 
[request setHTTPMethod:@"POST"]; 
[request setValue:@"application/x-www-form-urlencoded" forHTTPHeaderField:@"Content-Type"]; 

NSURLResponse *response; 
NSError *errro; 
[NSURLConnection sendSynchronousRequest:request returningResponse:&response error:&errro]; 

中號Ÿjava的AES加密方法是...

public byte[] AESencrypt(String plainText, String encryptionKey) throws Exception { 

    Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding"); 

    SecretKeySpec key = new SecretKeySpec(encryptionKey.getBytes("UTF-8"), "AES"); 

    final byte[] iv = new byte[16]; 
    Arrays.fill(iv, (byte) 0x00); 
    IvParameterSpec ivParameterSpec = new IvParameterSpec(iv); 

    cipher.init(Cipher.ENCRYPT_MODE, key,ivParameterSpec/*new IvParameterSpec(INITIALIZATIO_VECTOR.getBytes("UTF-8"))*/); 

    return cipher.doFinal(plainText.getBytes("UTF-8")); 

    } 

和我實現這...

byte[] encryptedString = AESencrypt("test", "abcdef"); 

和這個結果是(d24374ca 9c7adedd 26d3d285 8d42e69c) 一樣的iphone版本...

但是當我在javaee中檢索url請求的主體時,我得到的是稍微不同的字節。我得到的字節是這樣的方式......

*這是正在doGet方法做​​

BufferedReader reader = request.getReader();  

body = reader.readLine(); 
byte[] bytes = body.getBytes(); 

然後當我打印出來,我得到d24374ca 3f7adedd 26d3d23f 3f42e63f字節...

所以回顧一下(從iPhone和JavaEE的不同)...

iPhone AES加密字節數:d24374ca 9c7adedd 26d3d285 8d42e69c

JavaEE的加密字節:d24374ca 9c7adedd 26d3d285 8d42e69c

傳輸的字節:d24374ca 3f7adedd 26d3d23f 3f42e63f

我在做什麼錯了,當我把它們發送到服務器的JavaEE的字節數得到改變?

感謝您的幫助

* UPDATE *

我一直在用它瞎搞一些,發現當我刪除了「+1」從iOS加密(在第二行) ,當到達服務器時字節不會改變......但結果是不同的,我似乎無法在服務器端得到相同的結果:/ ....也許這會有所幫助?

+0

使用硬編碼IV擊敗CBC的目的,使你容易。 http://blog.slaks.net/2015-11-18/common-crypto-pitfalls/#don-39-t-reuse-ivs – SLaks

回答

0

最後!!!!

我找到了答案!因此,我進行加密的方式是正確的,問題在於獲取請求的正文。

之前我做的......

BufferedReader reader = request.getReader();  
body = reader.readLine(); 
byte[] bytes = body.getBytes(); 

使用 'getReader()' 是什麼導致了問題。因此,而不是上面的代碼我使用的代碼...

InputStream is = request.getInputStream(); 
byte[] bytes = getBytesFromInputStream(is); 

其中「getBytesFromInputStream」是......

public static byte[] getBytesFromInputStream(InputStream is) throws IOException 
{ 
    try (ByteArrayOutputStream os = new ByteArrayOutputStream();) 
    { 
     byte[] buffer = new byte[0xFFFF]; 

     for (int len; (len = is.read(buffer)) != -1;) 
      os.write(buffer, 0, len); 

     os.flush(); 

     return os.toByteArray(); 
    } 
} 

從那裏我得到了相同的字節我發送到服務器。我認爲我讀了'getReader()'改變了一些填充字符或什麼的地方,我認爲這就是爲什麼當我擺脫'+1',字節不會改變...

所以總之...

不要不要使用

BufferedReader reader = request.getReader(); 
body = reader.readLine(); 
byte[] bytes = body.getBytes(); 

改用

InputStream is = request.getInputStream(); 
byte[] bytes = getBytesFromInputStream(is); 

(檢索填充加密字符串時)

希望這可以幫助人們走出同樣的問題...

+0

如果有人想知道,這確實適用於返回加密數據。不要使用response.getWriter()而是使用response.getOutputStream() – Paul

相關問題