管理系统登录中使用飞天诚信的usbkey,服务器端做验证用到hmac-md5,java里有现成的实现,但一直没找着怎么指定key,只好照着rfc实现了一个.
package com.pay365.util;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
/**
* <pre>
* Definition of HMAC
*
* The definition of HMAC requires a cryptographic hash function, which
* we denote by H, and a secret key K. We assume H to be a cryptographic
* hash function where data is hashed by iterating a basic compression
* function on blocks of data. We denote by B the byte-length of such
* blocks (B=64 for all the above mentioned examples of hash functions),
* and by L the byte-length of hash outputs (L=16 for MD5, L=20 for
* SHA-1). The authentication key K can be of any length up to B, the
* block length of the hash function. Applications that use keys longer
* than B bytes will first hash the key using H and then use the
* resultant L byte string as the actual key to HMAC. In any case the
* minimal recommended length for K is L bytes (as the hash output
* length). See section 3 for more information on keys.
*
* We define two fixed and different strings ipad and opad as follows
* (the ‘i’ and ‘o’ are mnemonics for inner and outer):
*
* ipad = the byte 0×36 repeated B times
* opad = the byte 0×5C repeated B times.
*
* To compute HMAC over the data `text’ we perform
*
* H(K XOR opad, H(K XOR ipad, text))
*
* Namely,
*
* (1) append zeros to the end of K to create a B byte string
* (e.g., if K is of length 20 bytes and B=64, then K will be
* appended with 44 zero bytes 0×00)
* (2) XOR (bitwise exclusive-OR) the B byte string computed in step
* (1) with ipad
* (3) append the stream of data ‘text’ to the B byte string resulting
* from step (2)
* (4) apply H to the stream generated in step (3)
* (5) XOR (bitwise exclusive-OR) the B byte string computed in
* step (1) with opad
* (6) append the H result from step (4) to the B byte string
* resulting from step (5)
* (7) apply H to the stream generated in step (6) and output
* the result
* </pre>
*
* @author <a xhref="mailto:zzzhc.starfire@gmail.com">zzzhc</a>
*/
public class HmacMd5 {
/**
* Used building output as Hex
*/
private static final char[] DIGITS = { ‘0′, ‘1′, ‘2′, ‘3′, ‘4′, ‘5′, ‘6′,
‘7′, ‘8′, ‘9′, ‘A’, ‘B’, ‘C’, ‘D’, ‘E’, ‘F’ };
private byte[] ipod;
private byte[] opod;
public HmacMd5() {
this(64);
}
public HmacMd5(int b) {
ipod = new byte[b];
opod = new byte[b];
for (int i = 0; i < 64; i++) {
ipod[i] = 0×36;
opod[i] = 0×5c;
}
}
private char[] encodeHex(byte[] data) {
int l = data.length;
char[] out = new char[l << 1];
// two characters form the hex value.
for (int i = 0, j = 0; i < l; i++) {
out[j++] = DIGITS[(0xF0 & data[i]) >>> 4];
out[j++] = DIGITS[0x0F & data[i] ];
}
return out;
}
private MessageDigest getMD5Digest() {
try {
MessageDigest md5MessageDigest = MessageDigest.getInstance("MD5");
md5MessageDigest.reset();
return md5MessageDigest;
} catch (NoSuchAlgorithmException nsaex) {
throw new RuntimeException(
"Could not access MD5 algorithm, fatal error");
}
}
public byte[] md5(byte[] content) {
byte[] data = getMD5Digest().digest(content);
return data;
}
public String hmac(String key, String text) {
byte[] keyData = key.getBytes();
byte[] ki = new byte[64];
byte[] ko = new byte[64];
int keyLen = keyData.length;
for (int i = 0; i < 64; i++) {
if (i < keyLen) {
ki[i] = (byte) (keyData[i] ^ ipod[i]);
ko[i] = (byte) (keyData[i] ^ opod[i]);
} else {
ki[i] = ipod[i];
ko[i] = opod[i];
}
}
byte[] textData = text.getBytes();
byte[] h1Data = new byte[64 + textData.length];
System.arraycopy(ki, 0, h1Data, 0, 64);
System.arraycopy(textData, 0, h1Data, 64, textData.length);
byte[] h1Result = md5(h1Data);
byte[] h2Data = new byte[64 + h1Result.length];
System.arraycopy(ko, 0, h2Data, 0, 64);
System.arraycopy(h1Result, 0, h2Data, 64, h1Result.length);
byte[] result = md5(h2Data);
return new String(encodeHex(result));
}
public static void main(String[] args) {
HmacMd5 hm = new HmacMd5();
String result = hm.hmac("2howek8523jsi", "ort.com.cn");
System.out.println(result);
}
}
参考:
RFC 2104 – HMAC: Keyed-Hashing for Message Authentication
technorati tags: hmac, md5, hmac-md5, sourcecode, java