将密钥转换为字符串和反之亦然

Pri*_*raj 92 java string encryption

我正在生成一个密钥并需要将其存储在DB中,因此我将其转换为String,但要从String中获取密钥.有哪些可能的方法来实现这一目标?

我的代码是,

SecretKey key = KeyGenerator.getInstance("AES").generateKey();
String stringKey=key.toString();
System.out.println(stringKey);
Run Code Online (Sandbox Code Playgroud)

如何从String获取密钥?

Jab*_*ari 248

您可以将其转换SecretKey为字节数组(byte[]),然后将Base64编码为a String.要转换回a SecretKey,Base64解码String并在a中使用它SecretKeySpec来重建原始SecretKey.

对于Java 8

SecretKey to String:

// create new key
SecretKey secretKey = KeyGenerator.getInstance("AES").generateKey();
// get base64 encoded version of the key
String encodedKey = Base64.getEncoder().encodeToString(secretKey.getEncoded());
Run Code Online (Sandbox Code Playgroud)

字符串到SecretKey:

// decode the base64 encoded string
byte[] decodedKey = Base64.getDecoder().decode(encodedKey);
// rebuild key using SecretKeySpec
SecretKey originalKey = new SecretKeySpec(decodedKey, 0, decodedKey.length, "AES"); 
Run Code Online (Sandbox Code Playgroud)

对于Java 7及之前(包括Android):

注意I:您可以跳过Base64编码/解码部分,只存储byte[]在SQLite中.也就是说,执行Base64编码/解码并不是一项昂贵的操作,您几乎可以在任何数据库中存储字符串而不会出现问题.

注释II:早期的Java版本不包含其中一个java.lang或一个java.util包中的Base64 .但是,可以使用Apache Commons Codec,Bouncy CastleGuava中的编解码器.

SecretKey to String:

// CREATE NEW KEY
// GET ENCODED VERSION OF KEY (THIS CAN BE STORED IN A DB)

    SecretKey secretKey;
    String stringKey;

    try {secretKey = KeyGenerator.getInstance("AES").generateKey();}
    catch (NoSuchAlgorithmException e) {/* LOG YOUR EXCEPTION */}

    if (secretKey != null) {stringKey = Base64.encodeToString(secretKey.getEncoded(), Base64.DEFAULT)}
Run Code Online (Sandbox Code Playgroud)

字符串到SecretKey:

// DECODE YOUR BASE64 STRING
// REBUILD KEY USING SecretKeySpec

    byte[] encodedKey     = Base64.decode(stringKey, Base64.DEFAULT);
    SecretKey originalKey = new SecretKeySpec(encodedKey, 0, encodedKey.length, "AES");
Run Code Online (Sandbox Code Playgroud)


Maa*_*wes 5

为了说明创建一些快速失败的函数有多么有趣,我编写了以下3个函数。

一个创建一个AES密钥,一个对其进行编码,然后一个对其进行解码。这三种方法可以与Java 8一起使用(不依赖内部类或外部依赖):

public static SecretKey generateAESKey(int keysize)
        throws InvalidParameterException {
    try {
        if (Cipher.getMaxAllowedKeyLength("AES") < keysize) {
            // this may be an issue if unlimited crypto is not installed
            throw new InvalidParameterException("Key size of " + keysize
                    + " not supported in this runtime");
        }

        final KeyGenerator keyGen = KeyGenerator.getInstance("AES");
        keyGen.init(keysize);
        return keyGen.generateKey();
    } catch (final NoSuchAlgorithmException e) {
        // AES functionality is a requirement for any Java SE runtime
        throw new IllegalStateException(
                "AES should always be present in a Java SE runtime", e);
    }
}

public static SecretKey decodeBase64ToAESKey(final String encodedKey)
        throws IllegalArgumentException {
    try {
        // throws IllegalArgumentException - if src is not in valid Base64
        // scheme
        final byte[] keyData = Base64.getDecoder().decode(encodedKey);
        final int keysize = keyData.length * Byte.SIZE;

        // this should be checked by a SecretKeyFactory, but that doesn't exist for AES
        switch (keysize) {
        case 128:
        case 192:
        case 256:
            break;
        default:
            throw new IllegalArgumentException("Invalid key size for AES: " + keysize);
        }

        if (Cipher.getMaxAllowedKeyLength("AES") < keysize) {
            // this may be an issue if unlimited crypto is not installed
            throw new IllegalArgumentException("Key size of " + keysize
                    + " not supported in this runtime");
        }

        // throws IllegalArgumentException - if key is empty
        final SecretKeySpec aesKey = new SecretKeySpec(keyData, "AES");
        return aesKey;
    } catch (final NoSuchAlgorithmException e) {
        // AES functionality is a requirement for any Java SE runtime
        throw new IllegalStateException(
                "AES should always be present in a Java SE runtime", e);
    }
}

public static String encodeAESKeyToBase64(final SecretKey aesKey)
        throws IllegalArgumentException {
    if (!aesKey.getAlgorithm().equalsIgnoreCase("AES")) {
        throw new IllegalArgumentException("Not an AES key");
    }

    final byte[] keyData = aesKey.getEncoded();
    final String encodedKey = Base64.getEncoder().encodeToString(keyData);
    return encodedKey;
}
Run Code Online (Sandbox Code Playgroud)

  • 请注意,如果密钥存储区位于硬件安全模块上(或其他任何无法使用“ getEncoded()”的位置),则存储/检索密钥可能不起作用。 (2认同)