我试图了解如何通过使用PBKDF2和SHA256获得派生密钥。
我很纠结,需要一个清晰易懂的例子。
到目前为止我所拥有的:
>
我找到了https://en.wikipedia.org/wiki/PBKDF2其中有一个示例,但使用SHA1,具有以下值:
密码plnlrtfpijpuhqylxbgqiyipieyxvfsavzgxbbcfusqkozwpngsyjqlmjsytrmd UTF8
盐A009C1A485912C6AE630D3E744240B04 HEX
散列函数SHA1
密钥大小128
迭代1000次
我一直在使用https://gchq.github.io/CyberChef,可以得到输出17EB4014C8C461C300E9B61518B9A18B它与维基百科示例中派生的关键字节相匹配。
我一直在和你一起工作https://mkyong.com/java/java-aes-encryption-and-decryption/其中有一个名为getAESKeyFromPassword的方法,如下所示:
// Password derived AES 256 bits secret key
public static SecretKey getAESKeyFromPassword(char[] password, byte[] salt)
throws NoSuchAlgorithmException, InvalidKeySpecException {
SecretKeyFactory factory = SecretKeyFactory.getInstance("PBKDF2WithHmacSHA256");
// iterationCount = 65536
// keyLength = 256
KeySpec spec = new PBEKeySpec(password, salt, 65536, 256);
SecretKey secret = new SecretKeySpec(factory.generateSecret(spec).getEncoded(), "AES");
return secret;
}
我想进行同样的“调查”,就像我对Wikipedia页面、SHA1和CyberChef所做的那样,但使用SHA256(替换Java代码中的值,以匹配示例中的salt、密码和迭代)。
这就是我困惑的开始:
密码plnlrtfpijpuhqylxbgqiyipieyxvfsavzgxbbcfusqkozwpngsyjqlmjsytrmd UTF8
盐A009C1A485912C6AE630D3E744240B04 HEX
散列函数SHA256
密钥大小128
我希望派生密钥在CyberChef中与https://mkyong.com/java/java-aes-encryption-and-decryption/实例
不是。
我不禁认为我的理解有缺陷。
有人可以提供一个简单的(经过处理的)带有SHA256的PBKDF2示例,这样我就可以理解发生了什么。如果派生密钥不是相同的(与SHA1示例一样,请解释原因)。
是Java SecretKey:
SecretKey secret = new SecretKeySpec(factory.generateSecret(spec).getEncoded(), "AES");
与派生密钥相同?
似乎缺少易于理解的例子。
谢谢
英里。
感谢大家的投入,特别是Topaco:)
我要回答我的问题,因为我花了一些时间在MCVE上工作,并设法获得了与网络厨师相同的密钥。
密钥值为:28869b5f31ae29236f164c5cb33e2e3bb46f483867a15f8e7208e1836070f64a
以下是cyberChef的输出:
下面是Java代码,以及运行它的输出:
package crypto;
import javax.crypto.Cipher;
import javax.crypto.SecretKey;
import javax.crypto.SecretKeyFactory;
import javax.crypto.spec.GCMParameterSpec;
import javax.crypto.spec.PBEKeySpec;
import javax.crypto.spec.SecretKeySpec;
import java.nio.ByteBuffer;
import java.nio.charset.Charset;
import java.nio.charset.StandardCharsets;
import java.security.NoSuchAlgorithmException;
import java.security.SecureRandom;
import java.security.spec.InvalidKeySpecException;
import java.security.spec.KeySpec;
import java.util.Base64;
public class EncryptDecryptAesGcmPassword {
private static final String ENCRYPT_ALGO = "AES/GCM/NoPadding";
private static final int TAG_LENGTH_BIT = 128; // must be one of {128, 120, 112, 104, 96}
private static final int IV_LENGTH_BYTE = 12;
private static final int SALT_LENGTH_BYTE = 16;
public static final int ITERATION_COUNT = 1000;
public static final int KEY_LENGTH = 256;
private static final Charset UTF_8 = StandardCharsets.UTF_8;
// return a base64 encoded AES encrypted text
public static String encrypt(byte[] salt, byte[] pText, String password) throws Exception {
// GCM recommended 12 bytes iv?
byte[] iv = getRandomNonce(IV_LENGTH_BYTE);
// secret key from password
SecretKey aesKeyFromPassword = getAESKeyFromPassword(password.toCharArray(), salt);
Cipher cipher = Cipher.getInstance(ENCRYPT_ALGO);
// ASE-GCM needs GCMParameterSpec
cipher.init(Cipher.ENCRYPT_MODE, aesKeyFromPassword, new GCMParameterSpec(TAG_LENGTH_BIT, iv));
byte[] cipherText = cipher.doFinal(pText);
// prefix IV and Salt to cipher text
byte[] cipherTextWithIvSalt = ByteBuffer.allocate(iv.length + salt.length + cipherText.length)
.put(iv)
.put(salt)
.put(cipherText)
.array();
// string representation, base64, send this string to other for decryption.
return Base64.getEncoder().encodeToString(cipherTextWithIvSalt);
}
// we need the same password, salt and iv to decrypt it
private static String decrypt(String cText, String password) throws Exception {
byte[] decode = Base64.getDecoder().decode(cText.getBytes(UTF_8));
// get back the iv and salt from the cipher text
ByteBuffer bb = ByteBuffer.wrap(decode);
byte[] iv = new byte[IV_LENGTH_BYTE];
bb.get(iv);
byte[] salt = new byte[SALT_LENGTH_BYTE];
bb.get(salt);
byte[] cipherText = new byte[bb.remaining()];
bb.get(cipherText);
// get back the aes key from the same password and salt
SecretKey aesKeyFromPassword = getAESKeyFromPassword(password.toCharArray(), salt);
Cipher cipher = Cipher.getInstance(ENCRYPT_ALGO);
cipher.init(Cipher.DECRYPT_MODE, aesKeyFromPassword, new GCMParameterSpec(TAG_LENGTH_BIT, iv));
byte[] plainText = cipher.doFinal(cipherText);
return new String(plainText, UTF_8);
}
public static byte hexToByte(String hexString) {
int firstDigit = toDigit(hexString.charAt(0));
int secondDigit = toDigit(hexString.charAt(1));
return (byte) ((firstDigit << 4) + secondDigit);
}
public static byte[] decodeHexString(String hexString) {
if (hexString.length() % 2 == 1) {
throw new IllegalArgumentException(
"Invalid hexadecimal String supplied.");
}
byte[] bytes = new byte[hexString.length() / 2];
for (int i = 0; i < hexString.length(); i += 2) {
bytes[i / 2] = hexToByte(hexString.substring(i, i + 2));
}
return bytes;
}
private static int toDigit(char hexChar) {
int digit = Character.digit(hexChar, 16);
if (digit == -1) {
throw new IllegalArgumentException(
"Invalid Hexadecimal Character: "+ hexChar);
}
return digit;
}
// Random byte[] with length numBytes
public static byte[] getRandomNonce(int numBytes) {
byte[] nonce = new byte[numBytes];
new SecureRandom().nextBytes(nonce);
return nonce;
}
// Password derived AES 256 bits secret key
public static SecretKey getAESKeyFromPassword(char[] password, byte[] salt)
throws NoSuchAlgorithmException, InvalidKeySpecException {
SecretKeyFactory factory = SecretKeyFactory.getInstance("PBKDF2WithHmacSHA256");
// iterationCount = 1000
// keyLength = 256
KeySpec spec = new PBEKeySpec(password, salt, ITERATION_COUNT,
KEY_LENGTH);
SecretKey secret = new SecretKeySpec(factory.generateSecret(spec).getEncoded(), "AES");
String encodedKey = hex(secret.getEncoded());
// print SecretKey as hex
System.out.println("SecretKey: " + encodedKey);
return secret;
}
// hex representation
public static String hex(byte[] bytes) {
StringBuilder result = new StringBuilder();
for (byte b : bytes) {
result.append(String.format("%02x", b));
}
return result.toString();
}
public static void main(String[] args) throws Exception {
String OUTPUT_FORMAT = "%-30s:%s";
String PASSWORD = "plnlrtfpijpuhqylxbgqiiyipieyxvfsavzgxbbcfusqkozwpngsyejqlmjsytrmd";
// plain text
String pText = "AES-GSM Password-Bases encryption!";
// convert hex string to byte[]
byte[] salt = decodeHexString("A009C1A485912C6AE630D3E744240B04");
String encryptedTextBase64 = EncryptDecryptAesGcmPassword.encrypt(salt, pText.getBytes(UTF_8), PASSWORD);
System.out.println("\n------ AES GCM Password-based Encryption ------");
System.out.println(String.format(OUTPUT_FORMAT, "Input (plain text)", pText));
System.out.println(String.format(OUTPUT_FORMAT, "Encrypted (base64) ", encryptedTextBase64));
System.out.println("\n------ AES GCM Password-based Decryption ------");
System.out.println(String.format(OUTPUT_FORMAT, "Input (base64)", encryptedTextBase64));
String decryptedText = EncryptDecryptAesGcmPassword.decrypt(encryptedTextBase64, PASSWORD);
System.out.println(String.format(OUTPUT_FORMAT, "Decrypted (plain text)", decryptedText));
}
}
运行此代码,生成以下内容:
SecretKey: 28869b5f31ae29236f164c5cb33e2e3bb46f483867a15f8e7208e1836070f64a
------ AES GCM Password-based Encryption ------
Input (plain text) :AES-GSM Password-Bases encryption!
Encrypted (base64) :/PuTLBTKVWgJB2iMoAnBpIWRLGrmMNPnRCQLBABOkwNeY8BrrdtoRNVFqZ+xmUjvF2PET6Ne2+PAp34QLCUFjQodTMdmzaNAfzcLWOf4
------ AES GCM Password-based Decryption ------
Input (base64) :/PuTLBTKVWgJB2iMoAnBpIWRLGrmMNPnRCQLBABOkwNeY8BrrdtoRNVFqZ+xmUjvF2PET6Ne2+PAp34QLCUFjQodTMdmzaNAfzcLWOf4
SecretKey: 28869b5f31ae29236f164c5cb33e2e3bb46f483867a15f8e7208e1836070f64a
Decrypted (plain text) :AES-GSM Password-Bases encryption!
谢谢
英里。
问题内容: 有没有一种方法可以解密Java中的密码。Java将算法实现为。我得到了创建密码哈希的代码。我在下面提到了哈希技术的链接: http://howtodoinjava.com/security/how-to-generate-secure-password-hash- md5-sha-pbkdf2-bcrypt-examples/ 我的要求是以加密格式存储第三方FTP服务器密码,并在需要登
我将AES与salt和IV一起用于加密和解密一个唯一的ID,但它给出了javax。加密。解密时出现BadPaddingException。 每次解密数据时给出的完整错误堆栈跟踪 加密方法- 解密方法 我是JCA的新手。
我已经看到了其他一些关于创建加密的初始化向量(IV)的问题,似乎使用随机值是一种选择。然而,我需要生成用于解密的IV,所以我必须使用基于一些salt的数据加密的相同的数据。 node.js加密函数createDecipher表示: crypto.createdecipher()的实现使用OpenSSL函数EVP_BytesToKey派生密钥,摘要算法设置为MD5,一次迭代,没有salt。 好的,听
问题内容: 我正在尝试在Python中加密某些内容,并在nodejs应用程序中对其进行解密。 我正在努力使这两个AES实现一起工作。这是我的位置。 在节点中: 产生输出: 在python中 这产生输出 显然,它们非常接近,但是node似乎在用某些内容填充输出。有什么想法可以使两者互操作吗? 问题答案: 好的,我已经弄清楚了,节点使用OpenSSL,后者使用PKCS5进行填充。PyCrypto不处理
本文向大家介绍Python和Java进行DES加密和解密的实例,包括了Python和Java进行DES加密和解密的实例的使用技巧和注意事项,需要的朋友参考一下 DES 为 Data Encryption Standard (数据加密标准)的缩写,是一种常见的对称加密算法。有关对称加密与非对称加密的特点及其应用场景,本文就不描述了,读者可以自行 google 。本文说明如何使用 Java 和 Pyt
null 下面是我当前的代码: 以下是我的结果: 原文: 正如您所看到的,加密中缺少几个字符,这也影响了解密。缺的是2号线的v和3号线的v 你知道为什么吗?