簡體   English   中英

使用 python 和 kotlin 進行 Fernet 加密/解密

[英]Fernet encryption/decryption with python and kotlin

我有一個用python編寫的項目。 我使用密碼學庫來加密和解密數據。 我這樣做是如何在他們的教程中顯示的

這是我的python代碼:

import base64
import os
from cryptography.fernet import Fernet
from cryptography.hazmat.primitives import hashes
from cryptography.hazmat.primitives.kdf.pbkdf2 import PBKDF2HMAC

password = b"my password"
salt = os.urandom(16)

kdf = PBKDF2HMAC(algorithm=hashes.SHA256(),
                 length=32,
                 salt=salt,
                 iterations=100000,
                 backend=default_backend())
key = base64.urlsafe_b64encode(kdf.derive(password))
f = Fernet(key)
data = b"my data..."
token = f.encrypt(data)

然后解密我可以使用:

f.decrypt(token)

在 python 中一切正常,但現在我需要在 kotlin 中做同樣的事情。 我發現了fernet java-8庫,但我不知道如何以同樣的方式使用它。

問題是我有兩個工具:一個是用 python 編寫的,另一個我想用 kotlin 編寫。 這兩種工具都是為了做同樣的事情——python 一個用於桌面,而 kotlin 一個將成為一個 android 應用程序。 因此,它們的加密方式非常重要,以便在 python(桌面工具)中加密的文件可以在 kotlin(android 應用程序)中解密,反之亦然。

但我不知道如何編寫類似的 kotlin 代碼。

您會看到有一個名為PBKDF2HMAC的函數(或類),還有base64.urlsafe_b64encode等。 而且我不知道 kotlin 或 fernet java-8 中的類似函數是什么。

那我該怎么做呢? 假設在 kotlin 中我必須使用我在 python 中使用的密碼和鹽。

謝謝!

在 Java/Kotlin 中,使用fernet-java8 ,Python 代碼生成的令牌可以解密如下:

import java.security.SecureRandom
import java.util.Base64
import javax.crypto.spec.PBEKeySpec
import javax.crypto.SecretKeyFactory
import com.macasaet.fernet.Key
import com.macasaet.fernet.Token
import com.macasaet.fernet.StringValidator
import com.macasaet.fernet.Validator
import java.time.Duration
import java.time.temporal.TemporalAmount

...

// Data from encryption
val salt = Base64.getUrlDecoder().decode("2Yb8EwpYkMlycHxoKcmHuA==")
val token = Token.fromString("gAAAAABfoAmp7C7IWVgA5urICEIspm_MPAGZ-SyGnPEVUBBNerWQ-K6mpSoYTwRkUt3FobyAFHbYfhNtiGMe_96yyLvUoeLIIg==");

// Derive Fernet key
val key = deriveKey("my password", salt)
val fernetKey = Key(key)

// Decrypt
val validator: Validator<String> = object : StringValidator {
    override fun getTimeToLive(): TemporalAmount {
        return Duration.ofHours(24)
    }
}
val data = token.validateAndDecrypt(fernetKey, validator)
println(data) // my data...

和:

fun deriveKey(password: String, salt: ByteArray): String {
    val iterations = 100000
    val derivedKeyLength = 256
    val spec = PBEKeySpec(password.toCharArray(), salt, iterations, derivedKeyLength)
    val secretKeyFactory = SecretKeyFactory.getInstance("PBKDF2WithHmacSHA256")
    val key = secretKeyFactory.generateSecret(spec).encoded
    return Base64.getUrlEncoder().encodeToString(key)
}

這里 Fernet 密鑰是使用密鑰派生函數PBKDF2派生的。 PBKDF2 需要各種輸入參數,例如密碼、摘要、鹽、迭代次數和所需的密鑰長度。 在發布的示例中,密鑰返回Base64url編碼。
對於解密,必須使用與加密相同的參數。 由於鹽通常(如在發布的代碼中)在加密期間隨機生成,因此它必須與密文一起傳遞給解密方(注意:鹽不是秘密)。

驗證器將生存時間(默認為 60 秒)設置為 24 小時,請參閱此處了解更多詳細信息。

在發布的 Python 代碼中,必須添加鹽的導出,例如通過 Base64url 將其編碼為類似於密鑰和令牌(並為簡單起見將其打印)。 在實踐中,salt 和 token 也可以在加密期間連接並在解密期間分開。

更新:

加密部分類似:

// Generate salt
val salt = generateSalt()
println(Base64.getUrlEncoder().encodeToString(salt))

// Derive Fernet key
val key = deriveKey("my password", salt)
val fernetKey = Key(key)

// Encrypt
val data = "my data..."
val token = Token.generate(fernetKey, data)
println(token.serialise()) // the Base64url encoded token

fun generateSalt(): ByteArray {
    val random = SecureRandom()
    val salt = ByteArray(16)
    random.nextBytes(salt)
    return salt
}

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM