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