由于用户看不到字符串,因此生成随机“密钥”

时间:2012-08-24 08:56:41

标签: java string random key invisible

我正在寻找在java(在Windows上)执行以下当前任务的最佳方法:

由于用户输入的特定字符串,在程序内部创建一个随机的其他字符串/键(字母数字),并且用户不可见。

如果我们输入相同的字符串,则密钥必须相同。

所以基本上,我看到如何制作一个随机字符串,但我想确定该程序的用户无法找到内部给出的密钥(我实际上然后使用此密钥加密数据,并且因此我不希望简单的用户访问此密钥。)

我该怎么做?你能告诉我一个适当解决方案的代码运行示例吗?

编辑:我请求为用户输入的相同字符串使用相同的密钥,因为我需要知道这个生成的密钥,以便下次在我的计算机上使用,然后与另一个客户端一起使用。

4 个答案:

答案 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来生成随机数,但将所有结果存储在地图中。这样,如果已经创建了值,则不会重复生成值,而是使用缓存的值。