销毁SecretKey会抛出DestroyFailedException吗?

时间:2016-07-08 23:46:19

标签: java java-8

我正在编写一个函数,使用SecretKeyFactory基于密码生成密钥(字节)。

,我想在不再需要时销毁SecretKey实例。但是它会抛出异常。

try {
    byte[] salt = new byte[] { 1, 2, 3, 4, 5, 6, 7, 8 };

    SecretKeyFactory factory = SecretKeyFactory.getInstance("PBKDF2WithHmacSHA256");

    PBEKeySpec keySpec = new PBEKeySpec("password".toCharArray(), salt, 1000, 256);

    SecretKey secretkey = factory.generateSecret(keySpec);
    byte[] key = secretkey.getEncoded();

    // Using key

    // Destroy key
    Arrays.fill(key, (byte)0);

    // Destroy secretKey
    secretkey.destroy();  // --> Throw DestroyFailedException

} catch (Exception e) {
    e.printStackTrace();
}

我在Mac上使用Oracle JDK1.8.0_66。

我看看SecretKey源代码,我发现这个默认实现(SecretKey实现了Destroyable接口)

public default void destroy() throws DestroyFailedException {
    throw new DestroyFailedException();
}

这意味着:SecretKey的实现不会覆盖destroy方法来销毁内部密码字符和内部密钥字节。

这是JDK 8中的错误吗?

2 个答案:

答案 0 :(得分:2)

你是对的。 verbatim string literal类不实现从Destroyable继承的destroy方法。 PBKDF2KeyImpl

这不一定是JDK中的错误,因为It also looks like you are not the first person to be concerned by this的API明确地将它留给实现类来定义这种行为,尽管这种行为没有被覆盖似乎有点奇怪。

答案 1 :(得分:0)

这对我来说非常糟糕。我也在寻找破坏SecretKey的方法。用反射怎么样?我知道这是超级hacky,但它允许我们获得底层私钥组:

public class DestroyableSecretKeySpec extends SecretKeySpec {
    public DestroyableSecretKeySpec( byte[] key, int offset, int len, String algorithm ) {
        super( key, offset, len, algorithm );
    }

    @Override
    public void destroy() {
        try {
            // Use hacky reflection to clear the underlying private key from memory.
            // This is so ugly :/
            Field f = SecretKeySpec.class.getDeclaredField( "key" );
            f.setAccessible(true);
            byte[] key = (byte[]) f.get( this );
            Arrays.fill( key, (byte)0xCC );
        } catch( NoSuchFieldException | IllegalAccessException e ) {
            throw new EncryptionException( "Can't use reflection to clear a secret key.", e );
        }
    }
}

你认为这有什么问题吗?