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 * Base64URL-encoded object.
015 *
016 * <p>Related specifications:
017 *
018 * <ul>
019 *     <li>RFC 4648.
020 * </ul>
021 *
022 * @author Vladimir Dzhuvinov
023 * @version $version$ (2013-03-20)
024 */
025@Immutable
026public class Base64URL implements JSONAware {
027
028
029        /**
030         * The Base64URL value.
031         */
032        private final String value;
033
034
035        /**
036         * Creates a new Base64URL-encoded object.
037         *
038         * @param base64URL The Base64URL-encoded object value. The value is 
039         *                  not validated for having characters from the 
040         *                  Base64URL alphabet. Must not be {@code null}.
041         */
042        public Base64URL(final String base64URL) {
043
044                if (base64URL == null) {
045
046                        throw new IllegalArgumentException("The Base64URL value must not be null");
047                }
048
049                value = base64URL;
050        }
051
052
053        /**
054         * Decodes this Base64URL object to a byte array.
055         *
056         * @return The resulting byte array.
057         */
058        public byte[] decode() {
059
060                return org.apache.commons.codec.binary.Base64.decodeBase64(value);
061        }
062
063
064        /**
065         * Decodes this Base64URL object to an unsigned big integer.
066         *
067         * <p>Same as {@code new BigInteger(1, base64url.decode())}.
068         *
069         * @return The resulting big integer.
070         */
071        public BigInteger decodeToBigInteger() {
072
073                return new BigInteger(1, decode());
074        }
075
076
077        /**
078         * Decodes this Base64URL object to a string.
079         *
080         * @return The resulting string, in the UTF-8 character set.
081         */
082        public String decodeToString() {
083
084                try {
085                        return new String(decode(), Base64.CHARSET);
086
087                } catch (UnsupportedEncodingException e) {
088
089                        // UTF-8 should always be supported
090                        return "";
091                }
092        }
093
094
095        /**
096         * Returns a JSON string representation of this object.
097         *
098         * @return The JSON string representation of this object.
099         */
100        @Override
101        public String toJSONString() {
102
103                return "\"" + JSONValue.escape(value) + "\"";
104        }
105
106
107        /**
108         * Returns a Base64URL string representation of this object.
109         *
110         * @return The Base64URL string representation.
111         */
112        @Override
113        public String toString() {
114
115                return value;
116        }
117
118
119        /**
120         * Overrides {@code Object.hashCode()}.
121         *
122         * @return The object hash code.
123         */
124        @Override
125        public int hashCode() {
126
127                return value.hashCode();
128        }
129
130
131        /**
132         * Overrides {@code Object.equals()}.
133         *
134         * @param object The object to compare to.
135         *
136         * @return {@code true} if the objects have the same value, otherwise
137         *         {@code false}.
138         */
139        @Override
140        public boolean equals(final Object object) {
141
142                return object != null && 
143                       object instanceof Base64URL && 
144                       this.toString().equals(object.toString());
145        }
146
147
148        /**
149         * Base64URL-encodes the specified byte array.
150         *
151         * @param bytes The byte array to encode. Must not be {@code null}.
152         *
153         * @return The resulting Base64URL object.
154         */
155        public static Base64URL encode(final byte[] bytes) {
156
157                return new Base64URL(org.apache.commons.codec.binary.Base64.encodeBase64URLSafeString(bytes));
158        }
159
160
161        /**
162         * Base64URL-encodes the specified big integer, without the sign bit.
163         *
164         * @param bigInt The big integer to encode. Must not be {@code null}.
165         *
166         * @return The resulting Base64URL object.
167         */
168        public static Base64URL encode(final BigInteger bigInt) {
169
170                return encode(BigIntegerUtils.toBytesUnsigned(bigInt));
171        }
172
173
174        /**
175         * Base64URL-encodes the specified string.
176         *
177         * @param text The string to encode. Must be in the UTF-8 character set
178         *             and not {@code null}.
179         *
180         * @return The resulting Base64URL object.
181         */
182        public static Base64URL encode(final String text) {
183
184                try {
185                        return encode(text.getBytes(Base64.CHARSET));
186
187                } catch (UnsupportedEncodingException e) {
188
189                        // UTF-8 should always be supported
190                        return null;
191                }
192        }
193}