Java tutorial
/******************************************************************************* * Implementation of the protocols PACE, Terminal Authentication and Chip * Authentication (client side) with respect to the according BSI standards. * * Copyright (C) 2013 Fraunhofer-Gesellschaft * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see <http://www.gnu.org/licenses/>. ******************************************************************************/ package de.fraunhofer.fokus.openeid.ta; import java.io.IOException; import java.util.Arrays; import org.bouncycastle.asn1.ASN1Integer; import org.bouncycastle.asn1.ASN1Sequence; import org.bouncycastle.asn1.DEREncodable; import org.bouncycastle.asn1.DERInteger; import org.bouncycastle.asn1.DERSequence; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import de.fraunhofer.fokus.openeid.commands.UnsupportedProtocolException; import de.fraunhofer.fokus.openeid.cryptography.Signer; import de.fraunhofer.fokus.openeid.iso7816_4.Utils; /** * * Terminal Authentication related functionality: * sign/verify * * @author "Mateusz Khalil" * */ public enum TerminalAuthenticationInfoProtocol { ID_TA_ECDSA_SHA_224(TerminalAuthenticationInfoOID.ID_TA_ECDSA_SHA_224, "SHA224withECDSA", "ECDSA"), ID_TA_ECDSA_SHA_256(TerminalAuthenticationInfoOID.ID_TA_ECDSA_SHA_256, "SHA256withECDSA", "ECDSA"), ID_TA_ECDSA_SHA_512(TerminalAuthenticationInfoOID.ID_TA_ECDSA_SHA_512, "SHA512withECDSA", "ECDSA"),; private String oid; private Signer signer; private String keyType; private TerminalAuthenticationInfoProtocol(String oid, String signatureAlgorithm, String keyType) { Logger logger = LoggerFactory.getLogger(getClass()); this.oid = oid; this.keyType = keyType; try { signer = new Signer(signatureAlgorithm); } catch (Exception e) { logger.error("Could not retrieve signature algorithm"); } } public String getOid() { return oid; } public String getKeyType() { return keyType; } public Signer getSigner() { return signer; } public static TerminalAuthenticationInfoProtocol getProtocolByOid(String oid) throws UnsupportedProtocolException { for (TerminalAuthenticationInfoProtocol protocol : values()) { if (protocol.getOid().equals(oid)) return protocol; } throw new UnsupportedProtocolException(oid); } /** * convert signature from asn1 mode (default ECDSA) to plain mode (no asn1) * refert to: * D.2.1.4 ECDSA Plain Signature * According to [3] ECDSA signatures in plain format are specified as * direct concatenation of two octet * strings R||S. For ECDSA-224, each octet string has length 28 (decimal). * R 1DAF7AA1 98B948A6 DFB626BD DDAD3C03 43ABD1F1 049C4CA1 B09821C7 * S 7A5A3BBB 18A5D2F6 D9AF0A24 63B4C137 287BAFF1 9DB8684C 1441989F * @param signature in asn1 mode * @return signature in plain mode */ public static byte[] convertToPlainMode(byte[] signature) { try { ASN1Sequence sequence = (ASN1Sequence) DERSequence.fromByteArray(signature); DEREncodable rObject = sequence.getObjectAt(0); DEREncodable sObject = sequence.getObjectAt(1); byte[] rValue; byte[] sValue; if (rObject instanceof ASN1Integer) { ASN1Integer r = (ASN1Integer) rObject; ASN1Integer s = (ASN1Integer) sObject; rValue = r.getValue().toByteArray(); sValue = s.getValue().toByteArray(); } else { DERInteger r = (DERInteger) rObject; DERInteger s = (DERInteger) sObject; rValue = r.getValue().toByteArray(); sValue = s.getValue().toByteArray(); } byte[] r_part = removeLeadingZero(rValue); byte[] l_part = removeLeadingZero(sValue); return Utils.concat(r_part, l_part); } catch (IOException e) { return signature; } } public static byte[] removeLeadingZero(byte[] r_part) { if (r_part[0] == 0) r_part = Arrays.copyOfRange(r_part, 1, r_part.length); return r_part; } }