亚洲在线久爱草,狠狠天天香蕉网,天天搞日日干久草,伊人亚洲日本欧美

為了賬號安全,請及時綁定郵箱和手機立即綁定
已解決430363個問題,去搜搜看,總會有你想問的

使用 SecretKeyFactory 生成機密時,Java 字節數組到字符串必須等于 python

使用 SecretKeyFactory 生成機密時,Java 字節數組到字符串必須等于 python

慕桂英4014372 2023-08-08 16:39:28
我有一個任務將一些 python 加密代碼重寫為 java。我是Python新手。Python代碼:from cryptography.hazmat.primitives.kdf.pbkdf2 import PBKDF2HMACfrom cryptography.hazmat.backends import default_backendbackend = default_backend()  PASSWORD = bytes((1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16))key = PBKDF2HMAC(hashes.SHA256(), 32, salt, iterations, backend).derive(PASSWORD)我的java實現:import javax.crypto.SecretKeyFactory;    import javax.crypto.spec.PBEKeySpec;     byte[] PASSWORD = new byte[]{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16};        SecretKeyFactory factory = SecretKeyFactory.getInstance("PBKDF2WithHmacSHA256");    SecretKey tmp = factory.generateSecret(new PBEKeySpec(new String(PASSWORD).toCharArray(), salt, iterations, 256));    byte[] key = tmp.getEncoded();正如你所看到的 PASSWORD 是一個字節數組,我從十六進制字符串中獲得,即 010203....0F10,我無法更改它(即無法將其指定為 python 實現中的字符串,因為我了解服務器轉換密碼也轉換為字節數組)。使用這個虛擬密碼一切正常,即由 python 和 java 代碼生成的密鑰是相同的。但是當密碼更改為任意密碼時,我遇到了一個問題,即例如 AFFFFFFFFDBGEHTH .... 據我了解 java 字節數組表示為有符號整數的問題。即,當我將十六進制“FFFAAABBBCCCDDDDFFAAAAAAAAAAAABB”轉換為字節數組時,它將是字節數組 [-1, -6, -86, -69, -68, -52, -35, -35, -1, -86, - 86, -86, -86, -86, -86, -69],但在 python 中它將是 [255, 250, 170, 187, 188, 204, 221, 221, 255, 170, 170, 170, 170, 170、170、187]。我必須如何更改我的java代碼才能接收與python中相同的密鑰?據我了解,我必須將 java 字節數組字符串編碼為與 python .derive(...) 方法中相同的值。提前致謝。更新:salt       = b'salt'PASSWORD = = bytes((255, 250, 170, 187, 188, 204, 221, 221, 255, 170, 170, 170, 170, 170, 170, 187))key = PBKDF2HMAC(hashes.SHA256(), 32, salt, 512, backend).derive(PASSWORD)和SecretKeyFactory factory = SecretKeyFactory.getInstance("PBKDF2WithHmacSHA256");password = new String(new byte[]{-1, -6, -86, -69, -68, -52, -35, -35, -1, -86, -86, -86, -86, -86, -86, -69});var key = secretKeyFactory                    .generateSecret(new PBEKeySpec(password.toCharArray(), "salt".getBytes(), 512, 256))                    .getEncoded();應該給出相同的結果。它適用于新的 byte[]{1,2,3,4,....16} 密碼。
查看完整描述

2 回答

?
幕布斯6054654

TA貢獻1876條經驗 獲得超7個贊

這里的密碼是一個(任意)字節序列,通常與 UTF8 不兼容,因此在 UTF8 解碼過程中數據會被損壞。一個可能的解決方案是替換PBEKeySpec為 BouncyCastle 的PKCS5S2ParametersGenerator,它期望密碼為字節數組(在 中init):

import java.nio.charset.StandardCharsets;

import org.bouncycastle.crypto.PBEParametersGenerator;

import org.bouncycastle.crypto.digests.SHA256Digest;

import org.bouncycastle.crypto.generators.PKCS5S2ParametersGenerator;

import org.bouncycastle.crypto.params.KeyParameter;

...

byte[] salt = "salt".getBytes(StandardCharsets.UTF_8);

int iterations = 512;

byte[] PASSWORD = new byte[] { (byte)255, (byte)250, (byte)170, (byte)187, (byte)188, (byte)204, (byte)221, (byte)221, (byte)255, (byte)170, (byte)170, (byte)170, (byte)170, (byte)170, (byte)170, (byte)187 };

PBEParametersGenerator generator = new PKCS5S2ParametersGenerator(new SHA256Digest());

generator.init(PASSWORD, salt, iterations);

byte[] keyBytes = ((KeyParameter)generator.generateDerivedParameters(256)).getKey();?

// with bytesToHex from https://stackoverflow.com/a/9855338

System.out.println(bytesToHex(keyBytes).toLowerCase());? // d8aa4772e9648572611fe6dca7f653353de934cdb3b29fab94eb13ba2b198b9f

現在的結果與 Python 代碼的結果匹配:


from cryptography.hazmat.primitives.kdf.pbkdf2 import PBKDF2HMAC

from cryptography.hazmat.primitives import hashes


salt = b'salt'

iterations = 512

PASSWORD = bytes((255, 250, 170, 187, 188, 204, 221, 221, 255, 170, 170, 170, 170, 170, 170, 187))

key = PBKDF2HMAC(hashes.SHA256(), 32, salt, iterations).derive(PASSWORD)


print(key.hex()) # d8aa4772e9648572611fe6dca7f653353de934cdb3b29fab94eb13ba2b198b9f


查看完整回答
反對 回復 2023-08-08
?
慕慕森

TA貢獻1856條經驗 獲得超17個贊

SHA1您在 Java 代碼和Python 代碼中使用SHA256,這就是您得到不同結果的原因。使用PBKDF2WithHmacSHA256.



查看完整回答
反對 回復 2023-08-08
  • 2 回答
  • 0 關注
  • 208 瀏覽
慕課專欄
更多

添加回答

舉報

0/150
提交
取消
微信客服

購課補貼
聯系客服咨詢優惠詳情

幫助反饋 APP下載

慕課網APP
您的移動學習伙伴

公眾號

掃描二維碼
關注慕課網微信公眾號