Python equivalent of java PBKDF2WithHmacSHA1

痞子三分冷 提交于 2021-01-28 05:52:10

问题


I'm tasked with building a consumer of an API that requires an encrypted token with a seed value that is the UNIX time. The example I was shown was implemented using Java which I'm unfamiliar with, and after reading through documentation and other stack articles have been unable to find a solution.

Using the javax.crypto.SecretKey, javax.crypto.SecretKeyFactory, javax.crypto.spec.PBEKeySpec, and javax.crypto.spec.SecretKeySpec protocols, I need to generate a token similar to the below:

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);

        }

    }
}

Should I be using the built-in library hashlib to implement something like this? I can't really find documentation for implementing a PBKDF2 encryption with iterations/salt as inputs. Should I be using pbkdf2? Sorry for the vague questions, I'm unfamiliar with the encryption process and feel like even just knowing what the correct constructor would be is a step in the right direction.


回答1:


Yes, the Python equivalent is hashlib.pbkdf2_hmac. For example this code:

from hashlib import pbkdf2_hmac

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

print(key)

produces the same key as your Java code.

However, the problem with this code (as mentioned in memo's comment) is the use of salt. The salt should be random and unique for each password. You can create secure random bytes with os.urandom, so a better example would be:

from hashlib import pbkdf2_hmac
from os import urandom

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

You may also want to increase the number of iterations (I think the recommended minimum number is 10,000).


The rest of the code is easy to 'translate'.

  • For the timestamp, use time.time to get the current time and multiply by 1000.

    import time
    
    milliseconds = str(round(time.time() * 1000))
    
  • For encoding you can use base64.urlsafe_b64encode (it includes padding, but you could remove it with .rstrip(b'=')).

  • Now, for the encryption part, Python doesn't have a built-in encryption module, so you'll have to use a third party library. I recommend pycryptodome or cryptography.
    At this point I must warn you that the AES mode you're using is very weak. Please consider using CBC or CTR, or better yet use an authenticated encryption algorithm.



来源:https://stackoverflow.com/questions/52009682/python-equivalent-of-java-pbkdf2withhmacsha1

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!