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 }