package com.yida.data.common.core.utils.construction;

import java.io.DataInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.math.BigInteger;

/**
 * DER类
 *
 * @author ZYJ
 * @date 2023/6/22 2:26
 */
public class DER {

    static int INTEGER = 2;
    static int BIT_STRING = 3;
    static int OCTET_STRING = 4;
    static int SEQUENCE = 16;
    static int CONSTRUCTED = 32;
    static byte[] version = new byte[]{2, 1, 0};
    static byte[] rsaEncryptionAlgorithmIdentifier = new byte[]{48, 13, 6, 9, 42, -122, 72, -122, -9, 13, 1, 1, 1, 5, 0};

    DER() {
    }

    static BigInteger readDERint(InputStream inputstream) throws IOException {
        DataInputStream datainputstream = new DataInputStream(inputstream);
        int i = readTag(datainputstream);
        int j = readLen(datainputstream);
        if (i != INTEGER) {
            throw new RuntimeException("Expecting tag[0x02] got " + Integer.toHexString(i));
        } else if (j > 5096) {
            throw new RuntimeException("Length value seems a little big " + Integer.toHexString(j));
        } else {
            byte[] abyte0 = new byte[j];
            datainputstream.readFully(abyte0);
            return new BigInteger(abyte0);
        }
    }

    static int readLen(InputStream inputstream) throws IOException {
        int i = inputstream.read();
        if (i > 127) {
            int j = 0;
            i ^= 128;

            for(int k = 0; k < i; ++k) {
                j = j * 256 + inputstream.read();
            }

            i = j;
        }

        return i;
    }

    static int readTag(InputStream inputstream) throws IOException {
        return inputstream.read();
    }

    static int writeDERint(OutputStream outputstream, BigInteger biginteger) throws IOException {
        byte[] abyte0 = biginteger.toByteArray();
        int i = abyte0.length + 1;
        outputstream.write(INTEGER);
        i += writeDERlen(outputstream, abyte0.length);
        outputstream.write(abyte0);
        return i;
    }

    static int writeDERlen(OutputStream outputstream, int i) throws IOException {
        if (i <= 127) {
            outputstream.write((byte)i);
            return 1;
        } else {
            byte byte0 = 1;
            if (i >= 256) {
                byte0 = 2;
            } else if (i >= 65536) {
                byte0 = 3;
            } else if (i >= 16777216) {
                byte0 = 4;
            }

            outputstream.write((byte)(byte0 | 128));

            for(int j = (byte0 - 1) * 8; j >= 0; j -= 8) {
                int k = i >> j;
                outputstream.write((byte)k);
            }

            return byte0;
        }
    }
}
