All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.esteid.hacker.FakeEstEIDManager Maven / Gradle / Ivy

/**
 * Copyright (C) 2014-2017 Martin Paljak
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 3.0 of the License, or (at your option) any later version.
 *
 * This library 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
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this library; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
 */
package org.esteid.hacker;

import java.io.File;
import java.io.FileInputStream;
import java.io.InputStreamReader;
import java.math.BigInteger;
import java.security.InvalidKeyException;
import java.security.KeyPair;
import java.security.KeyPairGenerator;
import java.security.NoSuchAlgorithmException;
import java.security.SecureRandom;
import java.security.cert.X509Certificate;
import java.security.interfaces.RSAPrivateCrtKey;
import java.security.interfaces.RSAPublicKey;
import java.util.Arrays;

import javax.crypto.BadPaddingException;
import javax.crypto.Cipher;
import javax.crypto.IllegalBlockSizeException;
import javax.crypto.NoSuchPaddingException;
import javax.smartcardio.CardChannel;
import javax.smartcardio.CardException;
import javax.smartcardio.CommandAPDU;
import javax.smartcardio.ResponseAPDU;

import org.bouncycastle.cert.X509CertificateHolder;
import org.bouncycastle.crypto.RuntimeCryptoException;
import org.bouncycastle.jce.provider.BouncyCastleProvider;
import org.bouncycastle.openssl.PEMKeyPair;
import org.bouncycastle.openssl.PEMParser;
import org.bouncycastle.openssl.jcajce.JcaPEMKeyConverter;
import org.esteid.EstEID;
import org.esteid.EstEID.EstEIDException;

// Given a connection to a FakeEstEID applet, provides a higher level interface for the possibilities.
public class FakeEstEIDManager {

	// Other fun constants
	private static final String[] defaultDataFile = new String[] {"JÄNES-KARVANE", "SIILIPOISS", "Jesús MARIA", "G", "LOL", "01.01.0001", "10101010005", "A0000001", "31.12.2099", "TIIBET", "01.01.2014", "ALALINE", "SEE POLE PÄRIS KAART", " ", " ", " "};

	private final CardChannel channel;

	FakeEstEIDManager(CardChannel c) {
		channel = c;
	}

	public static FakeEstEIDManager getInstance(EstEID esteid) {
		FakeEstEIDManager fake = new FakeEstEIDManager(esteid.getChannel());
		return fake;
	}

	public void send_cert(byte[] cert, int num) throws Exception {
		int chunksize = 240; // was:253

		byte [] c = org.bouncycastle.util.Arrays.append(cert, (byte)0x80);
		for (int i = 0; i<= (c.length / chunksize); i++) {
			byte []d = new byte[2+chunksize];
			int off = i*chunksize;

			d[0] = (byte) ((off & 0xFF00) >>> 8);
			d[1] = (byte) (off & 0xFF);
			byte[] chunk = Arrays.copyOfRange(c, i*chunksize, i*chunksize+chunksize);
			System.arraycopy(chunk, 0, d, 2, chunk.length);
			CommandAPDU cmd = new CommandAPDU(0x80, 0x02, num, 0x00, d);
			EstEIDException.check(channel.transmit(cmd));
		}

	}

	public void send_cert_pem(File f, int num) throws Exception {
		try (PEMParser pem = new PEMParser(new InputStreamReader(new FileInputStream(f), "UTF-8"))) {
			X509CertificateHolder crt = (X509CertificateHolder) pem.readObject();
			send_cert(crt.getEncoded(), num);
		}
	}

	public void send_new_key(int num) throws Exception {
		KeyPairGenerator keyGen = KeyPairGenerator.getInstance("RSA");
		keyGen.initialize(2048);
		//keyGen.initialize(new RSAKeyGenParameterSpec(2048, BigInteger.ONE));
		KeyPair key = keyGen.generateKeyPair();
		send_key((RSAPrivateCrtKey) key.getPrivate(), num);
	}

	public void send_key_pem(File f, int num) throws Exception {
		try (PEMParser pem = new PEMParser(new InputStreamReader(new FileInputStream(f), "UTF-8"))) {
			// OpenSSL genrsa makes a key pair.
			Object o = pem.readObject();
			RSAPrivateCrtKey key;
			if (o instanceof org.bouncycastle.openssl.PEMKeyPair) {
				PEMKeyPair pair = (PEMKeyPair) o;
				JcaPEMKeyConverter convert = new JcaPEMKeyConverter();
				key = (RSAPrivateCrtKey) convert.getPrivateKey(pair.getPrivateKeyInfo());
			} else {
				key = (RSAPrivateCrtKey) pem.readObject();
			}
			send_key(key, num);
		}
	}

	public void send_key(RSAPrivateCrtKey key, int num) throws CardException, EstEIDException {
		//card.beginExclusive();
		try {
			CommandAPDU cmd = null;
			cmd = new CommandAPDU(0x80, 0x03, num, 0x01, unsigned(key.getPrimeP()));
			EstEIDException.check(channel.transmit(cmd));
			cmd = new CommandAPDU(0x80, 0x03, num, 0x02, unsigned(key.getPrimeQ()));
			EstEIDException.check(channel.transmit(cmd));
			cmd = new CommandAPDU(0x80, 0x03, num, 0x03, unsigned(key.getPrimeExponentP()));
			EstEIDException.check(channel.transmit(cmd));
			cmd = new CommandAPDU(0x80, 0x03, num, 0x04, unsigned(key.getPrimeExponentQ()));
			EstEIDException.check(channel.transmit(cmd));
			cmd = new CommandAPDU(0x80, 0x03, num, 0x05, unsigned(key.getCrtCoefficient()));
			EstEIDException.check(channel.transmit(cmd));
		} finally {
			//card.endExclusive();
		}
	}

	public void make_sample_card(FakeEstEIDCA ca, boolean check) throws Exception {
		KeyPairGenerator keyGen = KeyPairGenerator.getInstance("RSA", BouncyCastleProvider.PROVIDER_NAME);
		keyGen.initialize(2048);
		// Generate keys
		KeyPair auth = keyGen.generateKeyPair();
		KeyPair sign = keyGen.generateKeyPair();
		X509Certificate authcert = ca.generateUserCertificate((RSAPublicKey) auth.getPublic(), false, "SIILIPOISS", "UDUS", "10101010005", "[email protected]", null, null);
		X509Certificate signcert = ca.generateUserCertificate((RSAPublicKey) sign.getPublic(), true, "SIILIPOISS", "UDUS", "10101010005", "[email protected]", null, null);
		if (check) {
			// Verify softkeys
			if (!verifyKeypairIntegrity((RSAPrivateCrtKey)auth.getPrivate(), (RSAPublicKey)authcert.getPublicKey())) {
				throw new RuntimeCryptoException("Cert and key mismatch");
			}
			if (!verifyKeypairIntegrity((RSAPrivateCrtKey)sign.getPrivate(), (RSAPublicKey)signcert.getPublicKey())) {
				throw new RuntimeCryptoException("Cert and key mismatch");
			}
		}
		send_key((RSAPrivateCrtKey) auth.getPrivate(), 1);
		send_key((RSAPrivateCrtKey) sign.getPrivate(), 2);
		send_cert(authcert.getEncoded(), 1);
		send_cert(signcert.getEncoded(), 2);

		CommandAPDU cmd = null;
		ResponseAPDU resp = null;
		if (check) {
			// Verify on-card keys.
			Cipher verify_cipher = Cipher.getInstance("RSA/ECB/PKCS1Padding");
			SecureRandom r = SecureRandom.getInstance("SHA1PRNG");
			byte [] rnd = new byte[8];

			r.nextBytes(rnd);
			cmd = new CommandAPDU(0x00, 0x88, 0x00, 0x00, rnd, 256);
			resp = channel.transmit(cmd);
			EstEIDException.check(resp);
			verify_cipher.init(Cipher.DECRYPT_MODE, authcert.getPublicKey());
			byte[] result = verify_cipher.doFinal(resp.getData());
			if (!java.util.Arrays.equals(rnd, result)) {
				throw new RuntimeCryptoException("Card and auth key don't match!");
			}

			r.nextBytes(rnd);
			cmd = new CommandAPDU(0x00, 0x2A, 0x9E, 0x9A, rnd, 256);
			resp = channel.transmit(cmd);
			EstEIDException.check(resp);
			verify_cipher.init(Cipher.DECRYPT_MODE, signcert.getPublicKey());
			result = verify_cipher.doFinal(resp.getData());
			if (!java.util.Arrays.equals(rnd, result)) {
				throw new RuntimeCryptoException("Card and sign key don't match!");
			}
		}
		// Dump default data file
		for (int i=0;i




© 2015 - 2025 Weber Informatics LLC | Privacy Policy