Unverified 提交 933f97cc authored 作者: Noel Grandin's avatar Noel Grandin 提交者: GitHub

Merge pull request #808 from katzyn/security

Use HmacSHA256 provided by JRE
...@@ -5,11 +5,14 @@ ...@@ -5,11 +5,14 @@
*/ */
package org.h2.security; package org.h2.security;
import java.security.DigestException; import java.security.GeneralSecurityException;
import java.security.MessageDigest; import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException; import java.security.NoSuchAlgorithmException;
import java.util.Arrays; import java.util.Arrays;
import javax.crypto.Mac;
import javax.crypto.spec.SecretKeySpec;
import org.h2.util.Bits; import org.h2.util.Bits;
/** /**
...@@ -17,16 +20,7 @@ import org.h2.util.Bits; ...@@ -17,16 +20,7 @@ import org.h2.util.Bits;
*/ */
public class SHA256 { public class SHA256 {
private final MessageDigest md;
private final byte[] result = new byte[32];
private SHA256() { private SHA256() {
try {
md = MessageDigest.getInstance("SHA-256");
} catch (NoSuchAlgorithmException e) {
throw new RuntimeException(e);
}
} }
/** /**
...@@ -84,40 +78,20 @@ public class SHA256 { ...@@ -84,40 +78,20 @@ public class SHA256 {
* @return the hash * @return the hash
*/ */
public static byte[] getHMAC(byte[] key, byte[] message) { public static byte[] getHMAC(byte[] key, byte[] message) {
key = normalizeKeyForHMAC(key); return initMac(key).doFinal(message);
int len = message.length;
SHA256 sha = new SHA256();
byte[] iKey = new byte[64 + len];
byte[] oKey = new byte[64 + 32];
sha.calculateHMAC(key, message, len, iKey, oKey);
return sha.result;
}
private void calculateHMAC(byte[] key, byte[] message, int len,
byte[] iKey, byte[] oKey) {
Arrays.fill(iKey, 0, 64, (byte) 0x36);
xor(iKey, key, 64);
System.arraycopy(message, 0, iKey, 64, len);
calculateHash(iKey, 64 + len);
Arrays.fill(oKey, 0, 64, (byte) 0x5c);
xor(oKey, key, 64);
System.arraycopy(result, 0, oKey, 64, 32);
calculateHash(oKey, 64 + 32);
} }
private static byte[] normalizeKeyForHMAC(byte[] key) { private static Mac initMac(byte[] key) {
if (key.length > 64) { // Java forbids empty keys
key = getHash(key, false); if (key.length == 0) {
key = new byte[1];
} }
if (key.length < 64) { try {
key = Arrays.copyOf(key, 64); Mac mac = Mac.getInstance("HmacSHA256");
} mac.init(new SecretKeySpec(key, "HmacSHA256"));
return key; return mac;
} } catch (GeneralSecurityException e) {
throw new RuntimeException(e);
private static void xor(byte[] target, byte[] data, int len) {
for (int i = 0; i < len; i++) {
target[i] ^= data[i];
} }
} }
...@@ -133,12 +107,10 @@ public class SHA256 { ...@@ -133,12 +107,10 @@ public class SHA256 {
public static byte[] getPBKDF2(byte[] password, byte[] salt, public static byte[] getPBKDF2(byte[] password, byte[] salt,
int iterations, int resultLen) { int iterations, int resultLen) {
byte[] result = new byte[resultLen]; byte[] result = new byte[resultLen];
byte[] key = normalizeKeyForHMAC(password); Mac mac = initMac(password);
SHA256 sha = new SHA256();
int len = 64 + Math.max(32, salt.length + 4); int len = 64 + Math.max(32, salt.length + 4);
byte[] message = new byte[len]; byte[] message = new byte[len];
byte[] iKey = new byte[64 + len]; byte[] macRes = null;
byte[] oKey = new byte[64 + 32];
for (int k = 1, offset = 0; offset < resultLen; k++, offset += 32) { for (int k = 1, offset = 0; offset < resultLen; k++, offset += 32) {
for (int i = 0; i < iterations; i++) { for (int i = 0; i < iterations; i++) {
if (i == 0) { if (i == 0) {
...@@ -146,17 +118,17 @@ public class SHA256 { ...@@ -146,17 +118,17 @@ public class SHA256 {
Bits.writeInt(message, salt.length, k); Bits.writeInt(message, salt.length, k);
len = salt.length + 4; len = salt.length + 4;
} else { } else {
System.arraycopy(sha.result, 0, message, 0, 32); System.arraycopy(macRes, 0, message, 0, 32);
len = 32; len = 32;
} }
sha.calculateHMAC(key, message, len, iKey, oKey); mac.update(message, 0, len);
macRes = mac.doFinal();
for (int j = 0; j < 32 && j + offset < resultLen; j++) { for (int j = 0; j < 32 && j + offset < resultLen; j++) {
result[j + offset] ^= sha.result[j]; result[j + offset] ^= macRes[j];
} }
} }
} }
Arrays.fill(password, (byte) 0); Arrays.fill(password, (byte) 0);
Arrays.fill(key, (byte) 0);
return result; return result;
} }
...@@ -169,22 +141,16 @@ public class SHA256 { ...@@ -169,22 +141,16 @@ public class SHA256 {
* @return the hash code * @return the hash code
*/ */
public static byte[] getHash(byte[] data, boolean nullData) { public static byte[] getHash(byte[] data, boolean nullData) {
int len = data.length; byte[] result;
SHA256 sha = new SHA256();
sha.calculateHash(data, len);
if (nullData) {
Arrays.fill(data, (byte) 0);
}
return sha.result;
}
private void calculateHash(byte[] data, int len) {
try { try {
md.update(data, 0, len); result = MessageDigest.getInstance("SHA-256").digest(data);
md.digest(result, 0, 32); } catch (NoSuchAlgorithmException e) {
} catch (DigestException e) {
throw new RuntimeException(e); throw new RuntimeException(e);
} }
if (nullData) {
Arrays.fill(data, (byte) 0);
}
return result;
} }
} }
Markdown 格式
0%
您添加了 0 到此讨论。请谨慎行事。
请先完成此评论的编辑!
注册 或者 后发表评论