相当于 java PBKDF2WithHmacSHA1 的 Python

2024-05-13

我的任务是构建一个 API 的使用者,该 API 需要带有 UNIX 时间种子值的加密令牌。我看到的示例是使用我不熟悉的 Java 实现的,在阅读文档和其他堆栈文章后一直无法找到解决方案。

使用javax.crypto.SecretKey, javax.crypto.SecretKeyFactory, javax.crypto.spec.PBEKeySpec, and javax.crypto.spec.SecretKeySpec协议,我需要生成类似于以下内容的令牌:

public class EncryptionTokenDemo {

    public static void main(String args[]) {
        long millis = System.currentTimeMillis();
        String time = String.valueOf(millis);
        String secretKey = "somekeyvalue";
        int iterations = 12345;
        String iters = String.valueOf(iterations);
        String strToEncrypt_acctnum = "somevalue|" + time + "|" + iterations;

        try {

            byte[] input = strToEncrypt_acctnum.toString().getBytes("utf-8");
            byte[] salt = secretKey.getBytes("utf-8");
            SecretKeyFactory factory = SecretKeyFactory.getInstance("PBKDF2WithHmacSHA1");
            SecretKey tmp = factory.generateSecret(new PBEKeySpec(secretKey.toCharArray(), salt, iterations, 256));
            SecretKeySpec skc = new SecretKeySpec(tmp.getEncoded(), "AES");
            Cipher cipher = Cipher.getInstance("AES/ECB/PKCS5Padding");
            cipher.init(Cipher.ENCRYPT_MODE, skc);
            byte[] cipherText = new byte[cipher.getOutputSize(input.length)];
            int ctLength = cipher.update(input, 0, input.length, cipherText, 0);
            ctLength += cipher.doFinal(cipherText, ctLength);
            String query = Base64.encodeBase64URLSafeString(cipherText);
            // String query = cipherText.toString();
            System.out.println("The unix time in ms is :: " + time);
            System.out.println("Encrypted Token is :: " + query);
        } catch (Exception e) {
            System.out.println("Error while encrypting :" + e);

        }

    }
}

我应该使用内置库吗hashlib实施这样的事情?我真的找不到实现的文档PBKDF2以迭代/盐作为输入的加密。我应该使用pbkdf2?抱歉,我的问题含糊不清,我不熟悉加密过程,感觉即使知道正确的构造函数是什么也是朝着正确方向迈出的一步。


是的,Python 的等价物是hashlib.pbkdf2_hmac https://docs.python.org/3/library/hashlib.html#hashlib.pbkdf2_hmac。例如这段代码:

from hashlib import pbkdf2_hmac

key = pbkdf2_hmac(
    hash_name = 'sha1', 
    password = b"somekeyvalue", 
    salt = b"somekeyvalue", 
    iterations = 12345, 
    dklen = 32
)

print(key)

生成与 Java 代码相同的密钥。

然而,这段代码的问题(如备忘录中提到的)comment https://stackoverflow.com/questions/52009682/python-equivalent-of-java-pbkdf2withhmacsha1#comment91054901_52009682)是盐的使用。每个密码的盐应该是随机且唯一的。您可以使用以下命令创建安全随机字节os.urandom,所以更好的例子是:

from hashlib import pbkdf2_hmac
from os import urandom

salt = urandom(16)
key = pbkdf2_hmac('sha1', b"somekeyvalue", salt, 12345, 32)

您可能还想增加迭代次数(我认为建议的最小次数是 10,000)。


其余代码很容易“翻译”。

  • 对于时间戳,请使用time.time获取当前时间并乘以 1000。

    import time
    
    milliseconds = str(round(time.time() * 1000))
    
  • 对于编码,您可以使用base64.urlsafe_b64encode https://docs.python.org/3/library/base64.html#base64.urlsafe_b64encode(它包括填充,但您可以使用以下命令将其删除.rstrip(b'=')).

  • 现在,对于加密部分,Python没有内置的加密模块,因此您必须使用第三方库。我建议pycryptodome https://pycryptodome.readthedocs.io/en/latest/index.html or cryptography https://cryptography.io/en/latest/.
    此时我必须警告您,您使用的 AES 模式非常弱。请考虑使用 CBC 或 CTR,或者更好地使用认证加密 https://en.wikipedia.org/wiki/Authenticated_encryption算法。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

相当于 java PBKDF2WithHmacSHA1 的 Python 的相关文章

随机推荐