如何在 Java 中加密 URL 请求参数值以在电子邮件链接中使用
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/20401576/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
How to encrypt URL request parameter values in java for use in an emailed link
提问by Rahul Sahu
I am facing one problem related to encrypt url request parameter values. My scene is this I am sending one hyperlink to user through email and I want to hide url contains data from user. Url contains data that I am accessing through request object in struts application. and same values I am using on jsp page by using EL. So how can I encrypt data and how to maintain on jsp page and struts also?
我面临一个与加密 url 请求参数值相关的问题。我的场景是我通过电子邮件向用户发送一个超链接,我想隐藏包含来自用户的数据的 url。Url 包含我通过 struts 应用程序中的请求对象访问的数据。和我在 jsp 页面上使用 EL 使用的相同值。那么如何加密数据以及如何在jsp页面和struts上维护呢?
below code I am using for encrypt ans decrypt the data... but If i encrypt my request parameter value then how I can get decrypted value at jsp?
下面的代码我用于加密和解密数据......但是如果我加密我的请求参数值,那么我如何在jsp上获得解密值?
import java.security.Key;
import javax.crypto.Cipher;
import javax.crypto.spec.SecretKeySpec;
import sun.misc.BASE64Decoder;
import sun.misc.BASE64Encoder;
@SuppressWarnings("restriction")
public class EncryptDecrypt {
private static final String ALGO = "AES";
private static final byte[] keyValue = new byte[] { 'T', 'h', 'e', 'B',
'e', 's', 't', 'S', 'e', 'c', 'r', 'e', 't', 'K', 'e', 'y' };
public static String encrypt(String Data) throws Exception {
Key key = generateKey();
Cipher c = Cipher.getInstance(ALGO);
c.init(Cipher.ENCRYPT_MODE, key);
byte[] encVal = c.doFinal(Data.getBytes());
String encryptedValue = new BASE64Encoder().encode(encVal);
return encryptedValue;
}
public static String decrypt(String encryptedData) throws Exception {
Key key = generateKey();
Cipher c = Cipher.getInstance(ALGO);
c.init(Cipher.DECRYPT_MODE, key);
byte[] decordedValue = new BASE64Decoder().decodeBuffer(encryptedData);
byte[] decValue = c.doFinal(decordedValue);
String decryptedValue = new String(decValue);
return decryptedValue;
}
private static Key generateKey() throws Exception {
Key key = new SecretKeySpec(keyValue, ALGO);
return key;
}
}
采纳答案by Tim B
You can use any encryption scheme you like since you are sending the already-encrypted data to the user and then processing it again. You don't even need public/private key approaches for this.
您可以使用任何您喜欢的加密方案,因为您是将已加密的数据发送给用户,然后再次对其进行处理。为此,您甚至不需要公钥/私钥方法。
https://stackoverflow.com/questions/4319496/how-to-encrypt-and-decrypt-data-in-java
https://stackoverflow.com/questions/4319496/how-to-encrypt-and-decrypt-data-in-java
Just encrypt the data before you send it in the email link - then when you get it back decrypt it again.
只需在通过电子邮件链接发送数据之前加密数据 - 然后当您取回时再次解密它。
The linked question has been deleted, I've tried to get it undeleted but in case it does not here is the content. All credit to ataylor who wrote it.
链接的问题已被删除,我试图将其取消删除,但如果它不是这里的内容。所有的功劳都归功于写它的ataylor。
Unless you have very unusual requirements, Java has most of the crypto tools you'll need.
除非您有非常不寻常的要求,否则 Java 拥有您需要的大部分加密工具。
Symmetric Encryption
对称加密
Symmetric encryption uses the same key for both encryption and decryption. In Java, use an instance of javax.crypto.Cipher
.
对称加密使用相同的密钥进行加密和解密。在 Java 中,使用javax.crypto.Cipher
.
Encrypting and Decrypting
加密和解密
Initialize cipher in the appropriate mode and call the update
and doFinal
methods to encrypt or decrypt. Example:
在适当的模式下初始化 cipher 并调用update
和doFinal
方法来加密或解密。例子:
import java.security.*;
import javax.crypto.*;
Cipher aes = Cipher.getInstance("AES/ECB/PKCS5Padding");
aes.init(Cipher.ENCRYPT_MODE, key);
byte[] ciphertext = aes.doFinal("my cleartext".getBytes());
aes.init(Cipher.DECRYPT_MODE, key);
String cleartext = new String(aes.doFinal(ciphertext));
Creating the Keys
创建密钥
The key for the cipher should be an instance of javax.crypto.spec.SecretKeySpec
. AES in particular requires its key to be created with exactly 128 bits (16 bytes).
密码的密钥应该是 的一个实例javax.crypto.spec.SecretKeySpec
。AES 尤其需要使用恰好 128 位(16 字节)创建其密钥。
A simple way to get the required number of bytes is to take a variable length passphrase and hash it with a java.security.MessageDigest
such as SHA1. For example:
获取所需字节数的一种简单方法是采用可变长度的密码短语并使用java.security.MessageDigest
诸如 SHA1 之类的哈希值对其进行散列。例如:
import java.security.*;
import javax.crypto.spec.*;
String passphrase = "correct horse battery staple";
MessageDigest digest = MessageDigest.getInstance("SHA");
digest.update(passphrase.getBytes());
SecretKeySpec key = new SecretKeySpec(digest.digest(), 0, 16, "AES");
A better way to create a key is with a SecretKeyFactory using a salt:
创建密钥的更好方法是使用使用盐的 SecretKeyFactory:
byte[] salt = "choose a better salt".getBytes();
int iterations = 10000;
SecretKeyFactory factory = SecretKeyFactory.getInstance("PBKDF2WithHmacSHA1");
SecretKey tmp = factory.generateSecret(new PBEKeySpec(passphrase.toCharArray(), salt, iterations, 128));
SecretKeySpec key = new SecretKeySpec(tmp.getEncoded(), "AES");
PBKDF2is an algorithm specially designed for generating keys from passwords that is considered more secure than a simple SHA1 hash. The salt ensures your encryption won't match another encryption using the same key and cleartext and helps prevent dictionary attacks. The iterations value is an adjustable parameter. Higher values use more computing power, making brute force attacks more difficult.
PBKDF2是一种专门设计用于从密码生成密钥的算法,被认为比简单的 SHA1 哈希更安全。salt 确保您的加密不会与使用相同密钥和明文的另一个加密匹配,并有助于防止字典攻击。迭代值是一个可调参数。较高的值使用更多的计算能力,使蛮力攻击更加困难。
Initialization Vectors
初始化向量
As noted in the comments, ECB almost never a good mode to use in practice. To use better modes like CBC, you'll need to provide and preserve an initialization vector.
正如评论中所指出的,欧洲央行几乎从来没有在实践中使用的好模式。要使用更好的模式,如 CBC,您需要提供并保留一个初始化向量。
When encrypting with CBC mode, Java will automatically generate a random initialization vector. To be able to decrypt it later, you'll need to save it along with the ciphertext:
使用 CBC 模式加密时,Java 会自动生成一个随机初始化向量。为了以后能够解密它,您需要将它与密文一起保存:
Cipher aes = Cipher.getInstance("AES/CBC/PKCS5Padding");
aes.init(Cipher.ENCRYPT_MODE, key);
byte[] ciphertext = aes.doFinal("my cleartext".getBytes());
byte[] iv = aes.getIV();
When decrypting, pass it to the Cipher.init()
method as a parameter:
解密时,将其Cipher.init()
作为参数传递给方法:
Cipher aes = Cipher.getInstance("AES/CBC/PKCS5Padding");
aes.init(Cipher.DECRYPT_MODE, key, new IvParameterSpec(iv));
String cleartext = new String(aes.doFinal(ciphertext));
Asymmetric Encryption
非对称加密
Asymmetric encryption, also called public key encryption, uses a key pair. One part of the key is used to encrypt and the other to decrypt. This allows you to make the encryption key public, allowing anyone to generate messages only you, the holder of the private decryption key, can read. Alternatively, you can encrypt with the private key, useful for digital signatures.
非对称加密,也称为公钥加密,使用密钥对。密钥的一部分用于加密,另一部分用于解密。这允许您公开加密密钥,允许任何人生成只有您(私有解密密钥的持有者)才能读取的消息。或者,您可以使用私钥加密,这对数字签名很有用。
Encrypting and Decrypting
加密和解密
As with symmetric encryption, use an instance of javax.crypto.Cipher
:
与对称加密一样,使用以下实例javax.crypto.Cipher
:
import java.security.*;
Cipher rsa = Cipher.getInstance("RSA/ECB/PKCS1Padding");
rsa.init(Cipher.ENCRYPT_MODE, publicKey);
byte[] ciphertext = rsa.doFinal("my cleartext".getBytes());
rsa.init(Cipher.DECRYPT_MODE, privateKey);
String cleartext = new String(rsa.doFinal(ciphertext));
Generating and Storing the Keys
生成和存储密钥
In this case the keys will be instances of java.security.PublicKey
and java.security.PrivateKey
. To generate a new pair:
在这种情况下,键将是java.security.PublicKey
和 的实例java.security.PrivateKey
。要生成新对:
import java.security.*;
KeyPairGenerator keyPairGenerator = KeyPairGenerator.getInstance("RSA");
KeyPair keyPair = keyPairGenerator.generateKeyPair();
PublicKey publicKey = keyPair.getPublic();
PrivateKey privateKey = keyPair.getPrivate();
Public and private keys can also be transformed into byte arrays for storage and transmission:
公钥和私钥也可以转化为字节数组进行存储和传输:
import java.security.*;
import java.security.spec.*;
KeyFactory keyFactory = KeyFactory.getInstance("RSA");
byte[] publicKeyBytes = publicKey.getEncoded();
KeySpec keySpec = new X509EncodedKeySpec(publicKeyBytes);
PublicKey keyFromBytes = keyFactory.generatePublic(keySpec);