Java generates JWT manually

head

First, we need a Jason

{
	"alg":"HS256"
}

Then we need to show it in Java

        String header = "{\n" +
                "\t\"alg\":\"HS256\"\n" +
                "}";

Then remove all spaces

        String header = "{"alg":"HS256"}";

If the error is reported, it is obvious that there is a problem, and then use the escape character to show the "normal"

        String header = "{\"alg\":\"HS256\"}";

At this time, we encrypt the string with Base64URL, and here we use URLBase64 encryption based on common codec

        <!--Commons Codec rely on-->
        <dependency>
            <groupId>commons-codec</groupId>
            <artifactId>commons-codec</artifactId>
            <version>1.15</version>
        </dependency>
        byte[] encodeHeaderBytes = Base64.encodeBase64URLSafe(header.getBytes("UTF-8"));

Then convert the byte array into a string

		String encodeHeader = new String(encodeHeaderBytes);

At this point, you can try to output this string. Theoretically, it should be as follows, which is also the header of this JWT

		eyJhbGciOiJIUzI1NiJ9

The JWT official website debugger is debugged without error, and the JWT header can be parsed normally

load

First, let's have a JSON with content, as follows

{
	"sub":"psyduck "
}

After that, do the same processing as the header. The final output should be as follows

eyJzdWIiOiLlj6_ovr7puK0ifQ

Then use the head and load Splice as follows

        String s = encodeHeader+"."+encodeClaims;
        //Output result eyjhbgcioijiuzi1nij9 eyJzdWIiOiLlj6_ ovr7puK0ifQ

The debugging of the debugger on the JWT official website is correct, and the JWT header and load can be parsed normally

autograph

First of all, we can generate a complex string, or we can process it by ourselves

        String secret = "123456";//Common key

Then use HmacSHA256 to encrypt the previously spliced string and encode it with Base64URL

        String message = encodeHeader + "." + encodeClaims;
        Mac sha256_HMAC = Mac.getInstance("HmacSHA256");
        SecretKeySpec secret_key = new SecretKeySpec(secret.getBytes(), "HmacSHA256");
        sha256_HMAC.init(secret_key);
        String verifySignature = new String(Base64.encodeBase64URLSafe(sha256_HMAC.doFinal(message.getBytes())));

Finally, the header, payload and signature are passed After splicing, the following string is obtained

eyJhbGciOiJIUzI1NiJ9.eyJzdWIiOiLlj6_ovr7puK0ifQ.2AHwp9OhaBwj2uNlXTGSzyaIfym7hrA2_ubRx4E9xd4

Put it into the JWT official website, verify it and analyze it without error

answering question

Here are the problems I encountered when generating JWT manually
1. There is a small gap between base64 encryption header and official encryption
solve:
The official use is Base64URL encryption, not Base64 encryption
Base64URL encryption enhances the adaptability to the browser compared with Base64 encryption. When Base64 encryption is encrypted, the encryption of + is converted to - (subtraction symbol), and the encryption of / is converted to_ (underline) and remove the = (equal sign) at the end
2. The data is still different after using Base64URL encryption
solve:
The double quotation marks of the simulated JSON data are replaced with 'and replaced with "escape"
3. The signature character is completely wrong
solve:
The original method was to display the encrypted signature of HmacSHA256 directly in the form of toHexString (the encrypted byte array of HmacSHA256 cannot be displayed normally). Later, it was found that the official method was to encrypt this byte array with Base64URL, which was correct after modification
4. secret base64 encode under the official debugger (this problem wasted 2 hours of my life)
solve:
From the beginning to the end, I think the meaning of checking this option is, the meaning of this option is
Originally, my secret (salt) value was 123456. When checked, 123456 will be base64 encrypted, and then Base64URL encrypted as a secret. I believe most people think so.
However, after reproducing this operation in the code, I found that it is completely different from the official JWT signature.
So I have another guess. After checking this option, whether to no longer encrypt the base64URL of the last byte array. After verification, the guess is wrong.
After that, I tried many abnormal ideas and spent a lot of time. When I was about to give up, I thought of Baidu, so I Baidu. What does secret base64 encode on JWT official website mean? The following is the answer:
secret base64 encode on the official website of JWT means that the secret is regarded as generated by base64 encryption. First, base64decode it, and then use it as a secret for HmacSHA256 encryption. The test is correct.

        Base64 base64 = new Base64();
        byte[] secret = new Base64().encode("123456".getBytes("UTF-8"));//Complex key
        System.out.println("Base64 Encryption salt:" + new String(secret));
        //Base64 encryption salt: MTIzNDU2

        String message = encodeHeader + "." + encodeClaims;
        Mac sha256_HMAC = Mac.getInstance("HmacSHA256");
        SecretKeySpec secret_key = new SecretKeySpec(secret, "HmacSHA256");
        sha256_HMAC.init(secret_key);
        String verifySignature = new String(Base64.encodeBase64URLSafe(sha256_HMAC.doFinal(message.getBytes())));
        System.out.println("Base64 Encrypted salt final signature:" + verifySignature);
        //Base64 encryption salt final signature: V7TXJxLIij3gduj6b_8oGQ6K_RmA3kd43S8RrOB554s
        
        secret_key = new SecretKeySpec("123456".getBytes("UTF-8"),"HmacSHA256");
        sha256_HMAC.init(secret_key);
        verifySignature = new String(Base64.encodeBase64URLSafe(sha256_HMAC.doFinal(message.getBytes())));
        System.out.println("123456 Encrypted salt final signature:" + verifySignature);
        //123456 encryption salt final signature: 2AHwp9OhaBwj2uNlXTGSzyaIfym7hrA2_ubRx4E9xd4



Last updated on April 17, 2021
It's not easy to be original. If this article is helpful to you, please click to pay attention in the upper left corner ~ if there are any technical related problems, please contact me through comments for discussion, and I will reply accordingly and issue a single chapter to solve the problem within my ability

If there are any mistakes in this article, please point them out in the comments. Thank you very much. Please attach the source for reprint!
*Home page of personal blog: https://blog.csdn.net/yjrguxing ——Each of your concerns and comments means a lot to me

Keywords: Java jwt

Added by stennchau on Sat, 05 Mar 2022 03:01:18 +0200