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