272 lines · 10.2 KB · Java
RawDownload
/* * reserved comment block * DO NOT REMOVE OR ALTER! *//* * Copyright 2005 The Apache Software Foundation. * *  Licensed under the Apache License, Version 2.0 (the "License"); *  you may not use this file except in compliance with the License. *  You may obtain a copy of the License at * *      http://www.apache.org/licenses/LICENSE-2.0 * *  Unless required by applicable law or agreed to in writing, software *  distributed under the License is distributed on an "AS IS" BASIS, *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. *  See the License for the specific language governing permissions and *  limitations under the License. * *//* * Copyright (c) 2005, 2008, Oracle and/or its affiliates. All rights reserved. *//* * $Id: DOMKeyValue.java,v 1.2 2008/07/24 15:20:32 mullan Exp $ */package org.jcp.xml.dsig.internal.dom; import javax.xml.crypto.*;import javax.xml.crypto.dom.DOMCryptoContext;import javax.xml.crypto.dsig.*;import javax.xml.crypto.dsig.keyinfo.KeyValue; import java.security.KeyException;import java.security.KeyFactory;import java.security.NoSuchAlgorithmException;import java.security.PublicKey;import java.security.interfaces.DSAParams;import java.security.interfaces.DSAPublicKey;import java.security.interfaces.RSAPublicKey;import java.security.spec.DSAPublicKeySpec;import java.security.spec.InvalidKeySpecException;import java.security.spec.KeySpec;import java.security.spec.RSAPublicKeySpec;import org.w3c.dom.Document;import org.w3c.dom.Element;import org.w3c.dom.Node; /** * DOM-based implementation of KeyValue. * * @author Sean Mullan */public final class DOMKeyValue extends DOMStructure implements KeyValue {     private KeyFactory rsakf, dsakf;    private PublicKey publicKey;    private javax.xml.crypto.dom.DOMStructure externalPublicKey;     // DSAKeyValue CryptoBinaries    private DOMCryptoBinary p, q, g, y, j, seed, pgen;     // RSAKeyValue CryptoBinaries    private DOMCryptoBinary modulus, exponent;     public DOMKeyValue(PublicKey key)  throws KeyException {        if (key == null) {            throw new NullPointerException("key cannot be null");        }        this.publicKey = key;        if (key instanceof DSAPublicKey) {            DSAPublicKey dkey = (DSAPublicKey) key;            DSAParams params = dkey.getParams();            p = new DOMCryptoBinary(params.getP());            q = new DOMCryptoBinary(params.getQ());            g = new DOMCryptoBinary(params.getG());            y = new DOMCryptoBinary(dkey.getY());        } else if (key instanceof RSAPublicKey) {            RSAPublicKey rkey = (RSAPublicKey) key;            exponent = new DOMCryptoBinary(rkey.getPublicExponent());            modulus = new DOMCryptoBinary(rkey.getModulus());        } else {            throw new KeyException("unsupported key algorithm: " +                key.getAlgorithm());        }    }     /**     * Creates a <code>DOMKeyValue</code> from an element.     *     * @param kvElem a KeyValue element     */    public DOMKeyValue(Element kvElem) throws MarshalException {        Element kvtElem = DOMUtils.getFirstChildElement(kvElem);        if (kvtElem.getLocalName().equals("DSAKeyValue")) {            publicKey = unmarshalDSAKeyValue(kvtElem);        } else if (kvtElem.getLocalName().equals("RSAKeyValue")) {            publicKey = unmarshalRSAKeyValue(kvtElem);        } else {            publicKey = null;            externalPublicKey = new javax.xml.crypto.dom.DOMStructure(kvtElem);        }    }     public PublicKey getPublicKey() throws KeyException {        if (publicKey == null) {            throw new KeyException("can't convert KeyValue to PublicKey");        } else {            return publicKey;        }    }     public void marshal(Node parent, String dsPrefix, DOMCryptoContext context)        throws MarshalException {        Document ownerDoc = DOMUtils.getOwnerDocument(parent);         // create KeyValue element        Element kvElem = DOMUtils.createElement            (ownerDoc, "KeyValue", XMLSignature.XMLNS, dsPrefix);        marshalPublicKey(kvElem, ownerDoc, dsPrefix, context);         parent.appendChild(kvElem);    }     private void marshalPublicKey(Node parent, Document doc, String dsPrefix,        DOMCryptoContext context) throws MarshalException {        if (publicKey != null) {            if (publicKey instanceof DSAPublicKey) {                // create and append DSAKeyValue element                marshalDSAPublicKey(parent, doc, dsPrefix, context);            } else if (publicKey instanceof RSAPublicKey) {                // create and append RSAKeyValue element                marshalRSAPublicKey(parent, doc, dsPrefix, context);            } else {                throw new MarshalException(publicKey.getAlgorithm() +                    " public key algorithm not supported");            }        } else {            parent.appendChild(externalPublicKey.getNode());        }    }     private void marshalDSAPublicKey(Node parent, Document doc,        String dsPrefix, DOMCryptoContext context) throws MarshalException {        Element dsaElem = DOMUtils.createElement            (doc, "DSAKeyValue", XMLSignature.XMLNS, dsPrefix);        // parameters J, Seed & PgenCounter are not included        Element pElem = DOMUtils.createElement            (doc, "P", XMLSignature.XMLNS, dsPrefix);        Element qElem = DOMUtils.createElement            (doc, "Q", XMLSignature.XMLNS, dsPrefix);        Element gElem = DOMUtils.createElement            (doc, "G", XMLSignature.XMLNS, dsPrefix);        Element yElem = DOMUtils.createElement            (doc, "Y", XMLSignature.XMLNS, dsPrefix);        p.marshal(pElem, dsPrefix, context);        q.marshal(qElem, dsPrefix, context);        g.marshal(gElem, dsPrefix, context);        y.marshal(yElem, dsPrefix, context);        dsaElem.appendChild(pElem);        dsaElem.appendChild(qElem);        dsaElem.appendChild(gElem);        dsaElem.appendChild(yElem);        parent.appendChild(dsaElem);    }     private void marshalRSAPublicKey(Node parent, Document doc,        String dsPrefix, DOMCryptoContext context) throws MarshalException {        Element rsaElem = DOMUtils.createElement            (doc, "RSAKeyValue", XMLSignature.XMLNS, dsPrefix);        Element modulusElem = DOMUtils.createElement            (doc, "Modulus", XMLSignature.XMLNS, dsPrefix);        Element exponentElem = DOMUtils.createElement            (doc, "Exponent", XMLSignature.XMLNS, dsPrefix);        modulus.marshal(modulusElem, dsPrefix, context);        exponent.marshal(exponentElem, dsPrefix, context);        rsaElem.appendChild(modulusElem);        rsaElem.appendChild(exponentElem);        parent.appendChild(rsaElem);    }     private DSAPublicKey unmarshalDSAKeyValue(Element kvtElem)        throws MarshalException {        if (dsakf == null) {            try {                dsakf = KeyFactory.getInstance("DSA");            } catch (NoSuchAlgorithmException e) {                throw new RuntimeException("unable to create DSA KeyFactory: " +                    e.getMessage());            }        }        Element curElem = DOMUtils.getFirstChildElement(kvtElem);        // check for P and Q        if (curElem.getLocalName().equals("P")) {            p = new DOMCryptoBinary(curElem.getFirstChild());            curElem = DOMUtils.getNextSiblingElement(curElem);            q = new DOMCryptoBinary(curElem.getFirstChild());            curElem = DOMUtils.getNextSiblingElement(curElem);        }        if (curElem.getLocalName().equals("G")) {            g = new DOMCryptoBinary(curElem.getFirstChild());            curElem = DOMUtils.getNextSiblingElement(curElem);        }        y = new DOMCryptoBinary(curElem.getFirstChild());        curElem = DOMUtils.getNextSiblingElement(curElem);        if (curElem != null && curElem.getLocalName().equals("J")) {            j = new DOMCryptoBinary(curElem.getFirstChild());            curElem = DOMUtils.getNextSiblingElement(curElem);        }        if (curElem != null) {            seed = new DOMCryptoBinary(curElem.getFirstChild());            curElem = DOMUtils.getNextSiblingElement(curElem);            pgen = new DOMCryptoBinary(curElem.getFirstChild());        }        //@@@ do we care about j, pgenCounter or seed?        DSAPublicKeySpec spec = new DSAPublicKeySpec            (y.getBigNum(), p.getBigNum(), q.getBigNum(), g.getBigNum());        return (DSAPublicKey) generatePublicKey(dsakf, spec);    }     private RSAPublicKey unmarshalRSAKeyValue(Element kvtElem)        throws MarshalException {        if (rsakf == null) {            try {                rsakf = KeyFactory.getInstance("RSA");            } catch (NoSuchAlgorithmException e) {                throw new RuntimeException("unable to create RSA KeyFactory: " +                    e.getMessage());            }        }        Element modulusElem = DOMUtils.getFirstChildElement(kvtElem);        modulus = new DOMCryptoBinary(modulusElem.getFirstChild());        Element exponentElem = DOMUtils.getNextSiblingElement(modulusElem);        exponent = new DOMCryptoBinary(exponentElem.getFirstChild());        RSAPublicKeySpec spec = new RSAPublicKeySpec            (modulus.getBigNum(), exponent.getBigNum());        return (RSAPublicKey) generatePublicKey(rsakf, spec);    }     private PublicKey generatePublicKey(KeyFactory kf, KeySpec keyspec) {        try {            return kf.generatePublic(keyspec);        } catch (InvalidKeySpecException e) {            //@@@ should dump exception to log            return null;        }    }     public boolean equals(Object obj) {        if (this == obj) {            return true;        }        if (!(obj instanceof KeyValue)) {            return false;        }        try {            KeyValue kv = (KeyValue) obj;            if (publicKey == null ) {                if (kv.getPublicKey() != null) {                    return false;                }            } else if (!publicKey.equals(kv.getPublicKey())) {                return false;            }        } catch (KeyException ke) {            // no practical way to determine if the keys are equal            return false;        }         return true;    }}