de.fraunhofer.fokus.openeid.ta.TerminalAuthenticationInfoProtocol.java Source code

Java tutorial

Introduction

Here is the source code for de.fraunhofer.fokus.openeid.ta.TerminalAuthenticationInfoProtocol.java

Source

/*******************************************************************************
 * 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;
    }

}