1
16 package io.jsonwebtoken.impl;
17
18 public class Base64UrlCodec extends AbstractTextCodec {
19
20 @Override
21 public String encode(byte[] data) {
22 String base64Text = TextCodec.BASE64.encode(data);
23 byte[] bytes = base64Text.getBytes(US_ASCII);
24
25
26 bytes = removePadding(bytes);
27
28
29 for (int i = 0; i < bytes.length; i++) {
30 if (bytes[i] == '+') {
31 bytes[i] = '-';
32 } else if (bytes[i] == '/') {
33 bytes[i] = '_';
34 }
35 }
36
37 return new String(bytes, US_ASCII);
38 }
39
40 protected byte[] removePadding(byte[] bytes) {
41
42 byte[] result = bytes;
43
44 int paddingCount = 0;
45 for (int i = bytes.length - 1; i > 0; i--) {
46 if (bytes[i] == '=') {
47 paddingCount++;
48 } else {
49 break;
50 }
51 }
52 if (paddingCount > 0) {
53 result = new byte[bytes.length - paddingCount];
54 System.arraycopy(bytes, 0, result, 0, bytes.length - paddingCount);
55 }
56
57 return result;
58 }
59
60 @Override
61 public byte[] decode(String encoded) {
62 char[] chars = encoded.toCharArray();
63
64
65 chars = ensurePadding(chars);
66
67
68 for (int i = 0; i < chars.length; i++) {
69 if (chars[i] == '-') {
70 chars[i] = '+';
71 } else if (chars[i] == '_') {
72 chars[i] = '/';
73 }
74 }
75
76 String base64Text = new String(chars);
77
78 return TextCodec.BASE64.decode(base64Text);
79 }
80
81 protected char[] ensurePadding(char[] chars) {
82
83 char[] result = chars;
84
85 int paddingCount = 0;
86
87
88 int remainder = chars.length % 4;
89 if (remainder == 2 || remainder == 3) {
90 paddingCount = 4 - remainder;
91 }
92
93 if (paddingCount > 0) {
94 result = new char[chars.length + paddingCount];
95 System.arraycopy(chars, 0, result, 0, chars.length);
96 for (int i = 0; i < paddingCount; i++) {
97 result[chars.length + i] = '=';
98 }
99 }
100
101 return result;
102 }
103
104 }
105