Java 加密解密之消息摘要算法(MD5 SHA MAC) http://aub.iteye.com/blog/1131494
现有的消息摘要算法
消息摘要算法包含MD、SHA和MAC三大系列,常用于验证数据的完整性,是数据签名算法的核心算法。
MAC与MD和SHA不同,MAC是含有密钥的散列函数算法,我们也常把MAC称为HMAC。
JDK对消息摘要算法的支持
JDK6支持MD2/MD5/SHA/SHA256/SHA384/SHA512/HmacMD5/HmacSHA1/ HmacSHA256/HmacSHA384/HmacSHA512
使用到 十六进制工具类Hex.java 见: java byte数组与十六进制字符串互转
MD和SHA系列的java实现:
DigestUtils.java
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 |
import java.security.MessageDigest; import java.security.NoSuchAlgorithmException; /** * reference apache commons <a * href="http://commons.apache.org/codec/">http://commons.apache.org/codec/</a> * * support MD2/MD5/SHA/SHA256/SHA384/SHA512 * @author Aub * */ public class DigestUtils { /** * 根据给定摘要算法创建一个消息摘要实例 * * @param algorithm * 摘要算法名 * @return 消息摘要实例 * @see MessageDigest#getInstance(String) * @throws RuntimeException * 当 {@link java.security.NoSuchAlgorithmException} 发生时 */ static MessageDigest getDigest(String algorithm) { try { return MessageDigest.getInstance(algorithm); } catch (NoSuchAlgorithmException e) { throw new RuntimeException(e.getMessage()); } } /** * 获取 MD5 消息摘要实例 * * @return MD5 消息摘要实例 * @throws RuntimeException * 当 {@link java.security.NoSuchAlgorithmException} 发生时 */ private static MessageDigest getMd5Digest() { return getDigest("MD5"); } /** * 获取 SHA-1 消息摘要实例 * * @return SHA-1 消息摘要实例 * @throws RuntimeException * 当 {@link java.security.NoSuchAlgorithmException} 发生时 */ private static MessageDigest getShaDigest() { return getDigest("SHA"); } /** * 获取 SHA-256 消息摘要实例 * * @return SHA-256 消息摘要实例 * @throws RuntimeException * 当 {@link java.security.NoSuchAlgorithmException} 发生时 */ private static MessageDigest getSha256Digest() { return getDigest("SHA-256"); } /** * 获取 SHA-384 消息摘要实例 * * @return SHA-384 消息摘要实例 * @throws RuntimeException * 当 {@link java.security.NoSuchAlgorithmException} 发生时 */ private static MessageDigest getSha384Digest() { return getDigest("SHA-384"); } /** * 获取 SHA-512 消息摘要实例 * * @return SHA-512 消息摘要实例 * @throws RuntimeException * 当 {@link java.security.NoSuchAlgorithmException} 发生时 */ private static MessageDigest getSha512Digest() { return getDigest("SHA-512"); } /** * 使用MD5消息摘要算法计算消息摘要 * * @param data * 做消息摘要的数据 * @return 消息摘要(长度为16的字节数组) */ public static byte[] encodeMD5(byte[] data) { return getMd5Digest().digest(data); } /** * 使用MD5消息摘要算法计算消息摘要 * * @param data * 做消息摘要的数据 * @return 消息摘要(长度为32的十六进制字符串) */ public static String encodeMD5Hex(byte[] data) { return Hex.encodeHexStr(encodeMD5(data)); } /** * 使用SHA-1消息摘要算法计算消息摘要 * * @param data * 做消息摘要的数据 * @return SHA-1消息摘要(长度为20的字节数组) */ public static byte[] encodeSHA(byte[] data) { return getShaDigest().digest(data); } /** * 使用SHA-1消息摘要算法计算消息摘要 * * @param data * 做消息摘要的数据 * @return SHA-1消息摘要(长度为40的十六进制字符串) */ public static String encodeSHAHex(byte[] data) { return Hex.encodeHexStr(getShaDigest().digest(data)); } /** * 使用SHA-256消息摘要算法计算消息摘要 * * @param data * 做消息摘要的数据 * @return SHA-256消息摘要(长度为32的字节数组) */ public static byte[] encodeSHA256(byte[] data) { return getSha256Digest().digest(data); } /** * 使用SHA-256消息摘要算法计算消息摘要 * * @param data * 做消息摘要的数据 * @return SHA-256消息摘要(长度为64的十六进制字符串) */ public static String encodeSHA256Hex(byte[] data) { return Hex.encodeHexStr(encodeSHA256(data)); } /** * 使用SHA-384消息摘要算法计算消息摘要 * * @param data * 做消息摘要的数据 * @return SHA-384消息摘要(长度为43的字节数组) */ public static byte[] encodeSHA384(byte[] data) { return getSha384Digest().digest(data); } /** * 使用SHA-384消息摘要算法计算消息摘要 * * @param data * 做消息摘要的数据 * @return SHA-384消息摘要(长度为86的十六进制字符串) */ public static String encodeSHA384Hex(byte[] data) { return Hex.encodeHexStr(encodeSHA384(data)); } /** * 使用SHA-512消息摘要算法计算消息摘要 * * @param data * 做消息摘要的数据 * @return SHA-512消息摘要(长度为64的字节数组) */ public static byte[] encodeSHA512(byte[] data) { return getSha512Digest().digest(data); } /** * 使用SHA-512消息摘要算法计算消息摘要 * * @param data * 做消息摘要的数据 * @return SHA-512消息摘要(长度为128的十六进制字符串) */ public static String encodeSHA512Hex(byte[] data) { return Hex.encodeHexStr(encodeSHA512(data)); } } |
参考 org.apache.commons.codec.digest.DigestUtils
下载地址: http://commons.apache.org/codec/download_codec.cgi
MAC系列的java实现
Hmac.java
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 |
import java.security.InvalidKeyException; import java.security.Key; import java.security.NoSuchAlgorithmException; import javax.crypto.KeyGenerator; import javax.crypto.Mac; import javax.crypto.SecretKey; import javax.crypto.spec.SecretKeySpec; /** * Hmac<br/> * algorithm HmacMD5/HmacSHA/HmacSHA256/HmacSHA384/HmacSHA512 * @author Aub */ public class Hmac { /** * 根据给定密钥生成算法创建密钥 * * @param algorithm * 密钥算法 * @return 密钥 * @throws RuntimeException * 当 {@link java.security.NoSuchAlgorithmException} 发生时 */ private static byte[] getHmacKey(String algorithm){ //初始化KeyGenerator KeyGenerator keyGenerator = null; try { keyGenerator = KeyGenerator.getInstance(algorithm); } catch (NoSuchAlgorithmException e) { throw new RuntimeException(e.getMessage()); } //产生密钥 SecretKey secretKey = keyGenerator.generateKey(); //获得密钥 return secretKey.getEncoded(); } /** * 获取 HmaMD5的密钥 * * @return HmaMD5的密钥 * @throws RuntimeException * 当 {@link java.security.NoSuchAlgorithmException} 发生时 */ public static byte[] getHmaMD5key(){ return getHmacKey("HmacMD5"); } /** * 获取 HmaSHA的密钥 * * @return HmaSHA的密钥 * @throws RuntimeException * 当 {@link java.security.NoSuchAlgorithmException} 发生时 */ public static byte[] getHmaSHAkey(){ return getHmacKey("HmacSHA1"); } /** * 获取 HmaSHA256的密钥 * * @return HmaSHA256的密钥 * @throws RuntimeException * 当 {@link java.security.NoSuchAlgorithmException} 发生时 */ public static byte[] getHmaSHA256key(){ return getHmacKey("HmacSHA256"); } /** * 获取 HmaSHA384的密钥 * * @return HmaSHA384的密钥 * @throws RuntimeException * 当 {@link java.security.NoSuchAlgorithmException} 发生时 */ public static byte[] getHmaSHA384key(){ return getHmacKey("HmacSHA384"); } /** * 获取 HmaSHA512的密钥 * * @return HmaSHA384的密钥 * @throws RuntimeException * 当 {@link java.security.NoSuchAlgorithmException} 发生时 */ public static byte[] getHmaSHA512key(){ return getHmacKey("HmacSHA512"); } /** * 转换密钥 * * @param key 二进制密钥 * @param algorithm 密钥算法 * @return 密钥 */ private static Key toKey(byte[] key,String algorithm){ //生成密钥 return new SecretKeySpec(key, algorithm); } /** * 使用HmacMD5消息摘要算法计算消息摘要 * * @param data 做消息摘要的数据 * @param key 密钥 * @return 消息摘要(长度为16的字节数组) */ public static byte[] encodeHmacMD5(byte[] data, Key key){ Mac mac = null; try { mac = Mac.getInstance("HmacMD5"); mac.init(key); } catch (NoSuchAlgorithmException e) { e.printStackTrace(); return new byte[0]; }catch (InvalidKeyException e) { e.printStackTrace(); return new byte[0]; } return mac.doFinal(data); } /** * 使用HmacMD5消息摘要算法计算消息摘要 * * @param data 做消息摘要的数据 * @param key 密钥 * @return 消息摘要(长度为16的字节数组) */ public static byte[] encodeHmacMD5(byte[] data, byte[] key){ Key k = toKey(key, "HmacMD5"); return encodeHmacMD5(data, k); } /** * 使用HmacSHA消息摘要算法计算消息摘要 * * @param data 做消息摘要的数据 * @param key 密钥 * @return 消息摘要(长度为16的字节数组) */ public static byte[] encodeHmacSHA(byte[] data, Key key){ Mac mac = null; try { mac = Mac.getInstance("HmacSHA1"); mac.init(key); } catch (NoSuchAlgorithmException e) { e.printStackTrace(); return new byte[0]; }catch (InvalidKeyException e) { e.printStackTrace(); return new byte[0]; } return mac.doFinal(data); } /** * 使用HmacSHA消息摘要算法计算消息摘要 * * @param data 做消息摘要的数据 * @param key 密钥 * @return 消息摘要(长度为16的字节数组) */ public static byte[] encodeHmacSHA(byte[] data, byte[] key){ Key k = toKey(key, "HmacSHA1"); return encodeHmacSHA(data, k); } /** * 使用HmacSHA256消息摘要算法计算消息摘要 * * @param data 做消息摘要的数据 * @param key 密钥 * @return 消息摘要(长度为16的字节数组) */ public static byte[] encodeHmacSHA256(byte[] data, Key key){ Mac mac = null; try { mac = Mac.getInstance("HmacSHA256"); mac.init(key); } catch (NoSuchAlgorithmException e) { e.printStackTrace(); return new byte[0]; }catch (InvalidKeyException e) { e.printStackTrace(); return new byte[0]; } return mac.doFinal(data); } /** * 使用HmacSHA256消息摘要算法计算消息摘要 * * @param data 做消息摘要的数据 * @param key 密钥 * @return 消息摘要(长度为16的字节数组) */ public static byte[] encodeHmacSHA256(byte[] data, byte[] key){ Key k = toKey(key, "HmacSHA256"); return encodeHmacSHA256(data, k); } /** * 使用HmacSHA384消息摘要算法计算消息摘要 * * @param data 做消息摘要的数据 * @param key 密钥 * @return 消息摘要(长度为16的字节数组) */ public static byte[] encodeHmacSHA384(byte[] data, Key key){ Mac mac = null; try { mac = Mac.getInstance("HmacSHA384"); mac.init(key); } catch (NoSuchAlgorithmException e) { e.printStackTrace(); return new byte[0]; }catch (InvalidKeyException e) { e.printStackTrace(); return new byte[0]; } return mac.doFinal(data); } /** * 使用HmacSHA384消息摘要算法计算消息摘要 * * @param data 做消息摘要的数据 * @param key 密钥 * @return 消息摘要(长度为16的字节数组) */ public static byte[] encodeHmacSHA384(byte[] data, byte[] key){ Key k = toKey(key, "HmacSHA384"); return encodeHmacSHA384(data, k); } /** * 使用HmacSHA512消息摘要算法计算消息摘要 * * @param data 做消息摘要的数据 * @param key 密钥 * @return 消息摘要(长度为16的字节数组) */ public static byte[] encodeHmacSHA512(byte[] data, Key key){ Mac mac = null; try { mac = Mac.getInstance("HmacSHA512"); mac.init(key); } catch (NoSuchAlgorithmException e) { e.printStackTrace(); return new byte[0]; }catch (InvalidKeyException e) { e.printStackTrace(); return new byte[0]; } return mac.doFinal(data); } /** * 使用HmacSHA512消息摘要算法计算消息摘要 * * @param data 做消息摘要的数据 * @param key 密钥 * @return 消息摘要(长度为16的字节数组) */ public static byte[] encodeHmacSHA512(byte[] data, byte[] key){ Key k = toKey(key, "HmacSHA512"); return encodeHmacSHA512(data, k); } private static String showByteArray(byte[] data){ if(null == data){ return null; } StringBuilder sb = new StringBuilder("{"); for(byte b:data){ sb.append(b).append(","); } sb.deleteCharAt(sb.length()-1); sb.append("}"); return sb.toString(); } public static void main(String[] args) { // byte[] key = getHmaMD5key(); // byte[] key = getHmaSHAkey(); // byte[] key = getHmaSHA256key(); // byte[] key = getHmaSHA384key(); byte[] key = getHmaSHA512key(); System.out.println("加密密钥: byte[]:"+showByteArray(key).length()); String data = "Mac数据"; System.out.println("加密前数据: string:"+data); System.out.println("加密前数据: byte[]:"+showByteArray(data.getBytes())); System.out.println(); // byte[] encodeData = encodeHmacMD5(data.getBytes(), key); // byte[] encodeData = encodeHmacSHA(data.getBytes(), key); // byte[] encodeData = encodeHmacSHA256(data.getBytes(), key); // byte[] encodeData = encodeHmacSHA384(data.getBytes(), key); byte[] encodeData = encodeHmacSHA512(data.getBytes(), key); System.out.println("加密后数据: byte[]:"+showByteArray(encodeData).length()); System.out.println("加密后数据: byte[]:"+encodeData.length); System.out.println("加密后数据: hexStr:"+Hex.encodeHexStr(encodeData)); System.out.println(); } } |