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 com.nimbusds.jose.HeaderParameterNames; 022 023import java.io.Serializable; 024import java.security.cert.X509Certificate; 025import java.text.ParseException; 026import java.util.Objects; 027 028 029/** 030 * Enumeration of public key uses. Represents the {@code use} parameter in a 031 * JSON Web Key (JWK). 032 * 033 * <p>Public JWK use values: 034 * 035 * <ul> 036 * <li>{@link #SIGNATURE sig} 037 * <li>{@link #ENCRYPTION enc} 038 * </ul> 039 * 040 * @author Vladimir Dzhuvinov 041 * @version 2019-10-03 042 */ 043public final class KeyUse implements Serializable { 044 045 046 private static final long serialVersionUID = 1L; 047 048 049 /** 050 * Signature. 051 */ 052 public static final KeyUse SIGNATURE = new KeyUse("sig"); 053 054 055 /** 056 * Encryption. 057 */ 058 public static final KeyUse ENCRYPTION = new KeyUse(HeaderParameterNames.ENCRYPTION_ALGORITHM); 059 060 061 /** 062 * The public key use identifier. 063 */ 064 private final String identifier; 065 066 067 /** 068 * Creates a new public key use with the specified identifier. 069 * 070 * @param identifier The public key use identifier. Must not be 071 * {@code null}. 072 */ 073 public KeyUse(final String identifier) { 074 075 if (identifier == null) 076 throw new IllegalArgumentException("The key use identifier must not be null"); 077 078 this.identifier = identifier; 079 } 080 081 082 /** 083 * Returns the identifier of this public key use. 084 * 085 * @return The identifier. 086 */ 087 public String identifier() { 088 089 return identifier; 090 } 091 092 093 /** 094 * @see #identifier() 095 */ 096 public String getValue() { 097 098 return identifier(); 099 } 100 101 102 /** 103 * @see #identifier() 104 */ 105 @Override 106 public String toString() { 107 108 return identifier(); 109 } 110 111 112 @Override 113 public boolean equals(Object o) { 114 if (this == o) return true; 115 if (!(o instanceof KeyUse)) return false; 116 KeyUse keyUse = (KeyUse) o; 117 return Objects.equals(identifier, keyUse.identifier); 118 } 119 120 121 @Override 122 public int hashCode() { 123 return Objects.hash(identifier); 124 } 125 126 127 /** 128 * Parses a public key use from the specified JWK {@code use} parameter 129 * value. 130 * 131 * @param s The string to parse. May be {@code null}. 132 * 133 * @return The public key use, {@code null} if none. 134 * 135 * @throws ParseException If the string couldn't be parsed to a valid 136 * public key use. 137 */ 138 public static KeyUse parse(final String s) 139 throws ParseException { 140 141 if (s == null) { 142 return null; 143 } 144 145 if (s.equals(SIGNATURE.identifier())) { 146 return SIGNATURE; 147 } 148 149 if (s.equals(ENCRYPTION.identifier())) { 150 return ENCRYPTION; 151 } 152 153 if (s.trim().isEmpty()) { 154 throw new ParseException("JWK use value must not be empty or blank", 0); 155 } 156 157 return new KeyUse(s); 158 } 159 160 161 /** 162 * Infers the public key use of the specified X.509 certificate. Note 163 * that there is no standard algorithm for mapping PKIX key usage to 164 * JWK use. See RFC 2459, section 4.2.1.3, as well as the underlying 165 * code for the chosen algorithm to infer JWK use. 166 * 167 * @param cert The X.509 certificate. Must not be {@code null}. 168 * 169 * @return The public key use, {@code null} if the key use couldn't be 170 * reliably determined. 171 */ 172 public static KeyUse from(final X509Certificate cert) { 173 174 if (cert.getKeyUsage() == null) { 175 return null; 176 } 177 178 // nonRepudiation 179 if (cert.getKeyUsage()[1]) { 180 return SIGNATURE; 181 } 182 183 // digitalSignature && keyEncipherment 184 // (e.g. RSA TLS certificate for authenticated encryption) 185 if (cert.getKeyUsage()[0] && cert.getKeyUsage()[2]) { 186 return KeyUse.ENCRYPTION; 187 } 188 189 // digitalSignature && keyAgreement 190 // (e.g. EC TLS certificate for authenticated encryption) 191 if (cert.getKeyUsage()[0] && cert.getKeyUsage()[4]) { 192 return KeyUse.ENCRYPTION; 193 } 194 195 // keyEncipherment || dataEncipherment || keyAgreement 196 if (cert.getKeyUsage()[2] || cert.getKeyUsage()[3] || cert.getKeyUsage()[4]) { 197 return ENCRYPTION; 198 } 199 200 // keyCertSign || cRLSign 201 if (cert.getKeyUsage()[5] || cert.getKeyUsage()[6]) { 202 return SIGNATURE; 203 } 204 205 return null; 206 } 207}