001package com.nimbusds.openid.connect.sdk.id;
002
003
004import java.security.MessageDigest;
005import java.security.NoSuchAlgorithmException;
006
007import com.nimbusds.jose.util.Base64URL;
008import com.nimbusds.oauth2.sdk.id.Subject;
009import net.jcip.annotations.ThreadSafe;
010
011
012/**
013 * SHA-256 based encoder of pairwise subject identifiers. Reversal is not
014 * supported.
015 *
016 * <p>Algorithm:
017 *
018 * <pre>
019 * sub = SHA-256 ( sector_id || local_sub || salt )
020 * </pre>
021 *
022 * <p>Related specifications:
023 *
024 * <ul>
025 *     <li>OpenID Connect Core 1.0, section 8.1.
026 * </ul>
027 */
028@ThreadSafe
029public class HashBasedPairwiseSubjectCodec extends PairwiseSubjectCodec {
030
031
032        /**
033         * The hashing algorithm.
034         */
035        public static final String HASH_ALGORITHM = "SHA-256";
036
037
038        /**
039         * Creates a new hash-based codec for pairwise subject identifiers.
040         *
041         * @param salt The salt, must not be {@code null}.
042         */
043        public HashBasedPairwiseSubjectCodec(final byte[] salt) {
044                super(salt);
045                if (salt == null) {
046                        throw new IllegalArgumentException("The salt must not be null");
047                }
048        }
049
050
051        /**
052         * Creates a new hash-based codec for pairwise subject identifiers.
053         *
054         * @param salt The salt, must not be {@code null}.
055         */
056        public HashBasedPairwiseSubjectCodec(final Base64URL salt) {
057                super(salt.decode());
058        }
059
060
061        @Override
062        public Subject encode(final SectorID sectorID, final Subject localSub) {
063
064                MessageDigest sha256;
065                try {
066                        if (getProvider() != null) {
067                                sha256 = MessageDigest.getInstance(HASH_ALGORITHM, getProvider());
068                        } else {
069                                sha256 = MessageDigest.getInstance(HASH_ALGORITHM);
070                        }
071                } catch (NoSuchAlgorithmException e) {
072                        throw new RuntimeException(e.getMessage(), e);
073                }
074
075                sha256.update(sectorID.getValue().getBytes(CHARSET));
076                sha256.update(localSub.getValue().getBytes(CHARSET));
077                byte[] hash = sha256.digest(getSalt());
078
079                return new Subject(Base64URL.encode(hash).toString());
080        }
081}