2015-04-22 32 views
12

我努力通過網絡傳輸長的加密字符串,並讓它們在服務器上正確出來。例如,我在客戶端上此加密字符串:NSCharacterSet URLHostAllowedCharacterSet不會替換'+'符號嗎?

wcWSERZCh8Xm1hpbNo1kSD1LvFmpuUr4wmq9hQUWeK0vYcLeFPGwFR/sBTES1A4rPV6eyp9nzEEU9uKkiFSTdP + SPOSqUf6evjf3WRHrXMRe81lIrHuRyk0iRwoNe5uIk + VlpR41kETmznXa4 + gELmf53r7oayRkkffnIPDmpO + WbgE0VL3PQeOsXB01tWJyDiBIsz5WJiiEIm3ZoJW/SW ==

正如你所看到的,它有幾個字符如果沒有一些URL編碼(+/,最值得注意)將不會通過網絡傳輸。我不完全確定在其他情況下是否會出現其他角色,所以我想確保我的解決方案「普遍」正確。我正在使用這一行:

NSString *escapedString = [cipherString stringByAddingPercentEncodingWithAllowedCharacters:[NSCharacterSet URLHostAllowedCharacterSet]]; 

我發現在一個高度評論answer

不過,我仍然有問題在服務器端解密這一點,所以我打印出來的客戶端上的結果立即發送之前,我看到:

wcWSERZCh8Xm1hpbNo1kSD1LvFmpuUr4wmq9hQUWeK0vYcLeFPGwFR%2FsBTES1A4rPV6eyp9nzEEU9uKkiFSTdP + SPOSqUf6evjf3WRHrXMRe81lIrHuRyk0iRwoNe5uIk + VlpR41kETmznXa4 + gELmf53r7oayRkkffnIPDmpO + WbgE0VL3PQeOsXB01tWJyDiBIsz5WJiiEIm3ZoJW%2Fsw ==

爲什麼是 '+' 號還在嗎?我是否使用了錯誤的允許字符集?我應該使用哪種字符集來保證我正確地轉義所有有問題的字符?

如果有幫助,這裏是我用來加密純文本字符串的代碼。完成後,我base64編碼結果發送之前通過網絡:

- (NSData *)phpEncryptCleartext : (NSData *)cleartext 
{ 
    NSData *cleartextPadded = [self phpPadData:cleartext]; 

    CCCryptorStatus ccStatus  = kCCSuccess; 
    size_t   cryptBytes  = 0; // Number of bytes moved to buffer. 
    NSMutableData *cipherTextData = [NSMutableData dataWithLength:cleartextPadded.length]; 

    ccStatus = CCCrypt(kCCEncrypt, 
         kCCAlgorithmAES128, 
         0, 
         _sessionKey.bytes, 
         kCCKeySizeAES128, 
         _iv.bytes, 
         cleartextPadded.bytes, 
         cleartextPadded.length, 
         cipherTextData.mutableBytes, 
         cipherTextData.length, 
         &cryptBytes); 

    if (ccStatus == kCCSuccess) { 
     cipherTextData.length = cryptBytes; 
    } 
    else { 
     NSLog(@"kEncryptionError code: %d", ccStatus); // Add error handling 
     cipherTextData = nil; 
    } 

    return cipherTextData; 
} 

感謝您的任何意見!

+0

我沒有檢查的實況,但如果如果沒有逃脫'+'(這從我的POV將是確定的),你可以啓動你的自己的字符串替換更改爲等效的符號符號。 –

+0

也許你應該試試'URLFragmentAllowedCharacterSet'? –

+0

'URLFragmentAllowedCharacterSet'創建了其他問題。我可以很容易地做我自己的字符串替換,但是我擔心只要撲滅火災,那麼我就不能完全相信我已經看到了所有可能存在問題的字符。我假設之前已經處理過很多次了,並且希望有一種內置的方法可以可靠地處理它。不過,現在,我可能不得不按照你的建議來處理它。謝謝! – Alex

回答

27

Swift version here

要轉義字符使用stringByAddingPercentEncodingWithAllowedCharacters:

NSString *URLEscapedString = 
[string stringByAddingPercentEncodingWithAllowedCharacters:[NSCharacterSet URLQueryAllowedCharacterSet]]; 

以下是有用的字符集,實際上不包括在集合中的字符:

URLFragmentAllowedCharacterSet "#%<>[\]^`{|} 
URLHostAllowedCharacterSet  "#%/<>[email protected]\^`{|} 
URLPasswordAllowedCharacterSet "#%/:<>[email protected][\]^`{|} 
URLPathAllowedCharacterSet  "#%;<>?[\]^`{|} 
URLQueryAllowedCharacterSet  "#%<>[\]^`{|} 
URLUserAllowedCharacterSet  "#%/:<>[email protected][\]^` 

或者只用字符創建自己的字符集你需要逃避。

NSCharacterSet *customCharacterset = [[NSCharacterSet characterSetWithCharactersInString:@"your characters"] invertedSet]; 

創建一個字符集,結合上述所有的:

NSCharacterSet *URLFullCharacterSet = [[NSCharacterSet characterSetWithCharactersInString:@" \"#%/:<>[email protected][\\]^`{|}"] invertedSet]; 

創建一個Base64

在Base64編碼字符集的情況下:

NSCharacterSet *URLBase64CharacterSet = [[NSCharacterSet characterSetWithCharactersInString:@"/+=\n"] invertedSet]; 

注:stringByAddingPercentEncodingWithAllowedCharacters也將編碼需要編碼的UTF-8字符。

實例驗證字符集合:

void characterInSet(NSCharacterSet *set) { 
    NSMutableString *characters = [NSMutableString new]; 
    NSCharacterSet *invertedSet = set.invertedSet; 
    for (int i=32; i<127; i++) { 
     if ([invertedSet characterIsMember:(unichar)i]) { 
      NSString *c = [[NSString alloc] initWithBytes:&i length:1 encoding:NSUTF8StringEncoding]; 
      [characters appendString:c]; 
     } 
    } 
    printf("characters not in set: '%s'\n", [characters UTF8String]); 
} 
+0

已更新的答案。 – zaph

+0

非常感謝! – Alex

+1

優秀的答案是我們現在應該以不同的方式對URL的每個部分進行編碼,或者是否存在一種適用於所有方法的方法?你是怎麼確定每個字符集包含哪些字符的?蘋果文檔不會擴展,並且一如既往地模糊。謝謝 – RyanTCB