All Downloads are FREE. Search and download functionalities are using the official Maven repository.

cn.hutool.core.codec.Base58 Maven / Gradle / Ivy

There is a newer version: 5.8.33
Show newest version
package cn.hutool.core.codec;

import cn.hutool.core.exceptions.UtilException;
import cn.hutool.core.exceptions.ValidateException;

import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.util.Arrays;


/**
 * Base58工具类,提供Base58的编码和解码方案
* 参考: https://github.com/Anujraval24/Base58Encoding
* 规范见:https://en.bitcoin.it/wiki/Base58Check_encoding * * @author lin, looly * @since 5.7.22 */ public class Base58 { private static final int CHECKSUM_SIZE = 4; // -------------------------------------------------------------------- encode /** * Base58编码
* 包含版本位和校验位 * * @param version 编码版本,{@code null}表示不包含版本位 * @param data 被编码的数组,添加校验和。 * @return 编码后的字符串 */ public static String encodeChecked(Integer version, byte[] data) { return encode(addChecksum(version, data)); } /** * Base58编码 * * @param data 被编码的数据,不带校验和。 * @return 编码后的字符串 */ public static String encode(byte[] data) { return Base58Codec.INSTANCE.encode(data); } // -------------------------------------------------------------------- decode /** * Base58解码
* 解码包含标志位验证和版本呢位去除 * * @param encoded 被解码的base58字符串 * @return 解码后的bytes * @throws ValidateException 标志位验证错误抛出此异常 */ public static byte[] decodeChecked(CharSequence encoded) throws ValidateException { try { return decodeChecked(encoded, true); } catch (ValidateException ignore) { return decodeChecked(encoded, false); } } /** * Base58解码
* 解码包含标志位验证和版本呢位去除 * * @param encoded 被解码的base58字符串 * @param withVersion 是否包含版本位 * @return 解码后的bytes * @throws ValidateException 标志位验证错误抛出此异常 */ public static byte[] decodeChecked(CharSequence encoded, boolean withVersion) throws ValidateException { byte[] valueWithChecksum = decode(encoded); return verifyAndRemoveChecksum(valueWithChecksum, withVersion); } /** * 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"); } 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 { addressBytes = new byte[payload.length + CHECKSUM_SIZE]; System.arraycopy(payload, 0, addressBytes, 0, payload.length); } final byte[] checksum = checksum(payload); System.arraycopy(checksum, 0, addressBytes, addressBytes.length - CHECKSUM_SIZE, CHECKSUM_SIZE); return addressBytes; } /** * 获取校验码
* 计算规则为对数据进行两次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); } /** * 计算数据的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); } } }




© 2015 - 2024 Weber Informatics LLC | Privacy Policy