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.oauth2.sdk.pkce;
019
020
021import java.security.MessageDigest;
022import java.security.NoSuchAlgorithmException;
023
024import com.nimbusds.jose.util.Base64URL;
025import com.nimbusds.oauth2.sdk.id.Identifier;
026
027
028/**
029 * Authorisation code challenge.
030 *
031 * <p>Related specifications:
032 *
033 * <ul>
034 *     <li>Proof Key for Code Exchange by OAuth Public Clients (RFC 7636).
035 * </ul>
036 */
037public class CodeChallenge extends Identifier {
038        
039
040        /**
041         * Creates a new code challenge with the specified value.
042         *
043         * @param value The code challenge value. Must not be {@code null} or
044         *              empty string.
045         */
046        public CodeChallenge(final String value) {
047                super(value);
048        }
049
050
051        /**
052         * Computes the code challenge using the specified method and verifier.
053         *
054         * @param method       The code challenge method. Must be supported and
055         *                     not {@code null}.
056         * @param codeVerifier The code verifier. Must not be {@code null}.
057         *
058         * @return The computed code challenge.
059         */
060        public static CodeChallenge compute(final CodeChallengeMethod method, final CodeVerifier codeVerifier) {
061
062                if (CodeChallengeMethod.PLAIN.equals(method)) {
063                        return new CodeChallenge(codeVerifier.getValue());
064                }
065
066                if (CodeChallengeMethod.S256.equals(method)) {
067
068                        MessageDigest md;
069
070                        try {
071                                md = MessageDigest.getInstance("SHA-256");
072                        } catch (NoSuchAlgorithmException e) {
073                                throw new IllegalStateException(e.getMessage());
074                        }
075
076                        byte[] hash = md.digest(codeVerifier.getValueBytes());
077
078                        return new CodeChallenge(Base64URL.encode(hash).toString());
079                }
080
081                throw new IllegalArgumentException("Unsupported code challenge method: " + method);
082        }
083}