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

io.nuls.core.parse.SerializeUtils Maven / Gradle / Ivy

/*
 * MIT License
 *
 * Copyright (c) 2017-2018 nuls.io
 *
 * Permission is hereby granted, free of charge, to any person obtaining a copy
 * of this software and associated documentation files (the "Software"), to deal
 * in the Software without restriction, including without limitation the rights
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 * copies of the Software, and to permit persons to whom the Software is
 * furnished to do so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in all
 * copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
 * SOFTWARE.
 *
 */
package io.nuls.core.parse;

import io.nuls.core.basic.NulsData;
import io.nuls.core.basic.VarInt;
import io.nuls.core.constant.ToolsConstant;
import io.nuls.core.crypto.Sha256Hash;
import io.nuls.core.exception.NulsRuntimeException;
import io.nuls.core.log.Log;
import io.nuls.core.model.ByteUtils;
import org.bouncycastle.crypto.digests.RIPEMD160Digest;

import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.OutputStream;
import java.io.UnsupportedEncodingException;
import java.math.BigInteger;
import java.nio.charset.Charset;

/**
 * @author tag
 */
public class SerializeUtils {

    public static final Charset CHARSET = Charset.forName(ToolsConstant.DEFAULT_ENCODING);
    private static final int MAGIC_8 = 8;
    private static final int MAGIC_0X80 = 0x80;
    /**
     * The string that prefixes all text messages signed using Bitcoin keys.
     */
    public static final String SIGNED_MESSAGE_HEADER = "RiceChain Signed Message:\n";
    public static final byte[] SIGNED_MESSAGE_HEADER_BYTES = SIGNED_MESSAGE_HEADER.getBytes(CHARSET);

    /**
     * MPI encoded numbers are produced by the OpenSSL BN_bn2mpi function. They consist of
     * a 4 byte big endian length field, followed by the stated number of bytes representing
     * the number in big endian format (with a sign bit).
     *
     * @param hasLength can be set to false if the given array is missing the 4 byte length field
     */
    public static BigInteger decodeMPI(byte[] mpi, boolean hasLength) {
        byte[] buf;
        if (hasLength) {
            int length = (int) readUint32BE(mpi, 0);
            buf = new byte[length];
            System.arraycopy(mpi, 4, buf, 0, length);
        } else {
            buf = mpi;
        }
        if (buf.length == 0) {
            return BigInteger.ZERO;
        }
        boolean isNegative = (buf[0] & MAGIC_0X80) == MAGIC_0X80;
        if (isNegative) {
            buf[0] &= 0x7f;
        }
        BigInteger result = new BigInteger(buf);
        return isNegative ? result.negate() : result;
    }

    /**
     * MPI encoded numbers are produced by the OpenSSL BN_bn2mpi function. They consist of
     * a 4 byte big endian length field, followed by the stated number of bytes representing
     * the number in big endian format (with a sign bit).
     *
     * @param includeLength indicates whether the 4 byte length field should be included
     */
    public static byte[] encodeMPI(BigInteger value, boolean includeLength) {
        if (value.equals(BigInteger.ZERO)) {
            if (!includeLength) {
                return new byte[]{};
            } else {
                return new byte[]{0x00, 0x00, 0x00, 0x00};
            }
        }
        boolean isNegative = value.signum() < 0;
        if (isNegative) {
            value = value.negate();
        }
        byte[] array = value.toByteArray();
        int length = array.length;
        if ((array[0] & MAGIC_0X80) == MAGIC_0X80) {
            length++;
        }
        if (includeLength) {
            byte[] result = new byte[length + 4];
            System.arraycopy(array, 0, result, length - array.length + 3, array.length);
            uint32ToByteArrayBE(length, result, 0);
            if (isNegative) {
                result[4] |= MAGIC_0X80;
            }
            return result;
        } else {
            byte[] result;
            if (length != array.length) {
                result = new byte[length];
                System.arraycopy(array, 0, result, 1, array.length);
            } else {
                result = array;
            }
            if (isNegative) {
                result[0] |= MAGIC_0X80;
            }
            return result;
        }
    }


    /**
     * Given a textual message, returns a byte buffer formatted as follows:

*

* [24] "Bitcoin Signed Message:\n" [message.length as a varint] message

*/ public static byte[] formatMessageForSigning(String message) { try { ByteArrayOutputStream bos = new ByteArrayOutputStream(); bos.write(SIGNED_MESSAGE_HEADER_BYTES.length); bos.write(SIGNED_MESSAGE_HEADER_BYTES); byte[] messageBytes = message.getBytes(CHARSET); VarInt size = new VarInt(messageBytes.length); bos.write(size.encode()); bos.write(messageBytes); return bos.toByteArray(); } catch (IOException e) { // Cannot happen. throw new RuntimeException(e); } } public static short readUint8LE(byte[] bytes, int offset) { return (short) (bytes[offset] & 0xff); } /** * Parse 2 bytes from the byte array (starting at the offset) as unsigned 16-bit integer in little endian format./从字节数组(以偏移量开始)解析2字节,以小端格式的无符号16位整数 * * @param bytes 字节数组 * @param offset 偏移量(数组下标) */ public static int readUint16LE(byte[] bytes, int offset) { return (bytes[offset] & 0xff) | ((bytes[offset + 1] & 0xff) << 8); } /** * Parse 2 bytes from the byte array (starting at the offset) as unsigned 16-bit integer in big endian format./从字节数组(以偏移量开始)解析2字节,以大端格式的无符号32位整数 * * @param bytes 字节数组 * @param offset 偏移量(数组下标) */ public static int readUint16BE(byte[] bytes, int offset) { return ((bytes[offset] & 0xff) << 8) | (bytes[offset + 1] & 0xff); } /** * Parse 2 bytes from the byte array (starting at the offset) as unsigned 16-bit integer in little endian format. * 从字节数组(以偏移量开始)解析2字节,以端格式的无符号16位整数 * * @param bytes byte[] * @param offset int偏移量 * @return int */ public static int readUint16(byte[] bytes, int offset) { return (bytes[offset] & 0xff) | ((bytes[offset + 1] & 0xff) << 8); } /** * Parse 4 bytes from the byte array (starting at the offset) as unsigned 32-bit integer in little endian format./从字节数组(以偏移量开始)解析4字节,以小端格式的无符号32位整数 * * @param bytes 字节数组 * @param offset 偏移量(数组下标) */ public static long readUint32LE(byte[] bytes, int offset) { return (bytes[offset] & 0xffL) | ((bytes[offset + 1] & 0xffL) << 8) | ((bytes[offset + 2] & 0xffL) << 16) | ((bytes[offset + 3] & 0xffL) << 24); } /** * Parse 4 bytes from the byte array (starting at the offset) as unsigned 32-bit integer in little endian format./从字节数组(以偏移量开始)解析4字节,以小端格式的无符号32位整数 * * @param bytes 字节数组 * @param offset 偏移量(数组下标) */ public static int readInt32LE(byte[] bytes, int offset) { return (bytes[offset] & 0xff) | ((bytes[offset + 1] & 0xff) << 8) | ((bytes[offset + 2] & 0xff) << 16) | ((bytes[offset + 3] & 0xff) << 24); } /** * Parse 4 bytes from the byte array (starting at the offset) as unsigned 32-bit integer in big endian format./从字节数组(以偏移量开始)解析4字节,以大端格式的无符号32位整数 * * @param bytes 字节数组 * @param offset 偏移量(数组下标) */ public static long readUint32BE(byte[] bytes, int offset) { return ((bytes[offset] & 0xffL) << 24) | ((bytes[offset + 1] & 0xffL) << 16) | ((bytes[offset + 2] & 0xffL) << 8) | (bytes[offset + 3] & 0xffL); } /** * Parse 4 bytes from the byte array (starting at the offset) as unsigned 32-bit integer in little endian format. * 从字节数组(以偏移量开始)解析4字节,以端格式的无符号32位整数 * * @param bytes byte[] * @param offset int偏移量 * @return int */ public static long readUint32(byte[] bytes, int offset) { return (bytes[offset] & 0xffL) | ((bytes[offset + 1] & 0xffL) << 8) | ((bytes[offset + 2] & 0xffL) << 16) | ((bytes[offset + 3] & 0xffL) << 24); } /** * Parse 6 bytes from the byte array (starting at the offset) as unsigned 48-bit integer in little endian format. * 从字节数组(以偏移量开始)解析6字节,以端格式的无符号48位整数 * * @param bytes byte[] * @param offset int偏移量 * @return int */ public static long readUint48(byte[] bytes, int offset) { return (bytes[offset] & 0xffL) | ((bytes[offset + 1] & 0xffL) << 8) | ((bytes[offset + 2] & 0xffL) << 16) | ((bytes[offset + 3] & 0xffL) << 24) | ((bytes[offset + 4] & 0xffL) << 32) | ((bytes[offset + 5] & 0xffL) << 40); } /** * Parse 8 bytes from the byte array (starting at the offset) as unsigned 64-bit integer in little endian format./从字节数组(以偏移量开始)解析8字节,以小端格式的无符号64位整数 * * @param bytes 字节数组 * @param offset 偏移量(数组下标) */ public static long readInt64LE(byte[] bytes, int offset) { return (bytes[offset] & 0xffL) | ((bytes[offset + 1] & 0xffL) << 8) | ((bytes[offset + 2] & 0xffL) << 16) | ((bytes[offset + 3] & 0xffL) << 24) | ((bytes[offset + 4] & 0xffL) << 32) | ((bytes[offset + 5] & 0xffL) << 40) | ((bytes[offset + 6] & 0xffL) << 48) | ((bytes[offset + 7] & 0xffL) << 56); } /** * Parse 8 bytes from the byte array (starting at the offset) as unsigned 64-bit integer in little endian format. * 从字节数组(以偏移量开始)解析8字节,以端格式的无符号64位整数 * * @param bytes byte[] * @param offset int偏移量 * @return int */ public static long readUint64(byte[] bytes, int offset) { return (bytes[offset] & 0xffL) | ((bytes[offset + 1] & 0xffL) << 8) | ((bytes[offset + 2] & 0xffL) << 16) | ((bytes[offset + 3] & 0xffL) << 24) | ((bytes[offset + 4] & 0xffL) << 32) | ((bytes[offset + 5] & 0xffL) << 40) | ((bytes[offset + 6] & 0xffL) << 48) | ((bytes[offset + 7] & 0xffL) << 56); } /** * int转byte[] (只转int数据四个字节中的两个字节) * * @param x int * @return byte[] */ public static byte[] int16ToBytes(int x) { byte[] bb = new byte[2]; bb[1] = (byte) (0xFF & x >> 8); bb[0] = (byte) (0xFF & x); return bb; } /** * int转byte[] * * @param x int * @return byte[] */ public static byte[] int32ToBytes(int x) { byte[] bb = new byte[4]; bb[3] = (byte) (0xFF & x >> 24); bb[2] = (byte) (0xFF & x >> 16); bb[1] = (byte) (0xFF & x >> 8); bb[0] = (byte) (0xFF & x); return bb; } /** * long数据转byte[](只转前6个字节) * * @param val long * @return byte[] */ public static byte[] uint48ToBytes(long val) { byte[] bytes = new byte[SerializeUtils.sizeOfUint48()]; bytes[0] = (byte) (0xFF & val); bytes[1] = (byte) (0xFF & (val >> 8)); bytes[2] = (byte) (0xFF & (val >> 16)); bytes[3] = (byte) (0xFF & (val >> 24)); bytes[4] = (byte) (0xFF & (val >> 32)); bytes[5] = (byte) (0xFF & (val >> 40)); return bytes; } /** * long数据转byte[] * * @param val long * @return byte[] */ public static byte[] uint64ToByteArray(long val) { byte[] out = new byte[8]; out[0] = (byte) (0xFF & val); out[1] = (byte) (0xFF & (val >> 8)); out[2] = (byte) (0xFF & (val >> 16)); out[3] = (byte) (0xFF & (val >> 24)); out[4] = (byte) (0xFF & (val >> 32)); out[5] = (byte) (0xFF & (val >> 40)); out[6] = (byte) (0xFF & (val >> 48)); out[7] = (byte) (0xFF & (val >> 56)); return out; } /** * Calculates RIPEMD160(SHA256(input)). This is used in Address calculations. * * @param input 字节数组 */ public static byte[] sha256hash160(byte[] input) { byte[] sha256 = Sha256Hash.hash(input); RIPEMD160Digest digest = new RIPEMD160Digest(); digest.update(sha256, 0, sha256.length); byte[] out = new byte[20]; digest.doFinal(out, 0); return out; } /** * The regular {@link BigInteger#toByteArray()} method isn't quite what we often need: it appends a * leading zero to indicate that the number is positive and may need padding. * * @param b the integer to format into a byte array * @param numBytes the desired size of the resulting byte array * @return numBytes byte long array. */ public static byte[] bigIntegerToBytes(BigInteger b, int numBytes) { if (b == null) { return null; } byte[] bytes = new byte[numBytes]; byte[] biBytes = b.toByteArray(); int start = (biBytes.length == numBytes + 1) ? 1 : 0; int length = Math.min(biBytes.length, numBytes); System.arraycopy(biBytes, start, bytes, numBytes - length, length); return bytes; } /** * 将一个short型数据以小端格式存储到指定字节数组指定的偏移量的连续2个字节中 * * @param val short数据 * @param out 存放short型数据的字节数组 * @param offset 偏移量 */ public static void int16ToByteArrayLE(short val, byte[] out, int offset) { out[offset] = (byte) (0xFF & val); out[offset + 1] = (byte) (0xFF & (val >> 8)); } /** * 将一个Long型数据以大端格式存储到指定字节数组指定的偏移量的连续4个字节中 * * @param val long数据 * @param out 存放Long型数据的字节数组 * @param offset 偏移量 */ public static void uint32ToByteArrayBE(long val, byte[] out, int offset) { out[offset] = (byte) (0xFF & (val >> 24)); out[offset + 1] = (byte) (0xFF & (val >> 16)); out[offset + 2] = (byte) (0xFF & (val >> 8)); out[offset + 3] = (byte) (0xFF & val); } /** * 将一个Long型数据以小端格式存储到指定字节数组指定的偏移量的连续4个字节中 * * @param val long数据 * @param out 存放Long型数据的字节数组 * @param offset 偏移量 */ public static void uint32ToByteArrayLE(long val, byte[] out, int offset) { out[offset] = (byte) (0xFF & val); out[offset + 1] = (byte) (0xFF & (val >> 8)); out[offset + 2] = (byte) (0xFF & (val >> 16)); out[offset + 3] = (byte) (0xFF & (val >> 24)); } /** * 将一个int型数据以小端格式存储到指定字节数组指定的偏移量的连续4个字节中 * * @param val int数据 * @param out 存放int型数据的字节数组 * @param offset 偏移量 */ public static void int32ToByteArrayLE(int val, byte[] out, int offset) { out[offset] = (byte) (0xFF & val); out[offset + 1] = (byte) (0xFF & (val >> 8)); out[offset + 2] = (byte) (0xFF & (val >> 16)); out[offset + 3] = (byte) (0xFF & (val >> 24)); } /** * 将一个Long型数据以小端格式存储到指定字节数组指定的偏移量的连续8个字节中 * * @param val long数据 * @param out 存放Long型数据的字节数组 * @param offset 偏移量 */ public static void uint64ToByteArrayLE(long val, byte[] out, int offset) { out[offset] = (byte) (0xFF & val); out[offset + 1] = (byte) (0xFF & (val >> 8)); out[offset + 2] = (byte) (0xFF & (val >> 16)); out[offset + 3] = (byte) (0xFF & (val >> 24)); out[offset + 4] = (byte) (0xFF & (val >> 32)); out[offset + 5] = (byte) (0xFF & (val >> 40)); out[offset + 6] = (byte) (0xFF & (val >> 48)); out[offset + 7] = (byte) (0xFF & (val >> 56)); } public static void uint8ToByteStreamLE(short val, OutputStream stream) throws IOException { stream.write((short) (0xFF & val)); } /** * Write 2 bytes to the output stream as unsigned 16-bit short in little endian format./将2字节写入输出流作为无符号16位short型数据,以小端格式 * * @param val short数据 * @param stream 输出流 */ public static void int16ToByteStreamLE(short val, OutputStream stream) throws IOException { stream.write((byte) (0xFF & val)); stream.write((byte) (0xFF & (val >> 8))); } /** * Write 2 bytes to the output stream as unsigned 16-bit integer in little endian format./将2字节写入输出流作为无符号16位整数,以小端格式 * * @param val int数据 * @param stream 输出流 */ public static void uint16ToByteStreamLE(int val, OutputStream stream) throws IOException { stream.write((int) (0xFF & val)); stream.write((int) (0xFF & (val >> 8))); } /** * Write 4 bytes to the output stream as unsigned 32-bit long in little endian format./将4字节写入输出流作为无符号32位long型数据,以小端格式 * * @param val long数据 * @param stream 输出流 */ public static void uint32ToByteStreamLE(long val, OutputStream stream) throws IOException { stream.write((int) (0xFF & val)); stream.write((int) (0xFF & (val >> 8))); stream.write((int) (0xFF & (val >> 16))); stream.write((int) (0xFF & (val >> 24))); } /** * Write 8 bytes to the output stream as unsigned 64-bit long in little endian format./将8字节写入输出流作为无符号64位long型数据,以小端格式 * * @param val long数据 * @param stream 输出流 */ public static void int64ToByteStreamLE(long val, OutputStream stream) throws IOException { stream.write((int) (0xFF & val)); stream.write((int) (0xFF & (val >> 8))); stream.write((int) (0xFF & (val >> 16))); stream.write((int) (0xFF & (val >> 24))); stream.write((int) (0xFF & (val >> 32))); stream.write((int) (0xFF & (val >> 40))); stream.write((int) (0xFF & (val >> 48))); stream.write((int) (0xFF & (val >> 56))); } /** * Write 8 bytes to the output stream as unsigned 64-bit BigInteger in little endian format./将8字节写入输出流作为无符号64位BigInteger型数据,以小端格式 * * @param val BigInteger数据 * @param stream 输出流 */ public static void uint64ToByteStreamLE(BigInteger val, OutputStream stream) throws IOException { byte[] bytes = val.toByteArray(); if (bytes.length > MAGIC_8) { throw new RuntimeException("Input too large to encode into a uint64"); } bytes = ByteUtils.reverseBytes(bytes); stream.write(bytes); if (bytes.length < MAGIC_8) { for (int i = 0; i < MAGIC_8 - bytes.length; i++) { stream.write(0); } } } /** * 将Double类型数据写入输出流 * * @param val BigInteger数据 * @param stream 输出流 */ public static void doubleToByteStream(double val, OutputStream stream) throws IOException { stream.write(ByteUtils.doubleToBytes(val)); } public static int sizeOfDouble(Double val) { return MAGIC_8; } /** * 字符串转为byte[]的长度 * * @param val String * @return int */ public static int sizeOfString(String val) { if (null == val) { return 1; } byte[] bytes; try { bytes = val.getBytes(ToolsConstant.DEFAULT_ENCODING); } catch (UnsupportedEncodingException e) { Log.error(e.getMessage()); throw new NulsRuntimeException(e); } return sizeOfBytes(bytes); } /** * 计算Long型数据占几个字节 * * @param val Long * @return int */ public static int sizeOfVarInt(Long val) { return VarInt.sizeOf(val); } /** * 获取Int16数据占的字节数 * * @return int */ public static int sizeOfInt16() { return 2; } /** * 获取BigInteger数据占的字节数 * * @return int */ public static int sizeOfBigInteger() { return 32; } /** * 获取Uint16数据占的字节数 * * @return int */ public static int sizeOfUint16() { return 2; } /** * 获取Int32数据占的字节数 * * @return int */ public static int sizeOfInt32() { return 4; } /** * 获取Uint32数据占的字节数 * * @return int */ public static int sizeOfUint32() { return 4; } /** * 获取Unit48数据占的字节数 * * @return int */ public static int sizeOfUint48() { return ToolsConstant.INT48_VALUE_LENGTH; } /** * 获取Int64数据占的字节数 * * @return int */ public static int sizeOfInt64() { return 8; } /** * 获取指定Integer占用的最小字节数 * * @param val Integer * @return int */ public static int sizeOfVarInt(Integer val) { return VarInt.sizeOf(val); } /** * 获取Boolean数据占的字节数 * * @return int */ public static int sizeOfBoolean() { return 1; } /** * 获取nonce数据占的字节数 * * @return int */ public static int sizeOfNonce() { return 8; } /** * 获取byte[]占用的最小字节数(byte[]长度占用的最小字节数+byte[]长度) */ public static int sizeOfBytes(byte[] val) { if (null == val) { return 1; } return VarInt.sizeOf((val).length) + (val).length; } /** * 获取NulsData对象所占字节长度 * * @param val NulsData * @return int */ public static int sizeOfNulsData(NulsData val) { if (null == val) { return ToolsConstant.PLACE_HOLDER.length; } int size = val.size(); return size == 0 ? 1 : size; } /** * 根据字节数组生成对应的大整数 * Generate corresponding large integers from byte arrays * * @param array 小端序的字节数组/Small-endian byte array * @return 大整数 */ public static BigInteger bigIntegerFromBytes(byte[] array) { array = arrayReverse(array); return new BigInteger(array); } /** * 将大整数转为字节数组,结果是小端序字节数组 * Converting large integers to byte arrays results in small endian byte arrays * * @param value 大整数、BigInteger * @return 字节数组 */ public static byte[] bigInteger2Bytes(BigInteger value) { byte[] bytes = new byte[32]; byte[] oBytes = value.toByteArray(); oBytes = arrayReverse(oBytes); if (oBytes.length > 32) { throw new RuntimeException("The number is too large!"); } System.arraycopy(oBytes, 0, bytes, 0, oBytes.length); return bytes; } /** * 数组反转工具方法,会返回一个顺序颠倒的新的字节数组 * The array inversion tool method returns a new byte array in reverse order * * @param bytes 需要反转的字节数组 * @return a new byte array in reverse order */ private static byte[] arrayReverse(byte[] bytes) { int length = bytes.length; byte[] array = new byte[length]; for (int x = 0; x < length; x++) { array[x] = bytes[length - 1 - x]; } return array; } }




© 2015 - 2025 Weber Informatics LLC | Privacy Policy