在Java中执行身份验证加密的正确方法是什么? [英] What is the proper way to perform authenticated encryption in Java?

查看:530
本文介绍了在Java中执行身份验证加密的正确方法是什么?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

认证加密要求我们使用一些可接受的标准来加密和验证消息。所以我们都对消息进行加密,并在消息上计算一个MAC,以验证它没有被篡改。



这个问题概述了执行基于密码的密钥加密和加密的方法:

  / *导出密钥,给定密码和盐。 * / 
SecretKeyFactory factory = SecretKeyFactory.getInstance(PBKDF2WithHmacSHA1);
KeySpec spec = new PBEKeySpec(password,salt,65536,256);
SecretKey tmp = factory.generateSecret(spec);
SecretKey secret = new SecretKeySpec(tmp.getEncoded(),AES);
/ *加密消息。 * /
密码密码= Cipher.getInstance(AES / CBC / PKCS5Padding);
cipher.init(Cipher.ENCRYPT_MODE,secret);
AlgorithmParameters params = cipher.getParameters();
byte [] iv = params.getParameterSpec(IvParameterSpec.class).getIV();
byte [] ciphertext = cipher.doFinal(Hello,World!。getBytes(UTF-8));

但据我所知,这并不计算密文上的任何MAC,不安全的。在Java中执行认证加密的接受标准是什么?

解决方案

我建议使用GCM模式加密。它默认包含在最新的JDK(1.7)中。它使用计数器模式加密(流密码,不需要填充)并添加认证标签。一个很大的优点是它只需要一个键,而HMAC为混合添加了另一个键。 Bouncy Castle也有一个实现,它与Oracle提供的兼容。



GCM模式加密也是TLS RFC和XML加密1.1(两者都不是最终的)。 GCM模式提供了所有三种安全功能:保密性,完整性和数据发送的真实性。字符串将是AES / GCM / NoPadding,而不是您正在部署的CBC。如上所述,请确保您拥有Oracle的最新JDK,或安装了Bouncy Castle提供商。



同时查看我的答案这里,这主要是关于String编码,但是我也成功地尝试了GCM模式 - 看到评论。 / p>

Authenticated encryption requires that we use some accepted standard for encrypting and authenticating a message. So we both encrypt the message and compute a MAC on the message to verify it has not been tampered with.

This question outlines a way to perform password based key strengthening and encryption:

/* Derive the key, given password and salt. */
SecretKeyFactory factory = SecretKeyFactory.getInstance("PBKDF2WithHmacSHA1");
KeySpec spec = new PBEKeySpec(password, salt, 65536, 256);
SecretKey tmp = factory.generateSecret(spec);
SecretKey secret = new SecretKeySpec(tmp.getEncoded(), "AES");
/* Encrypt the message. */
Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
cipher.init(Cipher.ENCRYPT_MODE, secret);
AlgorithmParameters params = cipher.getParameters();
byte[] iv = params.getParameterSpec(IvParameterSpec.class).getIV();
byte[] ciphertext = cipher.doFinal("Hello, World!".getBytes("UTF-8"));

But as far as I can tell, this does not compute any MAC on the ciphertext and so would be insecure. What is the accepted standard for performing authenticated encryption in Java?

解决方案

I would recommend using GCM mode encryption. It is included in the latest JDK (1.7) by default. It uses a counter mode encryption (a stream cipher, no padding required) and adds an authentication tag. One big advantage is that it requires only a single key, whereas HMAC adds another key to the mix. Bouncy Castle has an implementation as well, which is moslty compatible with one provided by Oracle.

GCM mode encryption is also features in a TLS RFC, and in XML encrypt 1.1 (both not final). GCM mode provides all three security features: confidentiality, integrity and authenticity of the data send. The String would be "AES/GCM/NoPadding" instead of the CBC one you are now deploying. As said, make sure you have the latest JDK from Oracle, or have Bouncy Castle provider installed.

Also check out my answer here, which is mostly about String encoding, but I've succesfully tried GCM mode too - see the comment.

这篇关于在Java中执行身份验证加密的正确方法是什么?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆