Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/344.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Python与java PBKDF2的等价物,带有HMACSHA1_Java_Python_Pbkdf2_Hmacsha1_Hashlib - Fatal编程技术网

Python与java PBKDF2的等价物,带有HMACSHA1

Python与java PBKDF2的等价物,带有HMACSHA1,java,python,pbkdf2,hmacsha1,hashlib,Java,Python,Pbkdf2,Hmacsha1,Hashlib,我的任务是构建一个API的使用者,该API需要一个加密令牌,其种子值为UNIX时间。我所展示的示例是使用我不熟悉的Java实现的,在阅读了文档和其他堆栈文章后,一直无法找到解决方案 使用javax.crypto.SecretKey、javax.crypto.SecretKeyFactory、javax.crypto.spec.PBEKeySpec和javax.crypto.spec.SecretKeySpec协议,我需要生成一个类似于以下内容的令牌: public class Encryptio

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

使用
javax.crypto.SecretKey
javax.crypto.SecretKeyFactory
javax.crypto.spec.PBEKeySpec
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
来实现这样的功能吗?我真的找不到用迭代/salt作为输入实现
PBKDF2
加密的文档。我应该使用
pbkdf2
?对于这些模糊的问题,我很抱歉,我不熟悉加密过程,甚至觉得知道正确的构造函数是朝着正确方向迈出的一步

是的,Python的等价物是。例如,此代码:

from hashlib import pbkdf2_hmac

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

print(key)
生成与Java代码相同的密钥

然而,该代码的问题(如备忘录中所述)在于盐的使用。每个密码的salt应该是随机的和唯一的。您可以使用
os.uradom
创建安全的随机字节,因此更好的示例是:

from hashlib import pbkdf2_hmac
from os import urandom

salt = urandom(16)
key = pbkdf2_hmac('sha1', b"somekeyvalue", salt, 12345, 32)
您可能还希望增加迭代次数(我认为建议的最小迭代次数为10000次)


代码的其余部分很容易“翻译”

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

    import time
    
    milliseconds = str(round(time.time() * 1000))
    
  • 对于编码,您可以使用(它包括填充,但您可以使用
    .rstrip(b'=')
    删除它)

  • 现在,对于加密部分,Python没有内置的加密模块,因此您必须使用第三方库。我推荐或。
    此时,我必须警告您,您使用的AES模式非常弱。请考虑使用CBC或CTR,或者更好地使用算法。

这是几年前写的,应该是一个不错的起点:只是一句话:代码中的盐不应该与键相同。生成确定性非重复序列,或使用SecureRandom生成该序列;然后将其与加密信息一起传输。谢谢您的宝贵信息。关于盐的信息特别有用。API服务实际上向我提供了这个关于盐创建的示例,因此我可以继续提供反馈。接受并感激再次感谢亚当;只是为了跟进;在上面的
java
示例中,
skc
tmp
之间有什么区别?我能够使用您提到的方法复制
tmp
,但是我是否需要
AES
实例来创建
SecretKeySpec
?如果没有,我将如何获得skc的等效值?
skc
tmp
都包含相同的键-相同的字节。我们必须为中的
密钥
参数指定加密算法,因此我们使用
带有“AES”
的对象作为
算法
参数。它基本上是相同的密钥,只是不同的对象。啊,好吧,所以实际字节是相同的,但是
SecretKey
对象上的
AES
字段是
Cipher
对象使用的吗?在python中有这种类型的密码实现的例子吗?是的,我们使用
SecretKey
,因为它是一种更合适的类型,但实际的密钥是相同的。Python没有内置的加密库,但我可以推荐。您将在中找到一些AES示例。我将提供一个兼容的Python示例,但是您的java代码的安全性很差。它使用ECB,不执行身份验证。我建议api开发人员雇佣一名安全专家。