001/*
002 * nimbus-jose-jwt
003 *
004 * Copyright 2012-2016, Connect2id Ltd.
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.jose.jwk;
019
020
021import java.security.cert.X509Certificate;
022import java.text.ParseException;
023
024
025/**
026 * Enumeration of public key uses. Represents the {@code use} parameter in a
027 * JSON Web Key (JWK).
028 *
029 * <p>Public JWK use values:
030 *
031 * <ul>
032 *     <li>{@link #SIGNATURE sig}
033 *     <li>{@link #ENCRYPTION enc}
034 * </ul>
035 *
036 * @author Vladimir Dzhuvinov
037 * @version 2016-12-06
038 */
039public enum KeyUse {
040
041
042        /**
043         * Signature.
044         */
045        SIGNATURE("sig"),
046
047
048        /**
049         * Encryption.
050         */
051        ENCRYPTION("enc");
052
053
054        /**
055         * The public key use identifier.
056         */
057        private final String identifier;
058
059
060        /**
061         * Creates a new public key use with the specified identifier.
062         *
063         * @param identifier The public key use identifier. Must not be
064         *                   {@code null}.
065         */
066        KeyUse(final String identifier) {
067
068                if (identifier == null)
069                        throw new IllegalArgumentException("The key use identifier must not be null");
070
071                this.identifier = identifier;
072        }
073
074
075        /**
076         * Returns the identifier of this public key use.
077         *
078         * @return The identifier.
079         */
080        public String identifier() {
081
082                return identifier;
083        }
084
085
086        /**
087         * @see #identifier()
088         */
089        @Override
090        public String toString() {
091
092                return identifier();
093        }
094
095
096        /**
097         * Parses a public key use from the specified JWK {@code use} parameter
098         * value.
099         *
100         * @param s The string to parse. May be {@code null}.
101         *
102         * @return The public key use, {@code null} if none.
103         *
104         * @throws ParseException If the string couldn't be parsed to a valid
105         *                        public key use.
106         */
107        public static KeyUse parse(final String s)
108                throws ParseException {
109
110                if (s == null) {
111                        return null;
112                }
113
114                for (KeyUse use: KeyUse.values()) {
115
116                        if (s.equals(use.identifier)) {
117                                return use;
118                        }
119                }
120
121                throw new ParseException("Invalid JWK use: " + s, 0);
122        }
123        
124        
125        /**
126         * Infers the public key use of the specified X.509 certificate. Note
127         * that there is no standard algorithm for mapping PKIX key usage to
128         * JWK use. See RFC 2459, section 4.2.1.3, as well as the underlying
129         * code for the chosen algorithm to infer JWK use.
130         *
131         * @param cert The X.509 certificate. Must not be {@code null}.
132         *
133         * @return The public key use, {@code null} if the key use couldn't be
134         *         reliably determined.
135         */
136        public static KeyUse from(final X509Certificate cert) {
137                
138                if (cert.getKeyUsage() == null) {
139                        return null;
140                }
141                
142                // nonRepudiation
143                if (cert.getKeyUsage()[1]) {
144                        return SIGNATURE;
145                }
146                
147                // digitalSignature && keyEncipherment
148                // (e.g. RSA TLS certificate for authenticated encryption)
149                if (cert.getKeyUsage()[0] && cert.getKeyUsage()[2]) {
150                        return KeyUse.ENCRYPTION;
151                }
152                
153                // digitalSignature && keyAgreement
154                // (e.g. EC TLS certificate for authenticated encryption)
155                if (cert.getKeyUsage()[0] && cert.getKeyUsage()[4]) {
156                        return KeyUse.ENCRYPTION;
157                }
158                
159                // keyEncipherment || dataEncipherment || keyAgreement
160                if (cert.getKeyUsage()[2] || cert.getKeyUsage()[3] || cert.getKeyUsage()[4]) {
161                        return ENCRYPTION;
162                }
163                
164                // keyCertSign || cRLSign
165                if (cert.getKeyUsage()[5] || cert.getKeyUsage()[6]) {
166                        return SIGNATURE;
167                }
168                
169                return null;
170        }
171}