1/*
2 * reserved comment block
3 * DO NOT REMOVE OR ALTER!
4 */
5/**
6 * Licensed to the Apache Software Foundation (ASF) under one
7 * or more contributor license agreements. See the NOTICE file
8 * distributed with this work for additional information
9 * regarding copyright ownership. The ASF licenses this file
10 * to you under the Apache License, Version 2.0 (the
11 * "License"); you may not use this file except in compliance
12 * with the License. You may obtain a copy of the License at
13 *
14 * http://www.apache.org/licenses/LICENSE-2.0
15 *
16 * Unless required by applicable law or agreed to in writing,
17 * software distributed under the License is distributed on an
18 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
19 * KIND, either express or implied. See the License for the
20 * specific language governing permissions and limitations
21 * under the License.
22 */
23package com.sun.org.apache.xml.internal.security.keys.content;
24
25import java.security.KeyFactory;
26import java.security.NoSuchAlgorithmException;
27import java.security.PublicKey;
28import java.security.spec.InvalidKeySpecException;
29import java.security.spec.X509EncodedKeySpec;
30
31import com.sun.org.apache.xml.internal.security.exceptions.XMLSecurityException;
32import com.sun.org.apache.xml.internal.security.utils.Constants;
33import com.sun.org.apache.xml.internal.security.utils.Signature11ElementProxy;
34import org.w3c.dom.Document;
35import org.w3c.dom.Element;
36
37/**
38 * Provides content model support for the <code>dsig11:DEREncodedKeyvalue</code> element.
39 *
40 * @author Brent Putman (putmanb@georgetown.edu)
41 */
42public class DEREncodedKeyValue extends Signature11ElementProxy implements KeyInfoContent {
43
44    /** JCA algorithm key types supported by this implementation. */
45    private static final String supportedKeyTypes[] = { "RSA", "DSA", "EC"};
46
47    /**
48     * Constructor DEREncodedKeyValue
49     *
50     * @param element
51     * @param BaseURI
52     * @throws XMLSecurityException
53     */
54    public DEREncodedKeyValue(Element element, String BaseURI) throws XMLSecurityException {
55        super(element, BaseURI);
56    }
57
58    /**
59     * Constructor DEREncodedKeyValue
60     *
61     * @param doc
62     * @param publicKey
63     * @throws XMLSecurityException
64     */
65    public DEREncodedKeyValue(Document doc, PublicKey publicKey) throws XMLSecurityException {
66        super(doc);
67
68        this.addBase64Text(getEncodedDER(publicKey));
69    }
70
71    /**
72     * Constructor DEREncodedKeyValue
73     *
74     * @param doc
75     * @param base64EncodedKey
76     */
77    public DEREncodedKeyValue(Document doc, byte[] encodedKey) {
78        super(doc);
79
80        this.addBase64Text(encodedKey);
81    }
82
83    /**
84     * Sets the <code>Id</code> attribute
85     *
86     * @param Id ID
87     */
88    public void setId(String id) {
89        if (id != null) {
90            this.constructionElement.setAttributeNS(null, Constants._ATT_ID, id);
91            this.constructionElement.setIdAttributeNS(null, Constants._ATT_ID, true);
92        } else {
93            this.constructionElement.removeAttributeNS(null, Constants._ATT_ID);
94        }
95    }
96
97    /**
98     * Returns the <code>Id</code> attribute
99     *
100     * @return the <code>Id</code> attribute
101     */
102    public String getId() {
103        return this.constructionElement.getAttributeNS(null, Constants._ATT_ID);
104    }
105
106    /** @inheritDoc */
107    public String getBaseLocalName() {
108        return Constants._TAG_DERENCODEDKEYVALUE;
109    }
110
111    /**
112     * Method getPublicKey
113     *
114     * @return the public key
115     * @throws XMLSecurityException
116     */
117    public PublicKey getPublicKey() throws XMLSecurityException {
118        byte[] encodedKey = getBytesFromTextChild();
119
120        // Iterate over the supported key types until one produces a public key.
121        for (String keyType : supportedKeyTypes) {
122            try {
123                KeyFactory keyFactory = KeyFactory.getInstance(keyType);
124                X509EncodedKeySpec keySpec = new X509EncodedKeySpec(encodedKey);
125                PublicKey publicKey = keyFactory.generatePublic(keySpec);
126                if (publicKey != null) {
127                    return publicKey;
128                }
129            } catch (NoSuchAlgorithmException e) {
130                // Do nothing, try the next type
131            } catch (InvalidKeySpecException e) {
132                // Do nothing, try the next type
133            }
134        }
135        throw new XMLSecurityException("DEREncodedKeyValue.UnsupportedEncodedKey");
136    }
137
138    /**
139     * Method getEncodedDER
140     *
141     * @return the public key
142     * @throws XMLSecurityException
143     */
144    protected byte[] getEncodedDER(PublicKey publicKey) throws XMLSecurityException {
145        try {
146            KeyFactory keyFactory = KeyFactory.getInstance(publicKey.getAlgorithm());
147            X509EncodedKeySpec keySpec = keyFactory.getKeySpec(publicKey, X509EncodedKeySpec.class);
148            return keySpec.getEncoded();
149        } catch (NoSuchAlgorithmException e) {
150            Object exArgs[] = { publicKey.getAlgorithm(), publicKey.getFormat(), publicKey.getClass().getName() };
151            throw new XMLSecurityException("DEREncodedKeyValue.UnsupportedPublicKey", exArgs, e);
152        } catch (InvalidKeySpecException e) {
153            Object exArgs[] = { publicKey.getAlgorithm(), publicKey.getFormat(), publicKey.getClass().getName() };
154            throw new XMLSecurityException("DEREncodedKeyValue.UnsupportedPublicKey", exArgs, e);
155        }
156    }
157
158}
159