/* * Copyright 2011 by Graz University of Technology, Austria * MOCCA has been developed by the E-Government Innovation Center EGIZ, a joint * initiative of the Federal Chancellery Austria and Graz University of Technology. * * Licensed under the EUPL, Version 1.1 or - as soon they will be approved by * the European Commission - subsequent versions of the EUPL (the "Licence"); * You may not use this work except in compliance with the Licence. * You may obtain a copy of the Licence at: * http://www.osor.eu/eupl/ * * Unless required by applicable law or agreed to in writing, software * distributed under the Licence is distributed on an "AS IS" basis, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the Licence for the specific language governing permissions and * limitations under the Licence. * * This product combines work with different licenses. See the "NOTICE" text * file for details on the various modules and licenses. * The "NOTICE" text file is part of the distribution. Any derivative works * that you distribute must include a readable copy of the "NOTICE" text file. */ package at.gv.egiz.xmldsig; import iaik.security.ec.errorhandling.InvalidCurveParameterSpecException; import java.math.BigInteger; import java.security.InvalidKeyException; import java.security.PublicKey; import java.security.interfaces.DSAParams; import java.security.interfaces.DSAPublicKey; import java.security.interfaces.ECPublicKey; import java.security.interfaces.RSAPublicKey; import java.security.spec.ECField; import java.security.spec.ECFieldF2m; import java.security.spec.ECFieldFp; import java.security.spec.ECParameterSpec; import java.security.spec.ECPoint; import java.security.spec.EllipticCurve; import javax.xml.bind.JAXBElement; import org.w3._2000._09.xmldsig_.DSAKeyValueType; import org.w3._2000._09.xmldsig_.RSAKeyValueType; import org.w3._2001._04.xmldsig_more_.BasePointParamsType; import org.w3._2001._04.xmldsig_more_.CharTwoFieldElemType; import org.w3._2001._04.xmldsig_more_.CurveParamsType; import org.w3._2001._04.xmldsig_more_.DomainParamsType; import org.w3._2001._04.xmldsig_more_.ECDSAKeyValueType; import org.w3._2001._04.xmldsig_more_.ECPointType; import org.w3._2001._04.xmldsig_more_.ExplicitParamsType; import org.w3._2001._04.xmldsig_more_.FieldElemType; import org.w3._2001._04.xmldsig_more_.FieldParamsType; import org.w3._2001._04.xmldsig_more_.PnBFieldParamsType; import org.w3._2001._04.xmldsig_more_.PrimeFieldElemType; import org.w3._2001._04.xmldsig_more_.PrimeFieldParamsType; import org.w3._2001._04.xmldsig_more_.TnBFieldParamsType; import org.w3._2001._04.xmldsig_more_.DomainParamsType.NamedCurve; public class KeyValueFactory { private static byte[] bigInteger2byteArray(BigInteger bigPositiveInt) { if (bigPositiveInt == null) throw new NullPointerException("Argument 'bigPositiveInt' must not be null"); if (bigPositiveInt.signum() != 1) throw new IllegalArgumentException("Argument 'bigPositiveInt' must not be negative"); byte[] byteRepresentation = bigPositiveInt.toByteArray(); if (byteRepresentation[0] == 0) { byte[] oldByteRepresentation = byteRepresentation; byteRepresentation = new byte[oldByteRepresentation.length - 1]; System.arraycopy(oldByteRepresentation, 1, byteRepresentation, 0, oldByteRepresentation.length - 1); } return byteRepresentation; } org.w3._2001._04.xmldsig_more_.ObjectFactory ecFactory = new org.w3._2001._04.xmldsig_more_.ObjectFactory(); org.w3._2000._09.xmldsig_.ObjectFactory dsFactory = new org.w3._2000._09.xmldsig_.ObjectFactory(); public JAXBElement createKeyValue(PublicKey publicKey) throws KeyTypeNotSupportedException { if (publicKey instanceof RSAPublicKey) { RSAKeyValueType keyValueType = createRSAKeyValueType((RSAPublicKey) publicKey); return dsFactory.createRSAKeyValue(keyValueType); } else if (publicKey instanceof DSAPublicKey) { DSAKeyValueType keyValueType = createKeyValueType((DSAPublicKey) publicKey); return dsFactory.createDSAKeyValue(keyValueType); } else if (publicKey instanceof ECPublicKey) { ECDSAKeyValueType keyValueType = createKeyValueType((ECPublicKey) publicKey); return ecFactory.createECDSAKeyValue(keyValueType); } else if ("EC".equals(publicKey.getAlgorithm())) { byte[] encoded = publicKey.getEncoded(); try { ECPublicKey key = new iaik.security.ec.common.ECPublicKey(encoded); ECDSAKeyValueType keyValueType = createKeyValueType(key); return ecFactory.createECDSAKeyValue(keyValueType); } catch (InvalidKeyException e) { throw new KeyTypeNotSupportedException("Public key of type " + publicKey.getAlgorithm() + " (" + publicKey.getClass() + ") not supported."); } } else { throw new KeyTypeNotSupportedException("Public key of type " + publicKey.getAlgorithm() + " (" + publicKey.getClass() + ") not supported."); } } public RSAKeyValueType createRSAKeyValueType(RSAPublicKey publicKey) { RSAKeyValueType keyValueType = dsFactory.createRSAKeyValueType(); keyValueType.setExponent(bigInteger2byteArray(publicKey.getPublicExponent())); keyValueType.setModulus(bigInteger2byteArray(publicKey.getModulus())); return keyValueType; } public DSAKeyValueType createKeyValueType(DSAPublicKey publicKey) { DSAKeyValueType keyValueType = dsFactory.createDSAKeyValueType(); if (publicKey.getParams() != null) { // P, Q, G DSAParams params = publicKey.getParams(); if (params.getP() != null && params.getQ() != null) { keyValueType.setP(bigInteger2byteArray(params.getP())); keyValueType.setQ(bigInteger2byteArray(params.getQ())); } if (params.getG() != null) { keyValueType.setG(bigInteger2byteArray(params.getG())); } } // keyValueType.setY(bigInteger2byteArray(publicKey.getY())); return keyValueType; } public ECDSAKeyValueType createKeyValueType(ECPublicKey publicKey) throws KeyTypeNotSupportedException { ECDSAKeyValueType keyValueType = ecFactory.createECDSAKeyValueType(); ECParameterSpec params = publicKey.getParams(); if (params != null) { keyValueType.setDomainParameters(createDomainParamsType(params)); } if (!publicKey.getW().equals(java.security.spec.ECPoint.POINT_INFINITY)) { keyValueType.setPublicKey(createPointType(publicKey.getW(), params.getCurve().getField())); } return keyValueType; } public ECPointType createPointType(ECPoint point, ECField field) throws KeyTypeNotSupportedException { ECPointType pointType = ecFactory.createECPointType(); pointType.setX(createFieldElemType(point.getAffineX(), field)); pointType.setY(createFieldElemType(point.getAffineY(), field)); return pointType; } public FieldElemType createFieldElemType(BigInteger point, ECField field) throws KeyTypeNotSupportedException { if (field instanceof ECFieldFp) { PrimeFieldElemType fieldElemType = ecFactory.createPrimeFieldElemType(); fieldElemType.setValue(point); return fieldElemType; } else if (field instanceof ECFieldF2m) { CharTwoFieldElemType fieldElemType = ecFactory.createCharTwoFieldElemType(); fieldElemType.setValue(bigInteger2byteArray(point)); return fieldElemType; } else { throw new KeyTypeNotSupportedException("Field element type not supported."); } } public FieldParamsType createFieldParamsType(ECField field) throws KeyTypeNotSupportedException { if (field instanceof ECFieldFp) { // PrimeFieldParamsType PrimeFieldParamsType primeFieldParamsType = ecFactory.createPrimeFieldParamsType(); primeFieldParamsType.setP(((ECFieldFp) field).getP()); return primeFieldParamsType; } else if (field instanceof ECFieldF2m) { // CharTwoFieldParamsType ECFieldF2m fieldf2m = (ECFieldF2m) field; int[] ks = fieldf2m.getMidTermsOfReductionPolynomial(); // detect if trinomial or pentanomial base is present... switch (ks.length) { case 1: // trinomial base TnBFieldParamsType tnBFieldParamsType = ecFactory.createTnBFieldParamsType(); tnBFieldParamsType.setM(BigInteger.valueOf(fieldf2m.getM())); tnBFieldParamsType.setK(BigInteger.valueOf(ks[0])); return tnBFieldParamsType; case 3: // pentanomial base PnBFieldParamsType pnBFieldParamsType = ecFactory.createPnBFieldParamsType(); pnBFieldParamsType.setM(BigInteger.valueOf(fieldf2m.getM())); pnBFieldParamsType.setK1(BigInteger.valueOf(ks[0])); pnBFieldParamsType.setK2(BigInteger.valueOf(ks[1])); pnBFieldParamsType.setK3(BigInteger.valueOf(ks[2])); return pnBFieldParamsType; default: throw new KeyTypeNotSupportedException("Only trinomial and pentanomial base is supported."); } } else { throw new KeyTypeNotSupportedException("Field element type not supported."); } } public DomainParamsType createDomainParamsType(ECParameterSpec params) throws KeyTypeNotSupportedException { iaik.security.ec.common.ECParameterSpec params2; try { params2 = iaik.security.ec.common.ECParameterSpec.getParameterSpec(params); } catch (InvalidCurveParameterSpecException e) { throw new KeyTypeNotSupportedException(e); } DomainParamsType domainParamsType = ecFactory.createDomainParamsType(); EllipticCurve curve = params.getCurve(); String oid = params2.getOID(); if (oid != null) { // NamedCurve NamedCurve namedCurve = ecFactory.createDomainParamsTypeNamedCurve(); namedCurve.setURN("urn:oid:" + oid); domainParamsType.setNamedCurve(namedCurve); } else { // Explicit parameters ExplicitParamsType explicitParamsType = ecFactory.createExplicitParamsType(); explicitParamsType.setFieldParams(createFieldParamsType(curve.getField())); CurveParamsType curveParamsType = ecFactory.createCurveParamsType(); ECField field = params.getCurve().getField(); // curve coefficients curveParamsType.setA(createFieldElemType(curve.getA(), field)); curveParamsType.setB(createFieldElemType(curve.getB(), field)); // seed if (curve.getSeed() != null) curveParamsType.setSeed(curve.getSeed()); explicitParamsType.setCurveParams(curveParamsType); // BasePoint parameters BasePointParamsType basePointParamsType = ecFactory.createBasePointParamsType(); if (!params.getGenerator().equals(ECPoint.POINT_INFINITY)) { basePointParamsType.setBasePoint(createPointType(params.getGenerator(), field)); } basePointParamsType.setOrder(params.getOrder()); basePointParamsType.setCofactor(BigInteger.valueOf(params.getCofactor())); explicitParamsType.setBasePointParams(basePointParamsType); domainParamsType.setExplicitParams(explicitParamsType); } return domainParamsType; } }