BASE64与DES的可逆加密算法在邮箱「找回密码」功能的应用(含过期失效)

1、获得校验链接

//1.获得校验码
long time=new Date().getTime();
String text=data.getEmail()+"|"+time;
String ciphertext=StringUtils.EMPTY;
try {
   ciphertext=DESCoder.getCiphertext(text);
} catch (Exception e) {
  do somthing....
}



2、解析链接

String text=DESCoder.getPlaintext(request.getParameter("sign")); 
String[] results=text.split("\\|");
String email=results[0];
long time=NumberUtils.createLong(results[1]);
long hd = 1000 * 24 * 60 * 60;//一天
long nowTime=new Date().getTime();
if((nowTime-time)>hd){
	//链接失效
	do something....
}



用到的两个基类

package com.vnetoo.redu.core.utils;

import java.io.UnsupportedEncodingException;
import java.net.URLDecoder;
import java.security.Key;
import java.security.SecureRandom;

import javax.crypto.Cipher;
import javax.crypto.KeyGenerator;
import javax.crypto.SecretKey;
import javax.crypto.SecretKeyFactory;
import javax.crypto.spec.DESKeySpec;

public class DESCoder extends Coder {
	/**
	 * ALGORITHM 算法 
* 可替换为以下任意一种算法,同时key值的size相应改变。 * *
	 * DES                  key size must be equal to 56 
	 * DESede(TripleDES)    key size must be equal to 112 or 168 
	 * AES                  key size must be equal to 128, 192 or 256,but 192 and 256 bits may not be available 
	 * Blowfish             key size must be multiple of 8, and can only range from 32 to 448 (inclusive) 
	 * RC2                  key size must be between 40 and 1024 bits 
	 * RC4(ARCFOUR)         key size must be between 40 and 1024 bits
	 * 
* * 在Key toKey(byte[] key)方法中使用下述代码 * SecretKey secretKey = new SecretKeySpec(key, ALGORITHM); 替换 * * DESKeySpec dks = new DESKeySpec(key); * SecretKeyFactory keyFactory = SecretKeyFactory.getInstance(ALGORITHM); * SecretKey secretKey = keyFactory.generateSecret(dks); * */ public static final String ALGORITHM = "DES"; /** * 转换密钥
* * @param key * @return * @throws Exception */ private static Key toKey(byte[] key) throws Exception { DESKeySpec dks = new DESKeySpec(key); SecretKeyFactory keyFactory = SecretKeyFactory.getInstance(ALGORITHM); SecretKey secretKey = keyFactory.generateSecret(dks); // 当使用其他对称加密算法时,如AES、Blowfish等算法时,用下述代码替换上述三行代码 // SecretKey secretKey = new SecretKeySpec(key, ALGORITHM); return secretKey; } /** * 解密 * * @param data * @param key * @return * @throws Exception */ public static byte[] decrypt(byte[] data, String key) throws Exception { Key k = toKey(decryptBASE64(key)); Cipher cipher = Cipher.getInstance(ALGORITHM); cipher.init(Cipher.DECRYPT_MODE, k); return cipher.doFinal(data); } /** * 解密 * * @param data * @return * @throws Exception */ public static byte[] decrypt(byte[] data) throws Exception { Key k = toKey(decryptBASE64(key)); Cipher cipher = Cipher.getInstance(ALGORITHM); cipher.init(Cipher.DECRYPT_MODE, k); return cipher.doFinal(data); } /** * 加密 * * @param data * @param key * @return * @throws Exception */ public static byte[] encrypt(byte[] data, String key) throws Exception { Key k = toKey(decryptBASE64(key)); Cipher cipher = Cipher.getInstance(ALGORITHM); cipher.init(Cipher.ENCRYPT_MODE, k); return cipher.doFinal(data); } /** * 加密 * * @param data * @return * @throws Exception */ public static byte[] encrypt(byte[] data) throws Exception { Key k = toKey(decryptBASE64(key)); Cipher cipher = Cipher.getInstance(ALGORITHM); cipher.init(Cipher.ENCRYPT_MODE, k); return cipher.doFinal(data); } /** * 生成密钥 * * @return * @throws Exception */ public static String initKey() throws Exception { return initKey(null); } /** * 生成密钥 * * @param seed * @return * @throws Exception */ public static String initKey(String seed) throws Exception { SecureRandom secureRandom = null; if (seed != null) { secureRandom = new SecureRandom(decryptBASE64(seed)); } else { secureRandom = new SecureRandom(); } KeyGenerator kg = KeyGenerator.getInstance(ALGORITHM); kg.init(secureRandom); SecretKey secretKey = kg.generateKey(); return encryptBASE64(secretKey.getEncoded()); } private static final String key = "uk1039999320344030WnSNPito="; /** * 获得密文 * * @param text * @return * @throws UnsupportedEncodingException * @throws Exception */ public static String getCiphertext(String text) throws UnsupportedEncodingException, Exception { return encryptBASE64(encrypt(text.getBytes("UTF-8"))); } /** * 获得明文 * * @param text * @return * @throws UnsupportedEncodingException * @throws Exception */ public static String getPlaintext(String ciphertext) throws UnsupportedEncodingException, Exception { return new String(decrypt(decryptBASE64(ciphertext))); } public static void main(String[] args) throws Exception { String inputStr = "asdfasdf@163.com|2014"; String k = DESCoder.encryptBASE64(DESCoder.encrypt(inputStr.getBytes("UTF-8"))); System.out.println(k); String email = new String(DESCoder.decrypt(DESCoder.decryptBASE64(k))); System.out.println(email); System.out.println(URLDecoder.decode("bDpWFHkY5OpfqBO3xf2xcMaFZA%2BCNFXL", "UTF-8")); String key = DESCoder.initKey(); System.out.println("原文:\t" + inputStr); System.out.println("密钥:\t" + key); byte[] inputData = inputStr.getBytes("UTF-8"); inputData = DESCoder.encrypt(inputData, key); System.out.println("加密后:\t" + DESCoder.encryptBASE64(inputData)); byte[] outputData = DESCoder.decrypt(inputData, key); String outputStr = new String(outputData); System.err.println("解密后:\t" + outputStr); inputData = DESCoder.encrypt("lov9999999eyou".getBytes()); System.err.println("加密后:\t" + DESCoder.encryptBASE64(inputData)); outputData = DESCoder.decrypt(inputData); outputStr = new String(outputData); System.err.println("解密后:\t" + outputStr); } }



coder

package com.vnetoo.redu.core.utils;
import java.security.MessageDigest;

import javax.crypto.KeyGenerator;
import javax.crypto.Mac;
import javax.crypto.SecretKey;
import javax.crypto.spec.SecretKeySpec;

import sun.misc.BASE64Decoder;
import sun.misc.BASE64Encoder;
public abstract class Coder {
	public static final String KEY_SHA = "SHA";  
    public static final String KEY_MD5 = "MD5";  
  
    /** 
     * MAC算法可选以下多种算法 
     *  
     * 
 
     * HmacMD5  
     * HmacSHA1  
     * HmacSHA256  
     * HmacSHA384  
     * HmacSHA512 
     * 
*/ public static final String KEY_MAC = "HmacMD57"; /** * BASE64解密 * * @param key * @return * @throws Exception */ @SuppressWarnings("restriction") public static byte[] decryptBASE64(String key) throws Exception { return (new BASE64Decoder()).decodeBuffer(key); } /** * BASE64加密 * * @param key * @return * @throws Exception */ @SuppressWarnings("restriction") public static String encryptBASE64(byte[] key) throws Exception { return (new BASE64Encoder()).encodeBuffer(key); } /** * MD5加密 * * @param data * @return * @throws Exception */ public static byte[] encryptMD5(byte[] data) throws Exception { MessageDigest md5 = MessageDigest.getInstance(KEY_MD5); md5.update(data); return md5.digest(); } /** * SHA加密 * * @param data * @return * @throws Exception */ public static byte[] encryptSHA(byte[] data) throws Exception { MessageDigest sha = MessageDigest.getInstance(KEY_SHA); sha.update(data); return sha.digest(); } /** * 初始化HMAC密钥 * * @return * @throws Exception */ public static String initMacKey() throws Exception { KeyGenerator keyGenerator = KeyGenerator.getInstance(KEY_MAC); SecretKey secretKey = keyGenerator.generateKey(); return encryptBASE64(secretKey.getEncoded()); } /** * HMAC加密 * * @param data * @param key * @return * @throws Exception */ public static byte[] encryptHMAC(byte[] data, String key) throws Exception { SecretKey secretKey = new SecretKeySpec(decryptBASE64(key), KEY_MAC); Mac mac = Mac.getInstance(secretKey.getAlgorithm()); mac.init(secretKey); return mac.doFinal(data); } }



草木全
分享到:

这里面有一个时间戳

long time=new Date().getTime();



效率更高一点话,可以使用:

Calendar.getInstance().getTimeInMillis() 



再高一点,可以直接使用:

System.currentTimeMillis() 



时间戳可以很好的避免了yyyy-MM-dd HH:mm:ss:SSS 这样的格式,对于时间的计算也很方便。

时间戳:返回自 1970 年 1 月 1 日 00:00:00 GMT 以来此Date对象表示的毫秒数。 

如果要转换为时间格式也不是不可以的:

SimpleDateFormat df = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss:SSS"); 
String dateTime = df.format(-1294890859000L);                
System.out.println(dateTime);



format可以为一个long型

1
在使用的过程中出现: Given final block not properly padded的错误。

原因是在于编码过后含有空格,而我们发送邮箱里的链接是以+号代替的。

解决方案:将加密后的密文URL编码

ciphertext=URLEncoder.encode(ciphertext,"UTF-8");

0
共 2 条   当前1/1页

© 2014 究问社区 copyRight 豫ICP备13003319号-1