如何将String转换为SecretKey

pal*_*laa 10 java encryption

我想将String转换为secretKey

public void generateCode(String keyStr){ 
KeyGenerator kgen = KeyGenerator.getInstance("AES");
kgen.init(128); // 192 and 256 bits may not be available
// Generate the secret key specs.
secretKey skey=keyStr;  //How can I make the casting here
//SecretKey skey = kgen.generateKey();
byte[] raw = skey.getEncoded();
}
Run Code Online (Sandbox Code Playgroud)

我尝试使用BASE64Decoder而不是secretKey,但我面临的一个问题是我无法指定密钥长度.

编辑: 我想从另一个地方调用此功能

 static public String encrypt(String message , String key , int keyLength) throws Exception {
     // Get the KeyGenerator
   KeyGenerator kgen = KeyGenerator.getInstance("AES");
    kgen.init(keyLength); // 192 and 256 bits may not be available
    // Generate the secret key specs.
     SecretKey skey = key; //here is the error
   byte[] raw = skey.getEncoded();
    SecretKeySpec skeySpec = new SecretKeySpec(raw, "AES");
    // Instantiate the cipher
    Cipher cipher = Cipher.getInstance("AES");

    cipher.init(Cipher.ENCRYPT_MODE, skeySpec);
    System.out.println("msg is" + message + "\n raw is" + raw);
    byte[] encrypted = cipher.doFinal(message.getBytes());
    String cryptedValue = new String(encrypted);
    System.out.println("encrypted string: " + cryptedValue);
    return cryptedValue;
}
Run Code Online (Sandbox Code Playgroud)

如果有人可以提供帮助,我会非常感激.

Maa*_*wes 37

由于这些特殊原因,没有完整性检查

  1. 用例并不明显.
  2. "AES/GCM/NoPadding" 模式仅适用于Java 7以上版本
  3. 它取决于用户是否要部署例如HMAC和/或AESCMAC(推荐).
  4. 它至少需要额外的钥匙,并且需要两次完整的通行证.

如果您在双方都实现了GCM模式 - 例如在Java 6上使用Bouncy Castle - 请继续使用它,因为它更安全(只要"IV"真的是唯一的).改变实施应该很容易.

有关加密的实施说明

  1. 当在无限制的客户端/服务器角色中使用时,这种实现是不安全的,因为填充oracle攻击(它们每字节需要128次尝试或更低,平均而言,与算法或密钥大小无关).您需要在加密数据上使用MAC,HMAC或签名,并在解密之前对其进行验证,以便在客户端/服务器模式下进行部署.
  2. 如果解密失败,Decrypt将返回null.这只能指示一个填充异常,应该对其进行充分处理(我是否警告填充oracle攻击?)
  3. 无效的密钥将作为返回InvalidArgumentException.
  4. 所有其他与安全相关的异常都"在表下扫描",因为它意味着Java运行时环境无效.例如,支持"UTF-8"并且"AES/CBC/PKCS5Padding"是每个Java SE实现所必需的.

其他一些说明

  1. 请不要尝试相反的方法并将字节直接插入到encrypt方法的输入字符串中(new String(byte[])例如使用).该方法可能会无声地失败!
  2. 针对可读性进行了优化.CipherStream如果您更喜欢速度和更好的内存占用,请选择Base64流和实现.
  3. 您至少需要Java 6 SE或兼容才能运行此代码.
  4. 对于超过128位的AES密钥大小,加密/解密可能会失败,因为您可能需要用于无限制加密的策略文件(可从Oracle获得)
  5. 导出加密时要注意政府规定.
  6. 此实现使用十六进制键而不是base64键,因为它们足够小,十六进制更容易手动编辑/验证.
  7. 使用从JDK检索的hex和base64编码/解码,无需任何外部库.
  8. 优步易于使用,但当然不是非常面向对象,没有加密/解密中使用的对象实例的缓存.随意重构.

好的,这里有一些代码......

    public static String encrypt(final String plainMessage,
            final String symKeyHex) {
        final byte[] symKeyData = DatatypeConverter.parseHexBinary(symKeyHex);

        final byte[] encodedMessage = plainMessage.getBytes(Charset
                .forName("UTF-8"));
        try {
            final Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
            final int blockSize = cipher.getBlockSize();

            // create the key
            final SecretKeySpec symKey = new SecretKeySpec(symKeyData, "AES");

            // generate random IV using block size (possibly create a method for
            // this)
            final byte[] ivData = new byte[blockSize];
            final SecureRandom rnd = SecureRandom.getInstance("SHA1PRNG");
            rnd.nextBytes(ivData);
            final IvParameterSpec iv = new IvParameterSpec(ivData);

            cipher.init(Cipher.ENCRYPT_MODE, symKey, iv);

            final byte[] encryptedMessage = cipher.doFinal(encodedMessage);

            // concatenate IV and encrypted message
            final byte[] ivAndEncryptedMessage = new byte[ivData.length
                    + encryptedMessage.length];
            System.arraycopy(ivData, 0, ivAndEncryptedMessage, 0, blockSize);
            System.arraycopy(encryptedMessage, 0, ivAndEncryptedMessage,
                    blockSize, encryptedMessage.length);

            final String ivAndEncryptedMessageBase64 = DatatypeConverter
                    .printBase64Binary(ivAndEncryptedMessage);

            return ivAndEncryptedMessageBase64;
        } catch (InvalidKeyException e) {
            throw new IllegalArgumentException(
                    "key argument does not contain a valid AES key");
        } catch (GeneralSecurityException e) {
            throw new IllegalStateException(
                    "Unexpected exception during encryption", e);
        }
    }

    public static String decrypt(final String ivAndEncryptedMessageBase64,
            final String symKeyHex) {
        final byte[] symKeyData = DatatypeConverter.parseHexBinary(symKeyHex);

        final byte[] ivAndEncryptedMessage = DatatypeConverter
                .parseBase64Binary(ivAndEncryptedMessageBase64);
        try {
            final Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
            final int blockSize = cipher.getBlockSize();

            // create the key
            final SecretKeySpec symKey = new SecretKeySpec(symKeyData, "AES");

            // retrieve random IV from start of the received message
            final byte[] ivData = new byte[blockSize];
            System.arraycopy(ivAndEncryptedMessage, 0, ivData, 0, blockSize);
            final IvParameterSpec iv = new IvParameterSpec(ivData);

            // retrieve the encrypted message itself
            final byte[] encryptedMessage = new byte[ivAndEncryptedMessage.length
                    - blockSize];
            System.arraycopy(ivAndEncryptedMessage, blockSize,
                    encryptedMessage, 0, encryptedMessage.length);

            cipher.init(Cipher.DECRYPT_MODE, symKey, iv);

            final byte[] encodedMessage = cipher.doFinal(encryptedMessage);

            // concatenate IV and encrypted message
            final String message = new String(encodedMessage,
                    Charset.forName("UTF-8"));

            return message;
        } catch (InvalidKeyException e) {
            throw new IllegalArgumentException(
                    "key argument does not contain a valid AES key");
        } catch (BadPaddingException e) {
            // you'd better know about padding oracle attacks
            return null;
        } catch (GeneralSecurityException e) {
            throw new IllegalStateException(
                    "Unexpected exception during decryption", e);
        }
    }
Run Code Online (Sandbox Code Playgroud)

用法:

    String plain = "Zaphod's just zis guy, ya knöw?";
    String encrypted = encrypt(plain, "000102030405060708090A0B0C0D0E0F");
    System.out.println(encrypted);
    String decrypted = decrypt(encrypted, "000102030405060708090A0B0C0D0E0F");
    if (decrypted != null && decrypted.equals(plain)) {
        System.out.println("Hey! " + decrypted);
    } else {
        System.out.println("Bummer!");
    }
Run Code Online (Sandbox Code Playgroud)

  • 要在Java 7中使用"AES/GCM/NoPadding"模式加密,请将'IvParameterSpec`的代码替换为['GCMParameterSpec params = new GCMParameterSpec(blockSize*Byte.SIZE,ivData);'](http:// docs.oracle.com/javase/7/docs/api/javax/crypto/spec/GCMParameterSpec.html)并且不要忘记处理[`AEADBadTagException`](http://docs.oracle.com/javase/ 7/docs/api/javax/crypto`/AEADBadTagException.html)来捕获完整性异常.Bouncy将通过简单地使用"AES/GCM/NoPadding"来工作,并将抛出BadPaddingException,返回null. (2认同)