public static SignatureData signatureDataFromHex(String hexSignature)
            throws SignatureException {
        byte[] sigBytes = Numeric.hexStringToByteArray(hexSignature);
        byte v;
        byte[] r, s;
        if (sigBytes.length == 64) {
            // EIP-2098; pull the v from the top bit of s and clear it
            v = (byte) (27 + (sigBytes[32] >> 7));
            sigBytes[32] &= 0x7f;
            r = Arrays.copyOfRange(sigBytes, 0, 32);
            s = Arrays.copyOfRange(sigBytes, 32, 64);

        } else if (sigBytes.length == 65) {
            r = Arrays.copyOfRange(sigBytes, 0, 32);
            s = Arrays.copyOfRange(sigBytes, 32, 64);
            v = sigBytes[64];
        } else {
            throw new SignatureException("invalid signature string");
        }
        // Allow a recid to be used as the v
        if (v < 27) {
            if (v == 0 || v == 1) {
                v = (byte) (v + 27);
            } else {
                throw new SignatureException("signature invalid v byte");
            }
        }
        return new Sign.SignatureData(v, r, s);
    }
@Test
    public void testFromHex() throws SignatureException {
        Sign.SignatureData signatureData =
                Sign.signatureDataFromHex(
                        "0x0464eee9e2fe1a10ffe48c78b80de1ed8dcf996f3f60955cb2e03cb21903d93006624da478b3f862582e85b31c6a21c6cae2eee2bd50f55c93c4faad9d9c8d7f1c");

        Sign.SignatureData expected =
                new Sign.SignatureData(
                        (byte) 28,
                        Numeric.hexStringToByteArray(
                                "0x0464eee9e2fe1a10ffe48c78b80de1ed8dcf996f3f60955cb2e03cb21903d930"),
                        Numeric.hexStringToByteArray(
                                "0x06624da478b3f862582e85b31c6a21c6cae2eee2bd50f55c93c4faad9d9c8d7f"));

        assertEquals(signatureData, (expected));
    }