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}