我正在寻找在java(在Windows上)执行以下当前任务的最佳方法:
由于用户输入的特定字符串,在程序内部创建一个随机的其他字符串/键(字母数字),并且用户不可见。
如果我们输入相同的字符串,则密钥必须相同。
所以基本上,我看到如何制作一个随机字符串,但我想确定该程序的用户无法找到内部给出的密钥(我实际上然后使用此密钥加密数据,并且因此我不希望简单的用户访问此密钥。)
我该怎么做?你能告诉我一个适当解决方案的代码运行示例吗?
编辑:我请求为用户输入的相同字符串使用相同的密钥,因为我需要知道这个生成的密钥,以便下次在我的计算机上使用,然后与另一个客户端一起使用。
答案 0 :(得分:2)
也许是盐渍哈希函数?
获取用户输入,添加一些秘密输入,并对事物进行散列。
(没有秘密输入,用户可以自己弄清楚如何创建)。
当然,这个字符串根本不是随机的。具有这种可重复性的要求排除了随机性。但是,这些字符串没有可辨别的模式,因此它看起来是“随机的”。
答案 1 :(得分:2)
我真的不太了解您的用例,从安全角度提供建议。但是,要直接解决从用户提供的输入生成可重现密钥的问题,您可以使用基于密码的密钥派生,其中我们将用户提供的输入视为密码(编辑为完整示例):< / p>
import java.security.NoSuchAlgorithmException;
import java.security.spec.InvalidKeySpecException;
import java.security.spec.KeySpec;
import javax.crypto.Cipher;
import javax.crypto.SecretKey;
import javax.crypto.SecretKeyFactory;
import javax.crypto.spec.IvParameterSpec;
import javax.crypto.spec.PBEKeySpec;
import javax.crypto.spec.SecretKeySpec;
import sun.security.provider.SecureRandom;
public class DerivationExample {
private static SecretKey makeKeyFromUserInput(String userInput, byte[] salt)
throws NoSuchAlgorithmException, InvalidKeySpecException {
SecretKeyFactory factory = SecretKeyFactory
.getInstance("PBKDF2WithHmacSHA1");
KeySpec keySpec = new PBEKeySpec(userInput.toCharArray(), salt, 1024, 256);
byte[] derivedKey = factory.generateSecret(keySpec).getEncoded();
return new SecretKeySpec(derivedKey, "AES");
}
public static void main(String[] args) throws Exception {
String userInput = "foo";
// PBKDF2 standard recommends at least 64-bit salt
// Note: you want to randomly generate this elsewhere and keep it constant
byte[] salt = new byte[8];
new SecureRandom().engineNextBytes(salt);
SecretKey derivedKey = makeKeyFromUserInput(userInput, salt);
Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
cipher.init(Cipher.ENCRYPT_MODE, derivedKey, new IvParameterSpec(
new byte[16]));
String plaintext = "Hello, World!";
byte[] cipherText = cipher.doFinal(plaintext.getBytes());
// Derive key again to demonstrate it is the same
SecretKey derivedKey2 = makeKeyFromUserInput(userInput, salt);
cipher.init(Cipher.DECRYPT_MODE, derivedKey2, new IvParameterSpec(
new byte[16]));
byte[] plainText = cipher.doFinal(cipherText);
// Prints "Hello, World!"
System.out.println(new String(plainText));
}
}
如果盐保持不变,则生成的密钥将是可重现的。在需要生成相同密钥的任何其他设备之间共享salt。
注意:您需要安装不受限制的策略文件(请参阅this page的底部)才能使用此示例。
请记住,从整体上看,保证由“安全”零碎组成的安全系统是安全的。我们只看到了你的要求的片段,因此我们的建议应该用一小撮盐(没有双关语)。要获得更完整的答案,我们需要了解您要保护的端到端流程。
但是,由于StackOverflow不是设计安全系统的地方,您可能需要在其他地方寻求此帮助。
答案 2 :(得分:0)
我不太确定你想要实现什么,但我认为你可以使用hash来加密你的字符串。
也许此链接可以提供帮助:How can I generate an MD5 hash?
最好在散列字符串之前先将字符串“加盐”。
答案 3 :(得分:0)
如果您只想要相对少量的输入,则可以使用字符的unicode和Random来生成随机数,但将所有结果存储在地图中。这样,如果已经创建了值,则不会重复生成值,而是使用缓存的值。