mirror of
https://gitee.com/dromara/hutool.git
synced 2025-04-05 17:37:59 +08:00
add Base58
This commit is contained in:
parent
c3bf175b2b
commit
1c55e39832
@ -1,36 +1,37 @@
|
||||
package cn.hutool.core.codec;
|
||||
|
||||
import java.math.BigInteger;
|
||||
import cn.hutool.core.exceptions.UtilException;
|
||||
import cn.hutool.core.exceptions.ValidateException;
|
||||
|
||||
import java.security.MessageDigest;
|
||||
import java.security.NoSuchAlgorithmException;
|
||||
import java.util.Arrays;
|
||||
|
||||
|
||||
/**
|
||||
* @author lin
|
||||
* Inspired from https://github.com/adamcaudill/Base58Check/blob/master/src/Base58Check/Base58CheckEncoding.cs
|
||||
* Base58工具类,提供Base58的编码和解码方案<br>
|
||||
* 参考: https://github.com/Anujraval24/Base58Encoding<br>
|
||||
* 规范见:https://en.bitcoin.it/wiki/Base58Check_encoding
|
||||
*
|
||||
* @author lin, looly
|
||||
* @since 5.7.22
|
||||
*/
|
||||
public class Base58 {
|
||||
|
||||
|
||||
private static final String ALPHABET = "123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz";
|
||||
private static final char[] ALPHABET_ARRAY = ALPHABET.toCharArray();
|
||||
private static final BigInteger BASE_SIZE = BigInteger.valueOf(ALPHABET_ARRAY.length);
|
||||
private static final int CHECKSUM_SIZE = 4;
|
||||
|
||||
// -------------------------------------------------------------------- encode
|
||||
|
||||
/**
|
||||
* Base58编码
|
||||
* Base58编码<br>
|
||||
* 包含版本位和校验位
|
||||
*
|
||||
* @param data 被编码的数组,添加校验和。
|
||||
* @param version 编码版本,{@code null}表示不包含版本位
|
||||
* @param data 被编码的数组,添加校验和。
|
||||
* @return 编码后的字符串
|
||||
* @since 5.7.22
|
||||
*/
|
||||
public static String encode(byte[] data) throws NoSuchAlgorithmException {
|
||||
return encodePlain(addChecksum(data));
|
||||
public static String encodeChecked(Integer version, byte[] data) {
|
||||
return encode(addChecksum(version, data));
|
||||
}
|
||||
|
||||
/**
|
||||
@ -38,114 +39,114 @@ public class Base58 {
|
||||
*
|
||||
* @param data 被编码的数据,不带校验和。
|
||||
* @return 编码后的字符串
|
||||
* @since 5.7.22
|
||||
*/
|
||||
public static String encodePlain(byte[] data) {
|
||||
BigInteger intData;
|
||||
try {
|
||||
intData = new BigInteger(1, data);
|
||||
} catch (NumberFormatException e) {
|
||||
return "";
|
||||
}
|
||||
StringBuilder result = new StringBuilder();
|
||||
while (intData.compareTo(BigInteger.ZERO) > 0) {
|
||||
BigInteger[] quotientAndRemainder = intData.divideAndRemainder(BASE_SIZE);
|
||||
BigInteger quotient = quotientAndRemainder[0];
|
||||
BigInteger remainder = quotientAndRemainder[1];
|
||||
intData = quotient;
|
||||
result.insert(0, ALPHABET_ARRAY[remainder.intValue()]);
|
||||
}
|
||||
for (int i = 0; i < data.length && data[i] == 0; i++) {
|
||||
result.insert(0, '1');
|
||||
}
|
||||
return result.toString();
|
||||
public static String encode(byte[] data) {
|
||||
return Base58Codec.INSTANCE.encode(data);
|
||||
}
|
||||
// -------------------------------------------------------------------- decode
|
||||
|
||||
/**
|
||||
* Base58编码
|
||||
* Base58解码<br>
|
||||
* 解码包含标志位验证和版本呢位去除
|
||||
*
|
||||
* @param encoded 被解码的base58字符串
|
||||
* @return 解码后的bytes
|
||||
* @since 5.7.22
|
||||
* @throws ValidateException 标志位验证错误抛出此异常
|
||||
*/
|
||||
public static byte[] decode(String encoded) throws NoSuchAlgorithmException {
|
||||
byte[] valueWithChecksum = decodePlain(encoded);
|
||||
byte[] value = verifyAndRemoveChecksum(valueWithChecksum);
|
||||
if (value == null) {
|
||||
throw new IllegalArgumentException("Base58 checksum is invalid");
|
||||
public static byte[] decodeChecked(CharSequence encoded) throws ValidateException {
|
||||
try {
|
||||
return decodeChecked(encoded, true);
|
||||
} catch (ValidateException ignore) {
|
||||
return decodeChecked(encoded, false);
|
||||
}
|
||||
return value;
|
||||
}
|
||||
|
||||
/**
|
||||
* Base58编码
|
||||
* Base58解码<br>
|
||||
* 解码包含标志位验证和版本呢位去除
|
||||
*
|
||||
* @param encoded 被解码的base58字符串
|
||||
* @param encoded 被解码的base58字符串
|
||||
* @param withVersion 是否包含版本位
|
||||
* @return 解码后的bytes
|
||||
* @since 5.7.22
|
||||
* @throws ValidateException 标志位验证错误抛出此异常
|
||||
*/
|
||||
public static byte[] decodePlain(String encoded) {
|
||||
if (encoded.length() == 0) {
|
||||
return new byte[0];
|
||||
}
|
||||
BigInteger intData = BigInteger.ZERO;
|
||||
int leadingZeros = 0;
|
||||
for (int i = 0; i < encoded.length(); i++) {
|
||||
char current = encoded.charAt(i);
|
||||
int digit = ALPHABET.indexOf(current);
|
||||
if (digit == -1) {
|
||||
throw new IllegalArgumentException(String.format("Invalid Base58 character `%c` at position %d", current, i));
|
||||
}
|
||||
intData = (intData.multiply(BASE_SIZE)).add(BigInteger.valueOf(digit));
|
||||
}
|
||||
public static byte[] decodeChecked(CharSequence encoded, boolean withVersion) throws ValidateException {
|
||||
byte[] valueWithChecksum = decode(encoded);
|
||||
return verifyAndRemoveChecksum(valueWithChecksum, withVersion);
|
||||
}
|
||||
|
||||
for (int i = 0; i < encoded.length(); i++) {
|
||||
char current = encoded.charAt(i);
|
||||
if (current == '1') {
|
||||
leadingZeros++;
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
/**
|
||||
* Base58解码
|
||||
*
|
||||
* @param encoded 被编码的base58字符串
|
||||
* @return 解码后的bytes
|
||||
*/
|
||||
public static byte[] decode(CharSequence encoded) {
|
||||
return Base58Codec.INSTANCE.decode(encoded);
|
||||
}
|
||||
|
||||
/**
|
||||
* 验证并去除验证位和版本位
|
||||
*
|
||||
* @param data 编码的数据
|
||||
* @param withVersion 是否包含版本位
|
||||
* @return 载荷数据
|
||||
*/
|
||||
private static byte[] verifyAndRemoveChecksum(byte[] data, boolean withVersion) {
|
||||
final byte[] payload = Arrays.copyOfRange(data, withVersion ? 1 : 0, data.length - CHECKSUM_SIZE);
|
||||
final byte[] checksum = Arrays.copyOfRange(data, data.length - CHECKSUM_SIZE, data.length);
|
||||
final byte[] expectedChecksum = checksum(payload);
|
||||
if (false == Arrays.equals(checksum, expectedChecksum)) {
|
||||
throw new ValidateException("Base58 checksum is invalid");
|
||||
}
|
||||
byte[] bytesData;
|
||||
if (intData.equals(BigInteger.ZERO)) {
|
||||
bytesData = new byte[0];
|
||||
return payload;
|
||||
}
|
||||
|
||||
/**
|
||||
* 数据 + 校验码
|
||||
*
|
||||
* @param version 版本,{@code null}表示不添加版本位
|
||||
* @param payload Base58数据(不含校验码)
|
||||
* @return Base58数据
|
||||
*/
|
||||
private static byte[] addChecksum(Integer version, byte[] payload) {
|
||||
final byte[] addressBytes;
|
||||
if (null != version) {
|
||||
addressBytes = new byte[1 + payload.length + CHECKSUM_SIZE];
|
||||
addressBytes[0] = (byte) version.intValue();
|
||||
System.arraycopy(payload, 0, addressBytes, 1, payload.length);
|
||||
} else {
|
||||
bytesData = intData.toByteArray();
|
||||
addressBytes = new byte[payload.length + CHECKSUM_SIZE];
|
||||
System.arraycopy(payload, 0, addressBytes, 0, payload.length);
|
||||
}
|
||||
//Should we cut the sign byte ? - https://bitcoinj.googlecode.com/git-history/216deb2d35d1a128a7f617b91f2ca35438aae546/lib/src/com/google/bitcoin/core/Base58.java
|
||||
boolean stripSignByte = bytesData.length > 1 && bytesData[0] == 0 && bytesData[1] < 0;
|
||||
byte[] decoded = new byte[bytesData.length - (stripSignByte ? 1 : 0) + leadingZeros];
|
||||
System.arraycopy(bytesData, stripSignByte ? 1 : 0, decoded, leadingZeros, decoded.length - leadingZeros);
|
||||
return decoded;
|
||||
final byte[] checksum = checksum(payload);
|
||||
System.arraycopy(checksum, 0, addressBytes, addressBytes.length - CHECKSUM_SIZE, CHECKSUM_SIZE);
|
||||
return addressBytes;
|
||||
}
|
||||
|
||||
private static byte[] verifyAndRemoveChecksum(byte[] data) throws NoSuchAlgorithmException {
|
||||
byte[] value = Arrays.copyOfRange(data, 0, data.length - CHECKSUM_SIZE);
|
||||
byte[] checksum = Arrays.copyOfRange(data, data.length - CHECKSUM_SIZE, data.length);
|
||||
byte[] expectedChecksum = getChecksum(value);
|
||||
return Arrays.equals(checksum, expectedChecksum) ? value : null;
|
||||
}
|
||||
|
||||
private static byte[] addChecksum(byte[] data) throws NoSuchAlgorithmException {
|
||||
byte[] checksum = getChecksum(data);
|
||||
byte[] result = new byte[data.length + checksum.length];
|
||||
System.arraycopy(data, 0, result, 0, data.length);
|
||||
System.arraycopy(checksum, 0, result, data.length, checksum.length);
|
||||
return result;
|
||||
}
|
||||
|
||||
private static byte[] getChecksum(byte[] data) throws NoSuchAlgorithmException {
|
||||
byte[] hash = hash256(data);
|
||||
hash = hash256(hash);
|
||||
/**
|
||||
* 获取校验码<br>
|
||||
* 计算规则为对数据进行两次sha256计算,然后取{@link #CHECKSUM_SIZE}长度
|
||||
*
|
||||
* @param data 数据
|
||||
* @return 校验码
|
||||
*/
|
||||
private static byte[] checksum(byte[] data) {
|
||||
byte[] hash = hash256(hash256(data));
|
||||
return Arrays.copyOfRange(hash, 0, CHECKSUM_SIZE);
|
||||
}
|
||||
|
||||
private static byte[] hash256(byte[] data) throws NoSuchAlgorithmException {
|
||||
MessageDigest md = MessageDigest.getInstance("SHA-256");
|
||||
md.update(data);
|
||||
return md.digest();
|
||||
/**
|
||||
* 计算数据的SHA-256值
|
||||
*
|
||||
* @param data 数据
|
||||
* @return sha-256值
|
||||
*/
|
||||
private static byte[] hash256(byte[] data) {
|
||||
try {
|
||||
return MessageDigest.getInstance("SHA-256").digest(data);
|
||||
} catch (NoSuchAlgorithmException e) {
|
||||
throw new UtilException(e);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
142
hutool-core/src/main/java/cn/hutool/core/codec/Base58Codec.java
Normal file
142
hutool-core/src/main/java/cn/hutool/core/codec/Base58Codec.java
Normal file
@ -0,0 +1,142 @@
|
||||
package cn.hutool.core.codec;
|
||||
|
||||
import cn.hutool.core.util.StrUtil;
|
||||
|
||||
import java.util.Arrays;
|
||||
|
||||
/**
|
||||
* Base58编码器<br>
|
||||
* 此编码器不包括校验码、版本等信息
|
||||
*
|
||||
* @author lin, looly
|
||||
* @since 5.7.22
|
||||
*/
|
||||
public class Base58Codec implements Encoder<byte[], String>, Decoder<CharSequence, byte[]> {
|
||||
|
||||
public static Base58Codec INSTANCE = new Base58Codec();
|
||||
|
||||
private final char[] alphabet = "123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz".toCharArray();
|
||||
private final char ENCODED_ZERO = alphabet[0];
|
||||
private final int[] lookup = initLookup();
|
||||
|
||||
/**
|
||||
* Base58编码
|
||||
*
|
||||
* @param data 被编码的数据,不带校验和。
|
||||
* @return 编码后的字符串
|
||||
*/
|
||||
@Override
|
||||
public String encode(byte[] data) {
|
||||
if (null == data) {
|
||||
return null;
|
||||
}
|
||||
if (data.length == 0) {
|
||||
return StrUtil.EMPTY;
|
||||
}
|
||||
// 计算开头0的个数
|
||||
int zeroCount = 0;
|
||||
while (zeroCount < data.length && data[zeroCount] == 0) {
|
||||
++zeroCount;
|
||||
}
|
||||
// 将256位编码转换为58位编码
|
||||
data = Arrays.copyOf(data, data.length); // since we modify it in-place
|
||||
final char[] encoded = new char[data.length * 2]; // upper bound
|
||||
int outputStart = encoded.length;
|
||||
for (int inputStart = zeroCount; inputStart < data.length; ) {
|
||||
encoded[--outputStart] = alphabet[divmod(data, inputStart, 256, 58)];
|
||||
if (data[inputStart] == 0) {
|
||||
++inputStart; // optimization - skip leading zeros
|
||||
}
|
||||
}
|
||||
// Preserve exactly as many leading encoded zeros in output as there were leading zeros in input.
|
||||
while (outputStart < encoded.length && encoded[outputStart] == ENCODED_ZERO) {
|
||||
++outputStart;
|
||||
}
|
||||
while (--zeroCount >= 0) {
|
||||
encoded[--outputStart] = ENCODED_ZERO;
|
||||
}
|
||||
// Return encoded string (including encoded leading zeros).
|
||||
return new String(encoded, outputStart, encoded.length - outputStart);
|
||||
}
|
||||
|
||||
/**
|
||||
* 解码给定的Base58字符串
|
||||
*
|
||||
* @param encoded Base58编码字符串
|
||||
* @return 解码后的bytes
|
||||
* @throws IllegalArgumentException 非标准Base58字符串
|
||||
*/
|
||||
@Override
|
||||
public byte[] decode(CharSequence encoded) throws IllegalArgumentException {
|
||||
if (encoded.length() == 0) {
|
||||
return new byte[0];
|
||||
}
|
||||
// Convert the base58-encoded ASCII chars to a base58 byte sequence (base58 digits).
|
||||
final byte[] input58 = new byte[encoded.length()];
|
||||
for (int i = 0; i < encoded.length(); ++i) {
|
||||
char c = encoded.charAt(i);
|
||||
int digit = c < 128 ? lookup[c] : -1;
|
||||
if (digit < 0) {
|
||||
throw new IllegalArgumentException(StrUtil.format("Invalid char '{}' at [{}]", c, i));
|
||||
}
|
||||
input58[i] = (byte) digit;
|
||||
}
|
||||
// Count leading zeros.
|
||||
int zeros = 0;
|
||||
while (zeros < input58.length && input58[zeros] == 0) {
|
||||
++zeros;
|
||||
}
|
||||
// Convert base-58 digits to base-256 digits.
|
||||
byte[] decoded = new byte[encoded.length()];
|
||||
int outputStart = decoded.length;
|
||||
for (int inputStart = zeros; inputStart < input58.length; ) {
|
||||
decoded[--outputStart] = divmod(input58, inputStart, 58, 256);
|
||||
if (input58[inputStart] == 0) {
|
||||
++inputStart; // optimization - skip leading zeros
|
||||
}
|
||||
}
|
||||
// Ignore extra leading zeroes that were added during the calculation.
|
||||
while (outputStart < decoded.length && decoded[outputStart] == 0) {
|
||||
++outputStart;
|
||||
}
|
||||
// Return decoded data (including original number of leading zeros).
|
||||
return Arrays.copyOfRange(decoded, outputStart - zeros, decoded.length);
|
||||
}
|
||||
|
||||
/**
|
||||
* 初始化字符序号查找表
|
||||
*
|
||||
* @return 字符序号查找表
|
||||
*/
|
||||
private int[] initLookup() {
|
||||
final int[] lookup = new int['z' + 1];
|
||||
Arrays.fill(lookup, -1);
|
||||
for (int i = 0; i < alphabet.length; i++)
|
||||
lookup[alphabet[i]] = i;
|
||||
return lookup;
|
||||
}
|
||||
|
||||
/**
|
||||
* Divides a number, represented as an array of bytes each containing a single digit
|
||||
* in the specified base, by the given divisor. The given number is modified in-place
|
||||
* to contain the quotient, and the return value is the remainder.
|
||||
*
|
||||
* @param number the number to divide
|
||||
* @param firstDigit the index within the array of the first non-zero digit
|
||||
* (this is used for optimization by skipping the leading zeros)
|
||||
* @param base the base in which the number's digits are represented (up to 256)
|
||||
* @param divisor the number to divide by (up to 256)
|
||||
* @return the remainder of the division operation
|
||||
*/
|
||||
private static byte divmod(byte[] number, int firstDigit, int base, int divisor) {
|
||||
// this is just long division which accounts for the base of the input digits
|
||||
int remainder = 0;
|
||||
for (int i = firstDigit; i < number.length; i++) {
|
||||
int digit = (int) number[i] & 0xFF;
|
||||
int temp = remainder * base + digit;
|
||||
number[i] = (byte) (temp / divisor);
|
||||
remainder = temp % divisor;
|
||||
}
|
||||
return (byte) remainder;
|
||||
}
|
||||
}
|
@ -12,7 +12,7 @@ import java.io.Serializable;
|
||||
* @author Looly, Sebastian Ruhleder, sebastian@seruco.io
|
||||
* @since 4.5.9
|
||||
*/
|
||||
public class Base62Codec implements Serializable{
|
||||
public class Base62Codec implements Encoder<byte[], byte[]>, Decoder<byte[], byte[]>, Serializable{
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
private static final int STANDARD_BASE = 256;
|
||||
@ -86,6 +86,7 @@ public class Base62Codec implements Serializable{
|
||||
* @param message 被编码的消息
|
||||
* @return Base62内容
|
||||
*/
|
||||
@Override
|
||||
public byte[] encode(byte[] message) {
|
||||
final byte[] indices = convert(message, STANDARD_BASE, TARGET_BASE);
|
||||
return translate(indices, alphabet);
|
||||
@ -97,6 +98,7 @@ public class Base62Codec implements Serializable{
|
||||
* @param encoded Base62内容
|
||||
* @return 消息
|
||||
*/
|
||||
@Override
|
||||
public byte[] decode(byte[] encoded) {
|
||||
final byte[] prepared = translate(encoded, lookup);
|
||||
return convert(prepared, TARGET_BASE, STANDARD_BASE);
|
||||
@ -177,4 +179,4 @@ public class Base62Codec implements Serializable{
|
||||
return (int) Math.ceil((Math.log(sourceBase) / Math.log(targetBase)) * inputLength);
|
||||
}
|
||||
// --------------------------------------------------------------------------------------------------------------- Private method end
|
||||
}
|
||||
}
|
||||
|
@ -18,15 +18,6 @@ public class Base64Decoder {
|
||||
private static final byte PADDING = -2;
|
||||
|
||||
/** Base64解码表,共128位,-1表示非base64字符,-2表示padding */
|
||||
// private static final byte[] DECODE_TABLE2 = {
|
||||
// -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
|
||||
// -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
|
||||
// -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 62, -1, -1, -1, 63,
|
||||
// 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, -1, -1, -1, -2, -1, -1,
|
||||
// -1, 0, 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, -1, -1, -1, -1, -1,
|
||||
// -1, 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, -1, -1, -1, -1, -1 };
|
||||
private static final byte[] DECODE_TABLE = {
|
||||
// 0 1 2 3 4 5 6 7 8 9 A B C D E F
|
||||
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, // 00-0f
|
||||
|
@ -11,7 +11,7 @@ import java.nio.charset.Charset;
|
||||
* @author looly
|
||||
* @since 3.2.0
|
||||
*/
|
||||
public class Base64Encoder {
|
||||
public class Base64Encoder{
|
||||
|
||||
private static final Charset DEFAULT_CHARSET = CharsetUtil.CHARSET_UTF_8;
|
||||
/** 标准编码表 */
|
||||
|
20
hutool-core/src/main/java/cn/hutool/core/codec/Decoder.java
Normal file
20
hutool-core/src/main/java/cn/hutool/core/codec/Decoder.java
Normal file
@ -0,0 +1,20 @@
|
||||
package cn.hutool.core.codec;
|
||||
|
||||
/**
|
||||
* 解码接口
|
||||
*
|
||||
* @param <T> 被解码的数据类型
|
||||
* @param <R> 解码后的数据类型
|
||||
* @author looly
|
||||
* @since 5.7.22
|
||||
*/
|
||||
public interface Decoder<T, R> {
|
||||
|
||||
/**
|
||||
* 执行解码
|
||||
*
|
||||
* @param data 被解码的数据
|
||||
* @return 解码后的数据
|
||||
*/
|
||||
R decode(T data);
|
||||
}
|
20
hutool-core/src/main/java/cn/hutool/core/codec/Encoder.java
Normal file
20
hutool-core/src/main/java/cn/hutool/core/codec/Encoder.java
Normal file
@ -0,0 +1,20 @@
|
||||
package cn.hutool.core.codec;
|
||||
|
||||
/**
|
||||
* 编码接口
|
||||
*
|
||||
* @param <T> 被编码的数据类型
|
||||
* @param <R> 编码后的数据类型
|
||||
* @author looly
|
||||
* @since 5.7.22
|
||||
*/
|
||||
public interface Encoder<T, R> {
|
||||
|
||||
/**
|
||||
* 执行编码
|
||||
*
|
||||
* @param encoded 被编码的数据
|
||||
* @return 编码后的数据
|
||||
*/
|
||||
R encode(T encoded);
|
||||
}
|
@ -4,31 +4,37 @@ import org.junit.Assert;
|
||||
import org.junit.Test;
|
||||
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.security.NoSuchAlgorithmException;
|
||||
|
||||
public class Base58Test {
|
||||
|
||||
@Test
|
||||
public void testEncode() throws NoSuchAlgorithmException {
|
||||
public void encodeCheckedTest() {
|
||||
String a = "hello world";
|
||||
String encode = Base58.encode(a.getBytes(StandardCharsets.UTF_8));
|
||||
String encode = Base58.encodeChecked(0, a.getBytes());
|
||||
Assert.assertEquals(1 + "3vQB7B6MrGQZaxCuFg4oh", encode);
|
||||
|
||||
// 无版本位
|
||||
encode = Base58.encodeChecked(null, a.getBytes());
|
||||
Assert.assertEquals("3vQB7B6MrGQZaxCuFg4oh", encode);
|
||||
}
|
||||
@Test
|
||||
public void testEncodePlain() {
|
||||
public void encodeTest() {
|
||||
String a = "hello world";
|
||||
String encode = Base58.encodePlain(a.getBytes(StandardCharsets.UTF_8));
|
||||
String encode = Base58.encode(a.getBytes(StandardCharsets.UTF_8));
|
||||
Assert.assertEquals("StV1DL6CwTryKyV", encode);
|
||||
}
|
||||
@Test
|
||||
public void testDecode() throws NoSuchAlgorithmException {
|
||||
public void decodeCheckedTest() {
|
||||
String a = "3vQB7B6MrGQZaxCuFg4oh";
|
||||
byte[] decode = Base58.decode(a);
|
||||
byte[] decode = Base58.decodeChecked(1 + a);
|
||||
Assert.assertArrayEquals("hello world".getBytes(StandardCharsets.UTF_8),decode);
|
||||
decode = Base58.decodeChecked(a);
|
||||
Assert.assertArrayEquals("hello world".getBytes(StandardCharsets.UTF_8),decode);
|
||||
}
|
||||
@Test
|
||||
public void testDecodePlain() {
|
||||
public void testDecode() {
|
||||
String a = "StV1DL6CwTryKyV";
|
||||
byte[] decode = Base58.decodePlain(a);
|
||||
byte[] decode = Base58.decode(a);
|
||||
Assert.assertArrayEquals("hello world".getBytes(StandardCharsets.UTF_8),decode);
|
||||
}
|
||||
}
|
||||
|
@ -1,5 +1,6 @@
|
||||
package cn.hutool.crypto;
|
||||
|
||||
import cn.hutool.core.codec.Base64;
|
||||
import cn.hutool.core.io.FileUtil;
|
||||
import cn.hutool.core.io.IoUtil;
|
||||
import cn.hutool.core.lang.Assert;
|
||||
@ -22,6 +23,7 @@ import java.io.InputStream;
|
||||
import java.math.BigInteger;
|
||||
import java.security.InvalidAlgorithmParameterException;
|
||||
import java.security.InvalidKeyException;
|
||||
import java.security.Key;
|
||||
import java.security.KeyFactory;
|
||||
import java.security.KeyPair;
|
||||
import java.security.KeyPairGenerator;
|
||||
@ -988,4 +990,14 @@ public class KeyUtil {
|
||||
throw new CryptoException(e);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 将密钥编码为Base64格式
|
||||
* @param key 密钥
|
||||
* @return Base64格式密钥
|
||||
* @since 5.7.22
|
||||
*/
|
||||
public static String toBase64(Key key){
|
||||
return Base64.encode(key.getEncoded());
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user