java - 在javacard中将十六进制字符串转换为字节数组

标签 java binary hex javacard

我有一个名为“hexa”的字节数组,它经过一些过程并生成数组“hexa1”。 packPDU 返回一个字符串数组,该数组具有字符形式的十六进制。我希望遵循“hexa1”的格式,以便将它们解释为数字:

byte[] hexa1 =  { (byte) 0x0F, (byte) 0xAA, (byte) 0x5C, (byte) 0x4E, (byte) 0x45 ,(byte) 0xA3, (byte) 0XA9, (byte) 0x68};

以下是我使用的代码:

package com.bittest;



public class aditya1 {
public static void main(String[] args) {

    byte[] hexa = {'A','9', 'G', 'F', 'B', 'C', 'D', 'E', '5', '1'};
    byte[] gsm= convertUnicode2GSM(hexa);
    byte [] dst=new byte[gsm.length];
    byte[]  packed_array = packPDU(gsm, (short) 0, dst, (short) 0, (short) dst.length) ;

     byte[] hexa1 = new byte [(short)(packed_array.length/2)];
     for(short i =0; i<(short)((packed_array.length/2)-1); i++){
       hexa1[(short)(i+1)] = (byte)((short)(16*hexa[(short)(2*i+1)]) + (short)(hexa[(short)(2*i+2)]));
    }



}

public static byte[] convertUnicode2GSM(byte[] msg) {
       byte[] data = new byte[160];
       short j=0;
       for (short i = 0; i <(short) msg.length; i++) {
       switch (msg[i]) {
       case (byte)'@':  data[j] = 0x00; j++; break;
       case (byte)'$':  data[j] = 0x02; j++;break;
       case (byte)'\n': data[j] = 0x0A; j++;break;
       case (byte)'\r': data[j] = 0x0D; j++;break;
       case (byte)'_':  data[j] = 0x11; j++;break;
       //case (byte) 'ß':  data[j] = 0x1E; j++;break;
       case (byte)' ':  data[j] = 0x20; j++;break;
       case (byte)'!':  data[j] = 0x21; j++;break;

       case (byte) '\"': data[j] = 0x22; j++;break;
       case (byte)'#':  data[j] = 0x23; j++;break;
       case (byte)'%':  data[j] = 0x25; j++;break;
       case (byte)'&':  data[j] = 0x26; j++;break;
       case (byte)'\'': data[j] = 0x27; j++;break;
       case (byte)'(':  data[j] = 0x28; j++;break;
       case (byte)')':  data[j] = 0x29; j++;break;
       case (byte) '*':  data[j] = 0x2A; j++;break;
       case (byte)'+':  data[j] = 0x2B; j++;break;
       case (byte)',':  data[j] = 0x2C; j++;break;
       case (byte)'-':  data[j] = 0x2D; j++;break;
       case (byte) '.':  data[j] = 0x2E; j++;break;
       case (byte)'/':  data[j] = 0x2F; j++;break;
       case (byte)'0':  data[j] = 0x30; j++;break;
       case (byte)'1':  data[j] = 0x31; j++;break;
       case (byte)'2':  data[j] = 0x32; j++;break;
       case (byte)'3':  data[j] = 0x33; j++;break;
       case (byte)'4':  data[j] = 0x34; j++;break;
       case (byte)'5':  data[j] = 0x35; j++;break;
       case (byte)'6':  data[j] = 0x36; j++;break;
       case (byte)'7':  data[j] = 0x37; j++;break;
       case (byte)'8':  data[j] = 0x38; j++;break;
       case(byte) '9':  data[j] = 0x39; j++;break;
       case (byte)':':  data[j] = 0x3A; j++;break;
       case (byte)';':  data[j] = 0x3B; j++;break;
       case (byte)'<':  data[j] = 0x3C; j++;break;
       case (byte)'=':  data[j] = 0x3D; j++;break;
       case (byte)'>':  data[j] = 0x3E; j++;break;
       case (byte)'?':  data[j] = 0x3F; j++;break;
       case (byte)'A':  data[j] = 0x41; j++;break;
       case (byte)'B':  data[j] = 0x42; j++;break;
       case (byte)'C':  data[j] = 0x43; j++;break;
       case (byte)'D':  data[j] = 0x44; j++;break;
       case (byte)'E':  data[j] = 0x45; j++;break;
       case (byte)'F':  data[j] = 0x46; j++;break;
       case (byte)'G':  data[j] = 0x47; j++;break;
       case (byte)'H':  data[j] = 0x48; j++;break;
       case (byte)'I':  data[j] = 0x49; j++;break;
       case (byte)'J':  data[j] = 0x4A; j++;break;
       case (byte)'K':  data[j] = 0x4B; j++;break;
       case (byte)'L':  data[j] = 0x4C; j++;break;
       case (byte)'M':  data[j] = 0x4D; j++;break;
       case (byte)'N':  data[j] = 0x4E; j++;break;
       case (byte)'O':  data[j] = 0x4F; j++;break;
       case (byte)'P':  data[j] = 0x50; j++;break;
       case (byte)'Q':  data[j] = 0x51; j++;break;
       case (byte)'R':  data[j] = 0x52; j++;break;
       case (byte)'S':  data[j] = 0x53; j++;break;
       case (byte)'T':  data[j] = 0x54; j++;break;
       case (byte)'U':  data[j] = 0x55; j++;break;
       case (byte)'V':  data[j] = 0x56; j++;break;
       case (byte)'W':  data[j] = 0x57; j++;break;
       case (byte)'X':  data[j] = 0x58; j++;break;
       case (byte)'Y':  data[j] = 0x59; j++;break;
       case (byte)'Z':  data[j] = 0x5A; j++;break;
     //  case (byte) 'Ü':  data[j] = 0x5E; j++;break;
     //  case (byte) '§':  data[j] = 0x5F; j++;break;
       case (byte)'a':  data[j] = 0x61; j++;break;
       case (byte)'b':  data[j] = 0x62; j++;break;
       case (byte) 'c':  data[j] = 0x63; j++;break;
       case (byte)'d':  data[j] = 0x64; j++;break;
       case (byte)'e':  data[j] = 0x65; j++;break;
       case (byte)'f':  data[j] = 0x66; j++;break;
       case (byte)'g':  data[j] = 0x67; j++;break;
       case (byte)'h':  data[j] = 0x68; j++;break;
       case (byte)'i':  data[j] = 0x69; j++;break;
       case (byte)'j':  data[j] = 0x6A; j++;break;
       case (byte)'k':  data[j] = 0x6B; j++;break;
       case (byte)'l':  data[j] = 0x6C; j++;break;
       case (byte)'m':  data[j] = 0x6D; j++;break;
       case (byte)'n':  data[j] = 0x6E; j++;break;
       case (byte)'o':  data[j] = 0x6F; j++;break;
       case (byte)'p':  data[j] = 0x70; j++;break;
       case (byte)'q':  data[j] = 0x71; j++;break;
       case (byte)'r':  data[j] = 0x72; j++;break;
       case (byte)'s':  data[j] = 0x73; j++;break;
       case (byte)'t':  data[j] = 0x74; j++;break;
       case (byte)'u':  data[j] = 0x75; j++;break;
       case (byte)'v':  data[j] = 0x76; j++;break;
       case (byte)'w':  data[j] = 0x77; j++;break;
       case (byte)'x':  data[j] = 0x78; j++;break;
       case (byte)'y':  data[j] = 0x79; j++;break;
       case (byte)'z':  data[j] = 0x7A; j++;break;
       case (byte) '|':
                        data[j] = 0x1B; 
                        j +=1;
                        data[j] = 0x40;

                        j++;
                        break;


       default:   data[j] = 0x3F; j++;break; // '?'
       }  // switch
       }  // for
       return data;

       }  // convertUnicode2GSM

public static byte[] packPDU(byte[] src, short offsetSrc, byte[] dst, short offsetDst, short length) {

    short countSrc = (short) 0;
    short countDst = (short) 0;
    short countCurrent;
    byte leftover = (byte) 0;

    while (countSrc < length) {
        countCurrent = (byte) (countSrc & 7);
        if (countCurrent == 0) {
            leftover = src[(short) (offsetSrc)];
        } else {
            dst[offsetDst] = (byte) ((src[offsetSrc] << (8 - countCurrent)) | leftover);
            leftover = (byte) (src[offsetSrc] >> countCurrent);
            offsetDst++;
            countDst++;
        }
        countSrc++;
        offsetSrc++;
    }

    if ((length % 8) != 0) {
        dst[offsetDst] = leftover;
        countDst++;
    }

    return dst;
}

最佳答案

我已经通过 Java SE 测试了它,但我还没有将它上传到 Java Card。 Paul Bastian 似乎已经这样做了。

关于十六进制转换的注释在代码中。希望它也展示了一些最佳编程实践:

public final class HexCodec {

    private static final short NIBBLE_SIZE = 4;

    public static final short REASON_DATA_BUFFER_NOT_LARGE_ENOUGH = 0x0001;
    public static final short REASON_INVALID_ENCODING_SIZE = 0x0002;
    public static final short REASON_INVALID_ENCODING_CHARACTER = 0x0003;
    public static final short REASON_INVALID_DATA_SIZE = 0x0004;

    /**
     * Decodes the hexadecimal encoded bytes in the input buffer and puts them
     * in the output buffer.
     * Hex digits need to be ASCII encoded and the letters need to be uppercase.
     * Each byte needs to be encoded using exactly two hexadecimal digits.
     * WARNING: this function doesn't currently validate offset and length
     * arguments.
     * 
     * @param in
     *            the input buffer
     * @param inOff
     *            the offset in the input buffer containing the hexadecimal
     *            bytes
     * @param inLen
     *            the length in the input buffer of the hexadecimal bytes
     * @param out
     *            the output buffer
     * @param outOff
     *            the offset in the output buffer of the decoded bytes
     * @return the length in the output buffer of the decoded bytes
     * @throws CardRuntimeException
     *             with the following reason codes:
     *             <nl>
     *             <li>
     *             {@link HexCodec#REASON_INVALID_ENCODING_SIZE} : if the
     *             encoding size is not a multiple of 2</li>
     *             <li>
     *             {@link HexCodec#REASON_DATA_BUFFER_NOT_LARGE_ENOUGH} : if
     *             the output buffer cannot hold the decoded data</li>
     *             <li>
     *             {@link HexCodec#REASON_INVALID_ENCODING_CHARACTER} : if
     *             the encoding contains characters outside the uppercase
     *             hexadecimals</li>
     *             </nl>
     */
    private static short fromUppercaseHex(final byte[] in, final short inOff,
            final short inLen,
            final byte[] out, final short outOff) {

        // doesn't validate offsets in buffer

        // odd number of hex characters not allowed
        if (inLen % 2 != 0) {
            throw createCardRuntimeException(REASON_INVALID_ENCODING_SIZE);
        }

        final short outLen = (short) (inLen / 2);

        // make sure we have enough room in the buffer *before* decoding
        final short outEnd = (short) (outOff + outLen);
        if (outEnd < 0
                || outEnd > (short) out.length) {
            throw createCardRuntimeException(REASON_DATA_BUFFER_NOT_LARGE_ENOUGH);
        }

        // main decode loop
        for (short i = 0; i < outLen; i++) {
            byte b;

            // decodes high nibble of b
            final byte hexHi = in[(short) (inOff + i * 2)];
            if (hexHi >= '0' && hexHi <= '9') {
                b = (byte) ((hexHi - '0') << NIBBLE_SIZE);
            } else if (hexHi >= 'A' && hexHi <= 'F') {
                b = (byte) ((hexHi - 'A' + 10) << NIBBLE_SIZE);
            } else {
                throw createCardRuntimeException(REASON_INVALID_ENCODING_CHARACTER);
            }

            // decodes low nibble of b
            final byte hexLo = in[(short) (inOff + i * 2 + 1)];
            if (hexLo >= '0' && hexLo <= '9') {
                b |= (byte) (hexLo - '0');
            } else if (hexLo >= 'A' && hexLo <= 'F') {
                b |= (byte) (hexLo - 'A' + 10);
            } else {
                throw createCardRuntimeException(REASON_INVALID_ENCODING_CHARACTER);
            }

            out[(short) (outOff + i)] = b;
        }

        return outLen;
    }

    /**
     * Encodes the bytes in the input buffer and puts the hexadecimals in the
     * output buffer.
     * The hex digits will be ASCII encoded and the letters will be in
     * uppercase.
     * Each byte will be encoded using exactly two hexadecimal digits.
     * WARNING: this function doesn't currently validate offset and length
     * arguments.
     * 
     * @param in
     *            the input buffer
     * @param inOff
     *            the offset in the input buffer containing the binary data
     *            bytes
     * @param inLen
     *            the length in the input buffer of the binary data
     * @param out
     *            the output buffer
     * @param outOff
     *            the offset in the output buffer for the hexadecimal digits
     * @return the number of hexadecimal digits
     * @throws CardRuntimeException
     *             with the following reason codes:
     *             <nl>
     *             <li>
     *             {@link HexCodec#REASON_INVALID_DATA_SIZE} : if the output
     *             buffer cannot hold the encoded data</li>
     *             </nl>
     */
    private static short toUppercaseHex(
            final byte[] in, final short inOff, final short inLen,
            final byte[] out, final short outOff) {

        // doesn't validate offsets in buffer

        final short outLen = (short) (inLen * 2);
        final short outEnd = (short) (outOff + outLen);

        // make sure we have enough room in the buffer *before* decoding
        if (outEnd < 0 || outEnd > (short) out.length) {
            throw createCardRuntimeException(REASON_INVALID_DATA_SIZE);
        }

        // main encode loop
        for (short i = 0; i < inLen; i++) {
            final byte b = in[(short) (inOff + i)];

            // encodes high nibble of b
            final byte bHi = (byte) ((b >> NIBBLE_SIZE) & 0x0F);
            if (bHi < 10) {
                out[(short) (outOff + i * 2)] = (byte) ('0' + bHi);
            } else {
                out[(short) (outOff + i * 2)] = (byte) ('A' + bHi - 10);
            }

            // encodes low nibble of b
            final byte bLo = (byte) (b & 0x0F);
            if (bLo < 10) {
                out[(short) (outOff
                        + i * 2 + 1)] = (byte) ('0' + bLo);
            } else {
                out[(short) (outOff
                        + i * 2 + 1)] = (byte) ('A' + bLo - 10);
            }
        }

        return outLen;
    }

    /**
     * Creates a CardRuntimeException with the given reason code and returns it
     * so it can be thrown.
     * This alleviates the issue of the Java compiler not recognizing `throwIt`
     * as exit point.
     * WARNING: do not forget to actually throw the exception returned.
     * 
     * @param reason
     *            the reason code of the exception
     * @return the exception generated by the runtime environment (through
     *         <code>CardRuntimeException.throwIt</code>)
     */
    private static CardRuntimeException createCardRuntimeException(
            final short reason) {
        try {
            CardRuntimeException.throwIt(reason);
        } catch (CardRuntimeException e) {
            return e;
        }
        // should never be reached (but the compiler doesn't know that)
        return null;
    }

    private HexCodec() {
        // avoid instantiation
    }
}

关于java - 在javacard中将十六进制字符串转换为字节数组,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/41282249/

相关文章:

java - 如何设置Hadoop中MultithreadedMapRunner的线程数?

java - 返回到 First/Main Activity 而不重新加载它

string - Go:将 rune (字符串)转换为二进制的字符串表示形式

c - 在windows机器上读取linux机器生成的二进制文件

javascript - 为什么 Node.js 不输出二进制值 0's and 1' s?

c - 十六进制语法符号

java - 用 Java 实现 map

c++ - 将具有数字的十六进制表示形式的字符串转换为实际数值

c++ - 如何将十六进制字符串拆分为 std::vector?

java - 如何在Java中正确使用ulimit?