001package com.nimbusds.jose.util;
002
003
004import java.nio.charset.Charset;
005import java.math.BigInteger;
006
007import net.jcip.annotations.Immutable;
008
009import net.minidev.json.JSONAware;
010import net.minidev.json.JSONValue;
011
012
013/**
014 * Base64-encoded object.
015 *
016 * @author Vladimir Dzhuvinov
017 */
018@Immutable
019public class Base64 implements JSONAware {
020
021
022        /**
023         * UTF-8 is the required character set for all JOSE + JWT objects.
024         */
025        public static final Charset CHARSET = Charset.forName("UTF-8");
026
027
028        /**
029         * The Base64 value.
030         */
031        private final String value;
032
033
034        /**
035         * Creates a new Base64-encoded object.
036         *
037         * @param base64 The Base64-encoded object value. The value is not 
038         *               validated for having characters from a Base64 
039         *               alphabet. Must not be {@code null}.
040         */
041        public Base64(final String base64) {
042
043                if (base64 == null) {
044
045                        throw new IllegalArgumentException("The Base64 value must not be null");
046                }
047
048                value = base64;
049        }
050
051
052        /**
053         * Decodes this Base64 object to a byte array.
054         *
055         * @return The resulting byte array.
056         */
057        public byte[] decode() {
058
059                return Base64Codec.decode(value);
060        }
061
062
063        /**
064         * Decodes this Base64 object to an unsigned big integer.
065         *
066         * <p>Same as {@code new BigInteger(1, base64.decode())}.
067         *
068         * @return The resulting big integer.
069         */
070        public BigInteger decodeToBigInteger() {
071
072                return new BigInteger(1, decode());
073        }
074
075
076        /**
077         * Decodes this Base64 object to a string.
078         *
079         * @return The resulting string, in the UTF-8 character set.
080         */
081        public String decodeToString() {
082
083                return new String(decode(), CHARSET);
084        }
085
086
087        /**
088         * Returns a JSON string representation of this object.
089         *
090         * @return The JSON string representation of this object.
091         */
092        @Override
093        public String toJSONString() {
094
095                return "\"" + JSONValue.escape(value) + "\"";
096        }
097
098
099        /**
100         * Returns a Base64 string representation of this object. The string 
101         * will be chunked into 76 character blocks separated by CRLF.
102         *
103         * @return The Base64 string representation, chunked into 76 character 
104         *         blocks separated by CRLF.
105         */
106        @Override
107        public String toString() {
108
109                return value;
110        }
111
112
113        /**
114         * Overrides {@code Object.hashCode()}.
115         *
116         * @return The object hash code.
117         */
118        @Override
119        public int hashCode() {
120
121                return value.hashCode();
122        }
123
124
125        /**
126         * Overrides {@code Object.equals()}.
127         *
128         * @param object The object to compare to.
129         *
130         * @return {@code true} if the objects have the same value, otherwise
131         *         {@code false}.
132         */
133        @Override
134        public boolean equals(final Object object) {
135
136                return object != null && 
137                       object instanceof Base64 && 
138                       this.toString().equals(object.toString());
139        }
140
141
142        /**
143         * Base64-encodes the specified byte array. 
144         *
145         * @param bytes The byte array to encode. Must not be {@code null}.
146         *
147         * @return The resulting Base64 object.
148         */
149        public static Base64 encode(final byte[] bytes) {
150
151                return new Base64(Base64Codec.encodeToString(bytes, false));
152        }
153
154
155        /**
156         * Base64-encodes the specified big integer, without the sign bit.
157         *
158         * @param bigInt The big integer to encode. Must not be {@code null}.
159         *
160         * @return The resulting Base64 object.
161         */
162        public static Base64 encode(final BigInteger bigInt) {
163
164                return encode(BigIntegerUtils.toBytesUnsigned(bigInt));
165        }
166
167
168        /**
169         * Base64-encodes the specified string.
170         *
171         * @param text The string to encode. Must be in the UTF-8 character set
172         *             and not {@code null}.
173         *
174         * @return The resulting Base64 object.
175         */
176        public static Base64 encode(final String text) {
177
178                return encode(text.getBytes(CHARSET));
179        }
180}