2017-09-19 97 views
0

我在客戶端使用Swift鈉,因爲我的服務器在通過API與我共享之前使用libsodium加密數據。swift sodium使用私鑰解密

現在我有一個現有的私鑰和一個字符串格式的公鑰與我。我想現在使用Swift在iOS上解密加密數據。

如何使用公鑰和私鑰生成鈉密鑰對?

此外理想情況下,我應該只使用私鑰解密數據。那麼,我怎麼做只使用私鑰作爲字符串。

我的解密代碼如下所示 -

func decryptData(dataString: String) -> String? { 
    let sodium = Sodium() 
    let privateKey = sodium?.utils.hex2bin("MY_SECRET_KEY") 

    let publicKey = sodium?.utils.hex2bin("MY_PUBLIC_KEY") 

    let message = dataString.data(using: .utf8)! 

    if let decrypted = sodium?.box.open(anonymousCipherText: message, recipientPublicKey: publicKey!, recipientSecretKey: privateKey!){ 
     // authenticator is valid, decrypted contains the original message 
     return String(data: decrypted, encoding: String.Encoding.utf8) as String! 
    } 
    return nil 
} 

在上面的代碼我解密的字符串總是空的。

服務器使用下面的函數加密數據 -

protected function crypt($response) 
{ 
    $message = new HiddenString($response); 

    $repository = \App::make(EncryptionKeysRepository::class); 
    $enc = $repository->findOneBy(['device' => 'android']); 
    $dir = $enc->getDevice(); 
    $publicKey = $enc->getPublicKey(); 
    $storage = storage_path(); 

    if(!file_exists($storage."/{$dir}/")) { 
     mkdir($storage."/{$dir}/"); 
    } 

    // save key pair to key store 
    $pubFilename = \tempnam($storage."/{$dir}/", 'pub_key'); 
    file_put_contents($pubFilename, $publicKey); 

    $public = KeyFactory::loadEncryptionPublicKey($pubFilename); 
    unlink($pubFilename); 
    rmdir($storage."/{$dir}/"); 
    $message = Crypto::seal($message, $public); 

    return $message; 
} 

解密邏輯在服務器

protected function deCrypt($response) 
{ 
    $repository = \App::make(EncryptionKeysRepository::class); 
    $enc = $repository->findOneBy(['device' => 'android']); 
    $dir = $enc->getDevice(); 
    $publicKey = $enc->getSecretKey(); 
    $storage = storage_path(); 

    if(!file_exists($storage."/{$dir}/")) { 
     mkdir($storage."/{$dir}/"); 
    } 

    // save key pair to key store 
    $secFilename = \tempnam($storage."/{$dir}/", 'sec_key'); 
    file_put_contents($secFilename, $publicKey); 

    $secret = KeyFactory::loadEncryptionSecretKey($secFilename); 
    unlink($secFilename); 
    rmdir($storage."/{$dir}/"); 
    $res = Crypto::unseal($response, $secret); 

    $message = $res->getString(); 

    return response()->json(compact('message')); 
} 
+0

你有什麼格式的'dataString'?也許它是base64或其他格式,你必須在解密之前解碼它? – algrid

+0

@algrid它只是一個加密的字符串。不需要編碼,因此解碼是不必要的。 –

回答

0

所以,服務器端,你顯然是使用PHP,一個庫調用岩鹽。

我對Halite並不是很熟悉,但是看它的代碼,Crypto::seal()使用密封框,所以Box::open(anonymousCipherText: Data, recipientPublicKey: PublicKey, recipientSecretKey: SecretKey) -> Data?是在Swift中解密這個的正確方法。

但是,Halite似乎也將結果編碼爲BASE64字符串(urlsafe變體)。

所以,你需要首先解碼。或者,這樣會更高效,不要編碼密文。除非你必須大聲讀出它們,否則這些鍵可能不需要被編碼。

+0

我試着解碼它,但解碼的數據總是零,所以我假設它沒有base64編碼。我用這個 - '讓decodedData = Data(base64Encoded:dataString)' –

+0

確保你使用了正確的BASE64變體。如上所述,默認情況下,Halite似乎使用BASE64的URLsafe變體。 –

+0

檢查所有變種弗蘭克。我不認爲它的base64encoded誠實,因爲一切都沒有給予 –