1 /** 2 * Licensed to the Apache Software Foundation (ASF) under one 3 * or more contributor license agreements. See the NOTICE file 4 * distributed with this work for additional information 5 * regarding copyright ownership. The ASF licenses this file 6 * to you under the Apache License, Version 2.0 (the 7 * "License"); you may not use this file except in compliance 8 * with the License. You may obtain a copy of the License at 9 * 10 * http://www.apache.org/licenses/LICENSE-2.0 11 * 12 * Unless required by applicable law or agreed to in writing, 13 * software distributed under the License is distributed on an 14 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 15 * KIND, either express or implied. See the License for the 16 * specific language governing permissions and limitations 17 * under the License. 18 */ 19 20 package org.apache.wss4j.common.crypto; 21 22 import java.security.PublicKey; 23 24 import org.apache.wss4j.common.ext.WSSecurityException; 25 26 /** 27 * Represents the X.509 SubjectPublicKeyInfo for a public key, as specified 28 * in RFC3280/5280: 29 * <pre> 30 * SubjectPublicKeyInfo ::= SEQUENCE { 31 * algorithm AlgorithmIdentifier, 32 * subjectPublicKey BIT STRING } 33 * 34 * AlgorithmIdentifier ::= SEQUENCE { 35 * algorithm OBJECT IDENTIFIER, 36 * parameters ANY DEFINED BY algorithm OPTIONAL } 37 * </pre> 38 */ 39 public class X509SubjectPublicKeyInfo extends DERDecoder { 40 41 /** 42 * Construct a SubjectPublicKeyInfo for the given public key. 43 * 44 * @param key the public key. 45 * @throws WSSecurityException if the public key encoding format is 46 * not X.509 or the encoding is null. 47 */ 48 public X509SubjectPublicKeyInfo(PublicKey key) throws WSSecurityException { 49 super(key.getEncoded()); 50 if (!("X.509".equalsIgnoreCase(key.getFormat()) 51 || "X509".equalsIgnoreCase(key.getFormat()))) { 52 throw new WSSecurityException( 53 WSSecurityException.ErrorCode.UNSUPPORTED_SECURITY_TOKEN, 54 "noSKIHandling", 55 new Object[] {"Support for X.509-encoded public keys only"} 56 ); 57 } 58 } 59 60 /** 61 * Construct a SubjectPublicKeyInfo for the given X.509-encoded public key. 62 * 63 * @param x509EncodedPublicKey the public key, in X.509 DER-encoding. 64 * @throws WSSecurityException if the encoded public key is null. 65 */ 66 public X509SubjectPublicKeyInfo(byte[] x509EncodedPublicKey) throws WSSecurityException { 67 super(x509EncodedPublicKey); 68 } 69 70 /** 71 * Get the subjectPublicKey element of the SubjectPublicKeyInfo. 72 * 73 * @return the X.509-encoded subjectPublicKey bit string. 74 * @throws WSSecurityException the DER-encoding is invalid. 75 */ 76 public byte[] getSubjectPublicKey() throws WSSecurityException { 77 reset(); 78 expect(TYPE_SEQUENCE); // SubjectPublicKeyInfo SEQUENCE 79 getLength(); 80 // Could enforce the max length of this sequence, but not actually 81 // necessary for our purposes, so be forgiving and simply ignore. 82 expect(TYPE_SEQUENCE); // algorithm AlgorithmIdentifier SEQUENCE 83 int algIDlen = getLength(); 84 if (algIDlen < 0) { 85 // Unsupported indefinite-length 86 throw new WSSecurityException( 87 WSSecurityException.ErrorCode.UNSUPPORTED_SECURITY_TOKEN, 88 "noSKIHandling", 89 new Object[] {"Unsupported X.509 public key format"} 90 ); 91 } 92 skip(algIDlen); // AlgorithmIdentifier contents 93 expect(TYPE_BIT_STRING); // subjectPublicKey BIT STRING 94 int keyLen = getLength() - 1; 95 if (keyLen < 0) { 96 // Invalid BIT STRING length 97 throw new WSSecurityException( 98 WSSecurityException.ErrorCode.UNSUPPORTED_SECURITY_TOKEN, 99 "noSKIHandling", 100 new Object[] {"Invalid X.509 public key format"} 101 ); 102 } 103 skip(1); // number unused bits 104 // DER-encoding guarantees unused bits should be 0 105 106 return getBytes(keyLen); 107 } 108 }