【问题标题】:How to generate secret key using SecureRandom.getInstanceStrong()?如何使用 SecureRandom.getInstanceStrong() 生成密钥?
【发布时间】:2016-05-15 21:54:33
【问题描述】:

如何使用 SecureRandom.getInstanceStrong() 生成密钥?

使用此代码,我可以接收具有随机值的字节数组。是否有任何简单的方法来生成给定长度(例如256位)、类型(int、String)和格式(hex的密钥>, bin, dec)?

package com.company;

import java.security.NoSuchAlgorithmException;
import java.security.SecureRandom;

public class KeyGen {

    public void generate() throws NoSuchAlgorithmException {

        SecureRandom random = SecureRandom.getInstanceStrong();
        byte[] values = new byte[32]; // 256 bit
        random.nextBytes(values);

        StringBuilder sb = new StringBuilder();
        for (byte b : values) {
            sb.append(String.format("%02x", b));
        }
        System.out.print("Key: ");
        System.out.println(sb.toString());
    }
}

输出:

Key: 8fcea84897f48f575c22441ece4e7ddb43ac08cd2c1a83fca46c080768468059

【问题讨论】:

  • 你当然应该把你的包命名为com.pany :)
  • @MaartenBodewes 只是 IntelliJ IDEA 中的默认模板。
  • 啊,好吧,默认使用Eclipse,不知道。对于您自己的密码,您当前的代码似乎没有太大问题。不过,您可能会考虑密钥管理。也许将随机密钥放在某种容器中是个好主意,或者使用教师的公共 PGP 密钥对其进行加密(例如,使用 Bouncy Castle 功能)。

标签: java security random key


【解决方案1】:

键应该是特定类型的,例如AES。最好将它们保存在 SecretKey 实例或类似的 Key 派生类中。

现代对称密码的密钥由位组成。通常你不需要它们的人/字符串表示(这实际上可能会损害安全性)。将它们存储在KeyStore 中,或者从密码中派生它们。如果你对它们进行编码,那么表示格式是无关紧要的,只要你在转换过程中不丢失数据。

这可能是生成强 AES 密钥的最佳方式:

public class GenerateStrongAESKey {

    public static SecretKey generateStrongAESKey(final int keysize) {
        final KeyGenerator kgen;
        try {
            kgen = KeyGenerator.getInstance("AES");
        } catch (final NoSuchAlgorithmException e) {
            throw new RuntimeException("AES key generator should always be available in a Java runtime", e);
        }
        final SecureRandom rng;
        try {
            rng = SecureRandom.getInstanceStrong();
        } catch (final NoSuchAlgorithmException e) {
            throw new RuntimeException("No strong secure random available to generate strong AES key", e);
        }
        // already throws IllegalParameterException for wrong key sizes
        kgen.init(keysize, rng);

        return kgen.generateKey();
    }

    public static void main(String[] args) {
        SecretKey strongAESKey = generateStrongAESKey(256);
        // well, if you must have a human readable string, here it is
        // but you've been warned
        System.out.println(toHex(strongAESKey.getEncoded()));
    }

    private static String toHex(final byte[] data) {
        final StringBuilder sb = new StringBuilder(data.length * 2);
        for (byte b : data) {
            sb.append(String.format("%02X", b));
        }
        return sb.toString();
    }
}

注意:这需要 Oracle 运行时环境的密钥 > 128 位的无限强度管辖文件。

【讨论】:

  • 我需要human readable string 来实现我的 GOST/Magma 分组密码。就我而言,我需要向老师展示加密密钥。或者以某种方式拯救他。
  • 但是如果我们得到相同的 (?) 结果,我不完全理解你的代码和我的代码之间有什么根本区别。
  • 不同之处在于您的代码仅使用字节数组,而我的代码使用 JCE。输出值可能相同(或至少是相同类型的随机值),但上述代码可能会保护密钥或在可用时使用硬件设备。当然,如果您想为自制密码生成密钥,这并不是很有帮助。在这种情况下,您的代码几乎没有问题。如前所述,幸运的是,Java 不会将十六进制或其他人类可读的字符串作为(不安全的)默认值输出。
猜你喜欢
  • 2015-07-22
  • 1970-01-01
  • 2022-11-01
  • 1970-01-01
  • 2016-12-24
  • 2011-01-28
  • 2015-04-28
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多