001/*
002 * oauth2-oidc-sdk
003 *
004 * Copyright 2012-2016, Connect2id Ltd and contributors.
005 *
006 * Licensed under the Apache License, Version 2.0 (the "License"); you may not use
007 * this file except in compliance with the License. You may obtain a copy of the
008 * License at
009 *
010 *    http://www.apache.org/licenses/LICENSE-2.0
011 *
012 * Unless required by applicable law or agreed to in writing, software distributed
013 * under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
014 * CONDITIONS OF ANY KIND, either express or implied. See the License for the
015 * specific language governing permissions and limitations under the License.
016 */
017
018package com.nimbusds.openid.connect.sdk.claims;
019
020
021import java.nio.charset.Charset;
022import java.security.MessageDigest;
023import java.security.NoSuchAlgorithmException;
024import java.util.Arrays;
025
026import com.nimbusds.jose.JWSAlgorithm;
027import com.nimbusds.jose.util.Base64URL;
028
029import com.nimbusds.oauth2.sdk.id.Identifier;
030
031
032/**
033 * The base class for SHA-2 based claims.
034 */
035public abstract class HashClaim extends Identifier {
036
037
038        /**
039         * Creates a new SHA-2 based claim with the specified value.
040         *
041         * @param value The claim value. Must not be {@code null}.
042         */
043        protected HashClaim(final String value) {
044
045                super(value);
046        }
047
048
049        /**
050         * Gets the matching SHA-2 message digest for the specified JSON Web
051         * Signature (JWS) algorithm.
052         *
053         * @param alg The JWS algorithm. Must not be {@code null}.
054         *
055         * @return The SHA-2 message digest, {@code null} if the JWS algorithm
056         *         or its corresponding SHA-2 message digest are not supported.
057         */
058        public static MessageDigest getMessageDigestInstance(final JWSAlgorithm alg) {
059
060                String mdAlg;
061
062                if (alg.equals(JWSAlgorithm.HS256) ||
063                    alg.equals(JWSAlgorithm.RS256) ||
064                    alg.equals(JWSAlgorithm.ES256) ||
065                    alg.equals(JWSAlgorithm.PS256)    ) {
066
067                        mdAlg = "SHA-256";
068
069                } else if (alg.equals(JWSAlgorithm.HS384) ||
070                           alg.equals(JWSAlgorithm.RS384) ||
071                           alg.equals(JWSAlgorithm.ES384) ||
072                           alg.equals(JWSAlgorithm.PS384)    ) {
073
074                        mdAlg = "SHA-384";
075
076                } else if (alg.equals(JWSAlgorithm.HS512) ||
077                           alg.equals(JWSAlgorithm.RS512) ||
078                           alg.equals(JWSAlgorithm.ES512) ||
079                           alg.equals(JWSAlgorithm.PS512)    ) {
080
081                        mdAlg = "SHA-512";
082
083                } else {
084                        // unsupported JWS alg
085                        return null;
086                }
087
088                try {
089                        return MessageDigest.getInstance(mdAlg);
090
091                } catch (NoSuchAlgorithmException e) {
092
093                        // unsupported SHA-2 alg
094                        return null;
095                }
096        }
097
098
099        /**
100         * Computes the SHA-2 claim value for the specified identifier.
101         *
102         * @param identifier The identifier, typically an authorisation code or
103         *                   an access token.  Must not be {@code null}.
104         * @param alg        The reference JSON Web Signature (JWS) algorithm.
105         *                   Must not be {@code null}.
106         *
107         * @return The matching (truncated to first half) SHA-2 claim value,
108         *         or {@code null} if the JWS algorithm or its corresponding
109         *         SHA-2 message digest are not supported.
110         */
111        public static String computeValue(final Identifier identifier, final JWSAlgorithm alg) {
112
113                MessageDigest md = getMessageDigestInstance(alg);
114
115                if (md == null)
116                        return null;
117
118                md.update(identifier.getValue().getBytes(Charset.forName("US-ASCII")));
119
120                byte[] hash = md.digest();
121
122                byte[] firstHalf = Arrays.copyOf(hash, hash.length / 2);
123
124                return Base64URL.encode(firstHalf).toString();
125        }
126}