001package com.nimbusds.jose.util;
002
003
004import java.io.UnsupportedEncodingException;
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 * @version $version$ (2013-03-21)
018 */
019@Immutable
020public class Base64 implements JSONAware {
021
022
023        /**
024         * UTF-8 is the required character set for all JOSE + JWT objects.
025         */
026        public static final String CHARSET = "utf-8";
027
028
029        /**
030         * The Base64 value.
031         */
032        private final String value;
033
034
035        /**
036         * Creates a new Base64-encoded object.
037         *
038         * @param base64 The Base64-encoded object value. The value is not 
039         *               validated for having characters from a Base64 
040         *               alphabet. Must not be {@code null}.
041         */
042        public Base64(final String base64) {
043
044                if (base64 == null) {
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 org.apache.commons.codec.binary.Base64.decodeBase64(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                try {
084                        return new String(decode(), CHARSET);
085
086                } catch (UnsupportedEncodingException e) {
087
088                        // UTF-8 should always be supported
089                        return "";
090                }
091        }
092
093
094        /**
095         * Returns a JSON string representation of this object.
096         *
097         * @return The JSON string representation of this object.
098         */
099        @Override
100        public String toJSONString() {
101
102                return "\"" + JSONValue.escape(value) + "\"";
103        }
104
105
106        /**
107         * Returns a Base64 string representation of this object. The string 
108         * will be chunked into 76 character blocks separated by CRLF.
109         *
110         * @return The Base64 string representation, chunked into 76 character 
111         *         blocks separated by CRLF.
112         */
113        @Override
114        public String toString() {
115
116                return value;
117        }
118
119
120        /**
121         * Overrides {@code Object.hashCode()}.
122         *
123         * @return The object hash code.
124         */
125        @Override
126        public int hashCode() {
127
128                return value.hashCode();
129        }
130
131
132        /**
133         * Overrides {@code Object.equals()}.
134         *
135         * @param object The object to compare to.
136         *
137         * @return {@code true} if the objects have the same value, otherwise
138         *         {@code false}.
139         */
140        @Override
141        public boolean equals(final Object object) {
142
143                return object != null && 
144                       object instanceof Base64 && 
145                       this.toString().equals(object.toString());
146        }
147
148
149        /**
150         * Base64-encodes the specified byte array. 
151         *
152         * @param bytes The byte array to encode. Must not be {@code null}.
153         *
154         * @return The resulting Base64 object.
155         */
156        public static Base64 encode(final byte[] bytes) {
157
158                return new Base64(org.apache.commons.codec.binary.Base64.encodeBase64String(bytes));
159        }
160
161
162        /**
163         * Base64-encodes the specified big integer, without the sign bit.
164         *
165         * @param bigInt The big integer to encode. Must not be {@code null}.
166         *
167         * @return The resulting Base64 object.
168         */
169        public static Base64 encode(final BigInteger bigInt) {
170
171                return encode(BigIntegerUtils.toBytesUnsigned(bigInt));
172        }
173
174
175        /**
176         * Base64-encodes the specified string.
177         *
178         * @param text The string to encode. Must be in the UTF-8 character set
179         *             and not {@code null}.
180         *
181         * @return The resulting Base64 object.
182         */
183        public static Base64 encode(final String text) {
184
185                try {
186                        return encode(text.getBytes(CHARSET));
187
188                } catch (UnsupportedEncodingException e) {
189
190                        // UTF-8 should always be supported
191                        return null;
192                }
193        }
194}