Java AES512加密演算法
阿新 • • 發佈:2019-02-17
AES - 高階加密標準:
高階加密標準(英語:Advanced Encryption Standard,縮寫:AES),在密碼學中又稱Rijndael加密法,是美國聯邦政府採用的一種區塊加密標準。這個標準用來替代原先的DES,已經被多方分析且廣為全世界所使用。經過五年的甄選流程,高階加密標準由美國國家標準與技術研究院(NIST)於2001年11月26日釋出於FIPS PUB 197,並在2002年5月26日成為有效的標準。2006年,高階加密標準已然成為對稱金鑰加密中最流行的演算法之一
AES 演算法在工作中使用很頻繁, 藉著這次專案中使用做一下總結, 本次主要是正對 AES512 來講解。
開發前準備工作:
由於Java 執行環境中的 policy檔案是受限的,對AES512不支援。解決方案如下:
1:policy檔案位於${java_home}/jre/lib/security目錄下
2: 去除該限制需下載JavaCryptography
Extension (JCE) Unlimited Strength JurisdictionPolicy Files,
覆蓋上述目錄下的對應jar檔案(local_policy.jar,US_export_policy.jar)
3: jar 官方下載路徑
做完這三步 下面直接上程式碼:AES512 加密方法
package org.message.encrypt.cipher; import java.io.UnsupportedEncodingException; import java.security.InvalidAlgorithmParameterException; import java.security.InvalidKeyException; import java.security.NoSuchAlgorithmException; import javax.crypto.BadPaddingException; import javax.crypto.Cipher; import javax.crypto.IllegalBlockSizeException; import javax.crypto.NoSuchPaddingException; import javax.crypto.spec.IvParameterSpec; import javax.crypto.spec.SecretKeySpec; import org.message.encrypt.tool.Encode; import org.message.encrypt.tool.Numeric; import com.google.common.io.BaseEncoding; public class AESCipher { private static final String ALGORITHM_AES256 = "AES/CBC/PKCS5Padding";// "AES/CBC/PKCS7Padding"; private final SecretKeySpec secretKeySpec; private static final String CHARSET = "UTF-8"; private static final String DEFAULT_IV = "iv is default value"; private Cipher cipher; private IvParameterSpec iv; public AESCipher(String key) { this(key, DEFAULT_IV); } public AESCipher(String key, String iv) { this(Numeric.hexStringToByteArray(key), Numeric.hexStringToByteArray(iv)); } private AESCipher(byte[] key, byte[] iv) { // Security.addProvider(new BouncyCastleProvider()); if (null == key || key.length != 32) { throw new RuntimeException("input params key must be 32bit bytes array"); } if (null == iv || iv.length != 16) { throw new RuntimeException("input params iv must be 16bit bytes array"); } this.secretKeySpec = new SecretKeySpec(key, "AES"); this.iv = new IvParameterSpec(iv); try { this.cipher = Cipher.getInstance(ALGORITHM_AES256); } catch (NoSuchAlgorithmException | NoSuchPaddingException e) { throw new RuntimeException("instantiation objects Cipher exception"); } } /** * AES Encrypt algorithm * * @param encryptSource * not null string * @return after AES encrypt result , the type of the string */ public String getEncryptedMessage(final String encryptSource) { Cipher cipher = getCipher(Cipher.ENCRYPT_MODE); byte[] encryptedTextBytes = null; try { encryptedTextBytes = cipher.doFinal(encryptSource.getBytes(CHARSET)); } catch (IllegalBlockSizeException | BadPaddingException | UnsupportedEncodingException e) { throw new RuntimeException("AES encrypt exception"); } return Encode.baseEncode(encryptedTextBytes); } /** * AES decrypt algorithm * * @param decryptSource * AES encrypted cipher, type of String * @return decrypted plaintext, type of string */ public String getDecryptMessage(String decryptSource) { Cipher cipher = getCipher(Cipher.DECRYPT_MODE); byte[] encryptedTextBytes = null; String decryptResult = null; try { encryptedTextBytes = cipher.doFinal(BaseEncoding.base64().decode(decryptSource)); } catch (IllegalBlockSizeException | BadPaddingException e) { throw new RuntimeException("AES decrypt exception"); } try { decryptResult = new String(encryptedTextBytes, CHARSET); } catch (UnsupportedEncodingException e) { throw new RuntimeException("bytes array convert into string exception"); } return decryptResult; } private Cipher getCipher(int encryptMode) { try { cipher.init(encryptMode, secretKeySpec, iv); } catch (InvalidKeyException | InvalidAlgorithmParameterException e) { throw new RuntimeException("init objects Cipher exception"); } return cipher; } }
Encode 工具類
package org.message.encrypt.tool; import com.google.common.io.BaseEncoding; public class Encode { /** * byte[] convert into string ,use base encode default value BASE64 * * @param encodeMassage * not null byte[] * @return after encode result */ public static String baseEncode(final byte[] encodeMassage) { return baseEncode(encodeMassage, BaseType.BASE64); } /** * byte[] convert into string ,use base encode default value BASE64 * * @param encodeMassage * not null byte[] * @param encoder * of type please see enum type of inner class , the class name * 'BaseType' * @return after encode result , the type of string */ public static String baseEncode(final byte[] encodeMassage, final BaseType encoder) { String baseResult = null; switch (encoder) { case BASE64: baseResult = BaseEncoding.base64().encode(encodeMassage); break; case BASE32: baseResult = BaseEncoding.base32().encode(encodeMassage); break; case BASE32HEX: baseResult = BaseEncoding.base32Hex().encode(encodeMassage); break; case BASE16: baseResult = BaseEncoding.base16().encode(encodeMassage); break; default: break; } return baseResult; } /** * string convert into byte[], use base decode * * @param decodeMassage * not null string * @return after decode result , the type of byte[] */ public static byte[] baseDecode(final String decodeMassage) { return baseDecode(decodeMassage, BaseType.BASE64); } public static byte[] baseDecode(final String decodeMassage, final BaseType encoder) { byte[] baseResult = null; switch (encoder) { case BASE64: baseResult = BaseEncoding.base64().decode(decodeMassage); break; case BASE32: baseResult = BaseEncoding.base32().decode(decodeMassage); break; case BASE32HEX: baseResult = BaseEncoding.base32Hex().decode(decodeMassage); break; case BASE16: baseResult = BaseEncoding.base16().decode(decodeMassage); break; default: break; } return baseResult; } enum BaseType { BASE64, BASE32, BASE32HEX, BASE16; } }
Numeric 工具類
package org.message.encrypt.tool;
import java.math.BigDecimal;
import java.math.BigInteger;
import java.util.Arrays;
/**
* <p>Message codec functions.</p>
*
* <p>Implementation as per https://github.com/ethereum/wiki/wiki/JSON-RPC#hex-value-encoding</p>
*/
public final class Numeric {
private static final String HEX_PREFIX = "0x";
private Numeric() {
}
public static String encodeQuantity(BigInteger value) {
if (value.signum() != -1) {
return HEX_PREFIX + value.toString(16);
} else {
throw new RuntimeException("Negative values are not supported");
}
}
public static BigInteger decodeQuantity(String value) {
if (!isValidHexQuantity(value)) {
throw new RuntimeException("Value must be in format 0x[1-9]+[0-9]* or 0x0");
}
try {
return new BigInteger(value.substring(2), 16);
} catch (NumberFormatException e) {
throw new RuntimeException("Negative ", e);
}
}
private static boolean isValidHexQuantity(String value) {
if (value == null) {
return false;
}
if (value.length() < 3) {
return false;
}
if (!value.startsWith(HEX_PREFIX)) {
return false;
}
// If TestRpc resolves the following issue, we can reinstate this code
// https://github.com/ethereumjs/testrpc/issues/220
// if (value.length() > 3 && value.charAt(2) == '0') {
// return false;
// }
return true;
}
public static String cleanHexPrefix(String input) {
if (containsHexPrefix(input)) {
return input.substring(2);
} else {
return input;
}
}
public static String prependHexPrefix(String input) {
if (!containsHexPrefix(input)) {
return HEX_PREFIX + input;
} else {
return input;
}
}
public static boolean containsHexPrefix(String input) {
return input.length() > 1 && input.charAt(0) == '0' && input.charAt(1) == 'x';
}
public static BigInteger toBigInt(byte[] value, int offset, int length) {
return toBigInt((Arrays.copyOfRange(value, offset, offset + length)));
}
public static BigInteger toBigInt(byte[] value) {
return new BigInteger(1, value);
}
public static BigInteger toBigInt(String hexValue) {
String cleanValue = cleanHexPrefix(hexValue);
return new BigInteger(cleanValue, 16);
}
public static String toHexStringWithPrefix(BigInteger value) {
return HEX_PREFIX + value.toString(16);
}
public static String toHexStringNoPrefix(BigInteger value) {
return value.toString(16);
}
public static String toHexStringWithPrefixZeroPadded(BigInteger value, int size) {
return toHexStringZeroPadded(value, size, true);
}
public static String toHexStringNoPrefixZeroPadded(BigInteger value, int size) {
return toHexStringZeroPadded(value, size, false);
}
private static String toHexStringZeroPadded(BigInteger value, int size, boolean withPrefix) {
String result = toHexStringNoPrefix(value);
int length = result.length();
if (length > size) {
throw new UnsupportedOperationException(
"Value " + result + "is larger then length " + size);
} else if (value.signum() < 0) {
throw new UnsupportedOperationException("Value cannot be negative");
}
if (length < size) {
result = Strings.zeros(size - length) + result;
}
if (withPrefix) {
return HEX_PREFIX + result;
} else {
return result;
}
}
public static byte[] toBytesPadded(BigInteger value, int length) {
byte[] result = new byte[length];
byte[] bytes = value.toByteArray();
int bytesLength;
int srcOffset;
if (bytes[0] == 0) {
bytesLength = bytes.length - 1;
srcOffset = 1;
} else {
bytesLength = bytes.length;
srcOffset = 0;
}
if (bytesLength > length) {
throw new RuntimeException("Input is too large to put in byte array of size " + length);
}
int destOffset = length - bytesLength;
System.arraycopy(bytes, srcOffset, result, destOffset, bytesLength);
return result;
}
public static byte[] hexStringToByteArray(String input) {
String cleanInput = cleanHexPrefix(input);
int len = cleanInput.length();
if (len == 0) {
return new byte[] {};
}
byte[] data;
int startIdx;
if (len % 2 != 0) {
data = new byte[(len / 2) + 1];
data[0] = (byte) Character.digit(cleanInput.charAt(0), 16);
startIdx = 1;
} else {
data = new byte[len / 2];
startIdx = 0;
}
for (int i = startIdx; i < len; i += 2) {
data[(i + 1) / 2] = (byte) ((Character.digit(cleanInput.charAt(i), 16) << 4)
+ Character.digit(cleanInput.charAt(i+1), 16));
}
return data;
}
public static String toHexString(byte[] input, int offset, int length, boolean withPrefix) {
StringBuilder stringBuilder = new StringBuilder();
if (withPrefix) {
stringBuilder.append("0x");
}
for (int i = offset; i < offset + length; i++) {
stringBuilder.append(String.format("%02x", input[i] & 0xFF));
}
return stringBuilder.toString();
}
public static String toHexStringNoPrefix(byte[] input) {
return toHexString(input, 0, input.length, false);
}
public static String toHexString(byte[] input) {
return toHexString(input, 0, input.length, true);
}
public static byte b(int m, int n) {
return (byte) ( (m << 4) | n);
}
public static boolean isIntegerValue(BigDecimal value) {
return value.signum() == 0 ||
value.scale() <= 0 ||
value.stripTrailingZeros().scale() <= 0;
}
}
好了 這樣 AES512 就實現了, 測試方法我在這就寫了, 自己可以寫個test 測試下。