001package com.nimbusds.openid.connect.sdk.id;
002
003
004import java.net.URI;
005import java.nio.charset.Charset;
006import java.security.Provider;
007
008import com.nimbusds.oauth2.sdk.id.Subject;
009import net.jcip.annotations.ThreadSafe;
010import org.apache.commons.lang3.tuple.Pair;
011
012
013/**
014 * Encoder and decoder of pairwise subject identifiers. The encoder algorithms
015 * must be deterministic, to ensure a given set of inputs always produces an
016 * identical pairwise subject identifier.
017 *
018 * <p>Decoding pairwise subject identifiers is optional, and is implemented by
019 * algorithms that supported reversal (typically with encryption-based codecs).
020 * Hash-based codecs don't support reversal.
021 *
022 * <p>Codec implementations thread-safe.
023 *
024 * <p>Related specifications:
025 *
026 * <ul>
027 *     <li>OpenID Connect Core 1.0, section 8.1.
028 * </ul>
029 */
030@ThreadSafe
031public abstract class PairwiseSubjectCodec {
032
033
034        /**
035         * The charset (UTF-8) for string to byte conversions.
036         */
037        public static final Charset CHARSET = Charset.forName("UTF-8");
038
039
040        /**
041         * The salt.
042         */
043        private final byte[] salt;
044
045
046        /**
047         * The security provider.
048         */
049        private Provider provider;
050
051
052        /**
053         * Creates a new codec for pairwise subject identifiers.
054         *
055         * @param salt The salt, {@code null} if not required.
056         */
057        public PairwiseSubjectCodec(byte[] salt) {
058
059                this.salt = salt;
060        }
061
062
063        /**
064         * Returns the salt.
065         *
066         * @return The salt, {@code null} if not required.
067         */
068        public byte[] getSalt() {
069                return salt;
070        }
071
072
073        /**
074         * Gets the security provider for cryptographic operations.
075         *
076         * @return The security provider, {@code null} if not specified
077         *         (implies the default one).
078         */
079        public Provider getProvider() {
080                return provider;
081        }
082
083
084        /**
085         * Sets the security provider for cryptographic operations.
086         *
087         * @param provider The security provider, {@code null} if not specified
088         *                 (implies the default one).
089         */
090        public void setProvider(Provider provider) {
091                this.provider = provider;
092        }
093
094
095        /**
096         * Encodes a new pairwise subject identifier from the specified sector
097         * identifier URI and local subject.
098         *
099         * @param sectorURI The sector identifier URI. Its scheme should be
100         *                  "https", must include a host portion and must not
101         *                  be {@code null}.
102         * @param localSub  The local subject identifier. Must not be
103         *                  {@code null}.
104         *
105         * @return The pairwise subject identifier.
106         */
107        public Subject encode(final URI sectorURI, final Subject localSub) {
108
109                return encode(new SectorID(sectorURI), localSub);
110        }
111
112
113        /**
114         * Encodes a new pairwise subject identifier from the specified sector
115         * identifier and local subject.
116         *
117         * @param sectorID The sector identifier. Must not be
118         *                         {@code null}.
119         * @param localSub         The local subject identifier. Must not be
120         *                         {@code null}.
121         *
122         * @return The pairwise subject identifier.
123         */
124        public abstract Subject encode(final SectorID sectorID, final Subject localSub);
125
126
127        /**
128         * Decodes the specified pairwise subject identifier to produce the
129         * matching sector identifier and local subject. Throws a
130         * {@link UnsupportedOperationException}. Codecs that support pairwise
131         * subject identifier reversal should override this method.
132         *
133         * @param pairwiseSubject The pairwise subject identifier. Must be
134         *                        valid and not {@code null}.
135         *
136         * @return The matching sector identifier and local subject.
137         *
138         * @throws InvalidPairwiseSubjectException If the pairwise subject is
139         *                                         invalid.
140         */
141        public Pair<SectorID,Subject> decode(final Subject pairwiseSubject)
142                throws InvalidPairwiseSubjectException {
143
144                throw new UnsupportedOperationException("Pairwise subject decoding is not supported");
145        }
146}