001package com.nimbusds.openid.connect.sdk.claims;
002
003
004import java.nio.charset.Charset;
005import java.security.MessageDigest;
006import java.security.NoSuchAlgorithmException;
007import java.util.Arrays;
008
009import com.nimbusds.jose.JWSAlgorithm;
010import com.nimbusds.jose.util.Base64URL;
011
012import com.nimbusds.oauth2.sdk.id.Identifier;
013
014
015/**
016 * The base class for SHA-2 based claims.
017 */
018public abstract class HashClaim extends Identifier {
019
020
021        /**
022         * Creates a new SHA-2 based claim with the specified value.
023         *
024         * @param value The claim value. Must not be {@code null}.
025         */
026        protected HashClaim(final String value) {
027
028                super(value);
029        }
030
031
032        /**
033         * Gets the matching SHA-2 message digest for the specified JSON Web
034         * Signature (JWS) algorithm.
035         *
036         * @param alg The JWS algorithm. Must not be {@code null}.
037         *
038         * @return The SHA-2 message digest, {@code null} if the JWS algorithm
039         *         or its corresponding SHA-2 message digest are not supported.
040         */
041        public static MessageDigest getMessageDigestInstance(final JWSAlgorithm alg) {
042
043                String mdAlg;
044
045                if (alg.equals(JWSAlgorithm.HS256) ||
046                    alg.equals(JWSAlgorithm.RS256) ||
047                    alg.equals(JWSAlgorithm.ES256) ||
048                    alg.equals(JWSAlgorithm.PS256)    ) {
049
050                        mdAlg = "SHA-256";
051
052                } else if (alg.equals(JWSAlgorithm.HS384) ||
053                           alg.equals(JWSAlgorithm.RS384) ||
054                           alg.equals(JWSAlgorithm.ES384) ||
055                           alg.equals(JWSAlgorithm.PS384)    ) {
056
057                        mdAlg = "SHA-384";
058
059                } else if (alg.equals(JWSAlgorithm.HS512) ||
060                           alg.equals(JWSAlgorithm.RS512) ||
061                           alg.equals(JWSAlgorithm.ES512) ||
062                           alg.equals(JWSAlgorithm.PS512)    ) {
063
064                        mdAlg = "SHA-512";
065
066                } else {
067                        // unsupported JWS alg
068                        return null;
069                }
070
071                try {
072                        return MessageDigest.getInstance(mdAlg);
073
074                } catch (NoSuchAlgorithmException e) {
075
076                        // unsupported SHA-2 alg
077                        return null;
078                }
079        }
080
081
082        /**
083         * Computes the SHA-2 claim value for the specified identifier.
084         *
085         * @param identifier The identifier, typically an authorisation code or
086         *                   an access token.  Must not be {@code null}.
087         * @param alg        The reference JSON Web Signature (JWS) algorithm.
088         *                   Must not be {@code null}.
089         *
090         * @return The matching (truncated to first half) SHA-2 claim value,
091         *         or {@code null} if the JWS algorithm or its corresponding
092         *         SHA-2 message digest are not supported.
093         */
094        public static String computeValue(final Identifier identifier, final JWSAlgorithm alg) {
095
096                MessageDigest md = getMessageDigestInstance(alg);
097
098                if (md == null)
099                        return null;
100
101                md.update(identifier.getValue().getBytes(Charset.forName("US-ASCII")));
102
103                byte[] hash = md.digest();
104
105                byte[] firstHalf = Arrays.copyOf(hash, hash.length / 2);
106
107                return Base64URL.encode(firstHalf).toString();
108        }
109}