자바 의 hash + salt 암호 화 알고리즘
9388 단어 자바
비교적 안전 한 방법 은 hash + salt 의 암호 화 알고리즘 을 사용 하 는 것 이다.
여기 에는 RFC 2898 기준 이 적용 됐다.
코드 보기:
Rfc2898DeriveBytes.java
package com.poreader.common;
import java.io.UnsupportedEncodingException;
import java.security.InvalidKeyException;
import java.security.NoSuchAlgorithmException;
import java.util.Random;
import javax.crypto.Mac;
import javax.crypto.spec.SecretKeySpec;
import org.apache.commons.codec.binary.Base64;
/**
* This implementation follows RFC 2898 recommendations. See
* http://www.ietf.org/rfc/Rfc2898.txt
*/
public class Rfc2898DeriveBytes {
private static final int BLOCK_SIZE = 20;
private static Random random = new Random();
private Mac hmacsha1;
private byte[] salt;
private int iterations;
private byte[] buffer = new byte[BLOCK_SIZE];
private int startIndex = 0;
private int endIndex = 0;
private int block = 1;
/**
* Creates new instance.
*
* @param password
* The password used to derive the key.
* @param salt
* The key salt used to derive the key.
* @param iterations
* The number of iterations for the operation.
* @throws NoSuchAlgorithmException
* HmacSHA1 algorithm cannot be found.
* @throws InvalidKeyException
* Salt must be 8 bytes or more. -or- Password cannot be null.
*/
public Rfc2898DeriveBytes(byte[] password, byte[] salt, int iterations) throws NoSuchAlgorithmException,
InvalidKeyException {
this.salt = salt;
this.iterations = iterations;
this.hmacsha1 = Mac.getInstance("HmacSHA1");
this.hmacsha1.init(new SecretKeySpec(password, "HmacSHA1"));
}
/**
* Creates new instance.
*
* @param password
* The password used to derive the key.
* @param salt
* The key salt used to derive the key.
* @param iterations
* The number of iterations for the operation.
* @throws NoSuchAlgorithmException
* HmacSHA1 algorithm cannot be found.
* @throws InvalidKeyException
* Salt must be 8 bytes or more. -or- Password cannot be null.
* @throws UnsupportedEncodingException
*/
public Rfc2898DeriveBytes(String password, int saltSize, int iterations) throws NoSuchAlgorithmException,
InvalidKeyException, UnsupportedEncodingException {
this.salt = randomSalt(saltSize);
this.iterations = iterations;
this.hmacsha1 = Mac.getInstance("HmacSHA1");
this.hmacsha1.init(new SecretKeySpec(password.getBytes("UTF-8"), "HmacSHA1"));
this.buffer = new byte[BLOCK_SIZE];
this.block = 1;
this.startIndex = this.endIndex = 1;
}
/**
* Creates new instance.
*
* @param password
* The password used to derive the key.
* @param salt
* The key salt used to derive the key.
* @param iterations
* The number of iterations for the operation.
* @throws NoSuchAlgorithmException
* HmacSHA1 algorithm cannot be found.
* @throws InvalidKeyException
* Salt must be 8 bytes or more. -or- Password cannot be null.
* @throws UnsupportedEncodingException
*/
public Rfc2898DeriveBytes(String password, int saltSize) throws NoSuchAlgorithmException, InvalidKeyException,
UnsupportedEncodingException {
this(password, saltSize, 1000);
}
/**
* Creates new instance.
*
* @param password
* The password used to derive the key.
* @param salt
* The key salt used to derive the key.
* @param iterations
* The number of iterations for the operation.
* @throws NoSuchAlgorithmException
* HmacSHA1 algorithm cannot be found.
* @throws InvalidKeyException
* Salt must be 8 bytes or more. -or- Password cannot be null.
* @throws UnsupportedEncodingException
* UTF-8 encoding is not supported.
*/
public Rfc2898DeriveBytes(String password, byte[] salt, int iterations) throws InvalidKeyException,
NoSuchAlgorithmException, UnsupportedEncodingException {
this(password.getBytes("UTF8"), salt, iterations);
}
public byte[] getSalt() {
return this.salt;
}
public String getSaltAsString() {
return Base64.encodeBase64String(this.salt);
}
/**
* Returns a pseudo-random key from a data, salt and iteration count.
*
* @param cb
* Number of bytes to return.
* @return Byte array.
*/
public byte[] getBytes(int cb) {
byte[] result = new byte[cb];
int offset = 0;
int size = this.endIndex - this.startIndex;
if (size > 0) { // if there is some data in buffer
if (cb >= size) { // if there is enough data in buffer
System.arraycopy(this.buffer, this.startIndex, result, 0, size);
this.startIndex = this.endIndex = 0;
offset += size;
} else {
System.arraycopy(this.buffer, this.startIndex, result, 0, cb);
startIndex += cb;
return result;
}
}
while (offset < cb) {
byte[] block = this.func();
int remainder = cb - offset;
if (remainder > BLOCK_SIZE) {
System.arraycopy(block, 0, result, offset, BLOCK_SIZE);
offset += BLOCK_SIZE;
} else {
System.arraycopy(block, 0, result, offset, remainder);
offset += remainder;
System.arraycopy(block, remainder, this.buffer, startIndex, BLOCK_SIZE - remainder);
endIndex += (BLOCK_SIZE - remainder);
return result;
}
}
return result;
}
public static byte[] randomSalt(int size) {
byte[] salt = new byte[size];
random.nextBytes(salt);
return salt;
}
/**
* Generate random Salt
*
* @param size
* @return
*/
public static String generateSalt(int size) {
byte[] salt = randomSalt(size);
return Base64.encodeBase64String(salt);
}
private byte[] func() {
this.hmacsha1.update(this.salt, 0, this.salt.length);
byte[] tempHash = this.hmacsha1.doFinal(getBytesFromInt(this.block));
this.hmacsha1.reset();
byte[] finalHash = tempHash;
for (int i = 2; i <= this.iterations; i++) {
tempHash = this.hmacsha1.doFinal(tempHash);
for (int j = 0; j < 20; j++) {
finalHash[j] = (byte) (finalHash[j] ^ tempHash[j]);
}
}
if (this.block == 2147483647) {
this.block = -2147483648;
} else {
this.block += 1;
}
return finalHash;
}
private static byte[] getBytesFromInt(int i) {
return new byte[] { (byte) (i >>> 24), (byte) (i >>> 16), (byte) (i >>> 8), (byte) i };
}
}
CryptoUtils.java
package com.poreader.common;
import org.apache.commons.codec.binary.Base64;
public class CryptoUtils {
private static int saltSize = 32;
private static int iterations = 1000;
private static int subKeySize = 32;
/**
* Salt
* @return
*/
public static String getSalt() {
return Rfc2898DeriveBytes.generateSalt(saltSize);
}
/**
* hash
* @param password
* @param salt
* @return
*/
public static String getHash(String password, String salt) {
Rfc2898DeriveBytes keyGenerator = null;
try {
keyGenerator = new Rfc2898DeriveBytes(password + salt, saltSize, iterations);
} catch (Exception e1) {
e1.printStackTrace();
}
byte[] subKey = keyGenerator.getBytes(subKeySize);
byte[] bSalt = keyGenerator.getSalt();
byte[] hashPassword = new byte[1 + saltSize + subKeySize];
System.arraycopy(bSalt, 0, hashPassword, 1, saltSize);
System.arraycopy(subKey, 0, hashPassword, saltSize + 1, subKeySize);
return Base64.encodeBase64String(hashPassword);
}
/**
*
* @param hashedPassword
* @param password
* @param salt
* @return
*/
public static boolean verify(String hashedPassword, String password, String salt) {
byte[] hashedPasswordBytes = Base64.decodeBase64(hashedPassword);
if (hashedPasswordBytes.length != (1 + saltSize + subKeySize) || hashedPasswordBytes[0] != 0x00) {
return false;
}
byte[] bSalt = new byte[saltSize];
System.arraycopy(hashedPasswordBytes, 1, bSalt, 0, saltSize);
byte[] storedSubkey = new byte[subKeySize];
System.arraycopy(hashedPasswordBytes, 1 + saltSize, storedSubkey, 0, subKeySize);
Rfc2898DeriveBytes deriveBytes = null;
try {
deriveBytes = new Rfc2898DeriveBytes(password + salt, bSalt, iterations);
} catch (Exception e) {
e.printStackTrace();
}
byte[] generatedSubkey = deriveBytes.getBytes(subKeySize);
return byteArraysEqual(storedSubkey, generatedSubkey);
}
private static boolean byteArraysEqual(byte[] storedSubkey, byte[] generatedSubkey) {
int size = storedSubkey.length;
if (size != generatedSubkey.length) {
return false;
}
for (int i = 0; i < size; i++) {
if (storedSubkey[i] != generatedSubkey[i]) {
return false;
}
}
return true;
}
}
인증:
public static void main(String[] args) throws NoSuchAlgorithmException {
String salt = CryptoUtils.getSalt();
String password = "admin123";
String hashPassword = CryptoUtils.getHash(password, salt);
System.out.println("hashPassword:" + hashPassword);
System.out.println("salt:" + salt);
System.out.println("password:" + password);
// verify
boolean result = CryptoUtils.verify(hashPassword, password, salt);
System.out.println("Verify:" + result);
}
이 내용에 흥미가 있습니까?
현재 기사가 여러분의 문제를 해결하지 못하는 경우 AI 엔진은 머신러닝 분석(스마트 모델이 방금 만들어져 부정확한 경우가 있을 수 있음)을 통해 가장 유사한 기사를 추천합니다:
Is Eclipse IDE dying?In 2014 the Eclipse IDE is the leading development environment for Java with a market share of approximately 65%. but ac...
텍스트를 자유롭게 공유하거나 복사할 수 있습니다.하지만 이 문서의 URL은 참조 URL로 남겨 두십시오.
CC BY-SA 2.5, CC BY-SA 3.0 및 CC BY-SA 4.0에 따라 라이센스가 부여됩니다.