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