/* * Copyright 2011 Licel LLC. * * 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. */ package com.licel.jcardsim.crypto; import javacard.security.KeyBuilder; import javacard.security.KeyPair; import javacard.security.PrivateKey; import javacard.security.PublicKey; import javacard.security.RSAPublicKey; import javacard.security.RandomData; import javacard.security.Signature; import junit.framework.TestCase; import org.bouncycastle.util.encoders.Hex; /** * Test for * <code>AsymmetricSignatureImpl</code> Test data from NXP JCOP31-36 JavaCard */ public class AsymmetricSignatureImplTest extends TestCase { // rsa public key data from card final static String RSA_ETALON_MODULUS = "00D3038C1FCA3CB00A2B52D8EB9446B422F091FB0871715DB8747809461ADD98DDAE963F56B8CB21B00CE1E209D9BBF7FADE6580F8A5996EC9AB9455AF432D4994E261B0426A41DF155CEFF4CB464F9DCB9521AA9EEED2895E8B85D13469C0D5F22396314587D305740D2A219F7B641869DD8A995E5B928DC81DB385D140D48C71"; final static String RSA_ETALON_EXP = "010001"; final static short RSA_ETALON_KEY_SIZE = 1024; // etalon msg String MESSAGE = "C46A3D01F5494013F9DFF3C5392C64"; // signatures from card final static String[] RSA_SIGNATURES = new String[]{ // ALG_RSA_SHA_ISO9796 "389629B307B396FB2BCE1379DD950A5D21B052169FB8789E3A5483FDBE85B5B9B1AC92C50FD8D38F829D5565024506D69FC0A3DAF99BE379F62BE7BAC14C64DA100301CE96A9202151F1F227CB9AC492573BDFED0209CA6DCB19099B907E8C54FFF8A6C7919F892242A720E6A9113D5C9DDADF2E6FA0903CD35A88B48ACC4E62", // ALG_RSA_SHA_PKCS1 "A45ECBE4DC34A6EDDEFD547245720BBE706AE06EB1E162C04E556FAECD717C958C3134DDB99C4105E1DE2C38419A70B9C9094B192B1B68385B0A65399198C2685B6AC06F704E1EDAE638AD870599BC502801F4094D53354696DEB60C3453D718EB29D5815C395357DC6607EB9A6989DF7E2652899184D764BBA155B33AB6C267", // ALG_RSA_MD5_PKCS1 "2BCBD3220787D8D621526FBF88E852158FB37B46A339EAAF64742548155C7A48DA3ED9D41B9A29BAB2582A81329411C9FB0FDE0BFCF962438440C68828C1FDC3B33A4F0FEE318FA9DA3802A5CBAA9E9D6EA3618A2626E9FDA6F5613335F868442E20B3EB2E5C0580CE6E999BBD33A9BD5C633FE18930916586D91527781F1081" }; // RSA 2048-bit public key data from card final static String RSA_2048_MODULUS = "8D4E29049C1C1861557F78B399665AAF957B73EBCCF5A436ED204A3B2C88F7A73ACE693147A6A731FFC297FBDFEABBA3658FDA68F0C3A60C2D8A96F874293FADE00F6AF600091A59118E8388DC69FD2D737882FBBB624A1A8BBD89641CFE33FC9C85BBC99017FCFE5CD5D13A3FE70524BE870171B0DBC870CB2F123CA5540C3B0759B71871A08EE3521C66261DCC1BD8F95DC850B730D8B8F0CF80F19C71B35FCB0439F419E7BD8E7B6A55203EFC6191D79DEF46B8A8F47EDF38F9E618A885BDFB8B212919D41CA1AB2B9B48328A9F4CF552FC157B8A1361A5ACABEE27725E835622D633569291532384EE47817AEB75119294E8522444FCCCB4F54073C2E121"; // RSA 2048-bit Signature final static String RSA_2048_SIGNATURE = "27E3B9410C261BE66534B9FC8CB272902B8BFB06077CA973B39B512C48DD878FA4B00259E7B58ECD5F236127990DC6E10DAB1CAF4C967689C1D1A03A5C5EBD6EA617D5F0AEE09851207EC4BCE67287687F21AC450693B9B22CEC7EA87679FC6BCE1B2DA56F41BF9BD433932370379C103D269E9E529E46699E03E243B589DE5469B12E27B1F95E8FE6F872010A64126760AC51AEF44CDABE4D9FBC7568B12A077943E8CF3A4C3C1674B3600B1AA01CB2D290A0DC7968F1509BEB5ECC47C48789870D5279E675D67E262AF96CD8750D9C4CE450D64FDC8D135573B9BB0497B4A6F3F3034832707C116D2E3E51EC85D6BCF8AF681AC96245CD03D50CF5D391B0AF"; public AsymmetricSignatureImplTest(String testName) { super(testName); } protected void setUp() throws Exception { super.setUp(); } protected void tearDown() throws Exception { super.tearDown(); } /** * Test of verify method, of class AsymmetricSignatureImpl. */ public void testVerifyRSA() { System.out.println("verify rsa"); RSAPublicKey publicKey = (RSAPublicKey) KeyBuilder.buildKey(KeyBuilder.TYPE_RSA_PUBLIC, RSA_ETALON_KEY_SIZE, false); byte[] modulus = Hex.decode(RSA_ETALON_MODULUS); byte[] exponent = Hex.decode(RSA_ETALON_EXP); publicKey.setModulus(modulus, (short) 0, (short) modulus.length); publicKey.setExponent(exponent, (short) 0, (short) exponent.length); RSAPublicKey publicKey2048 = (RSAPublicKey) KeyBuilder.buildKey(KeyBuilder.TYPE_RSA_PUBLIC, KeyBuilder.LENGTH_RSA_2048, false); byte[] modulus2048 = Hex.decode(RSA_2048_MODULUS); publicKey2048.setModulus(modulus2048, (short) 0, (short) modulus2048.length); publicKey2048.setExponent(exponent, (short) 0, (short) exponent.length); // verify signs Signature signature = Signature.getInstance(Signature.ALG_RSA_SHA_ISO9796, false); testEngineVerify(signature, publicKey, Hex.decode(MESSAGE), Hex.decode(RSA_SIGNATURES[0]), (short) 0); signature = Signature.getInstance(Signature.ALG_RSA_SHA_PKCS1, false); testEngineVerify(signature, publicKey, Hex.decode(MESSAGE), Hex.decode(RSA_SIGNATURES[1]), (short) 0); signature = Signature.getInstance(Signature.ALG_RSA_SHA_PKCS1, false); testEngineVerify(signature, publicKey2048, new byte[24], Hex.decode(RSA_2048_SIGNATURE), (short) 0); signature = Signature.getInstance(Signature.ALG_RSA_MD5_PKCS1, false); testEngineVerify(signature, publicKey, Hex.decode(MESSAGE), Hex.decode(RSA_SIGNATURES[2]), (short) 0); } /** * SelfTest of RSA sign/verify method, of class AsymmetricSignatureImpl. */ public void testSelfSignVerifyRSA() { System.out.println("self test sign/verify rsa"); testSelfSignVerify(KeyPair.ALG_RSA_CRT, RSA_ETALON_KEY_SIZE, Signature.ALG_RSA_SHA_PKCS1); } /** * SelfTest of ECDSA sign/verify method, of class AsymmetricSignatureImpl. */ public void testSelfSignVerifyECDSA() { System.out.println("self test sign/verify ecdsa"); // ecf2m keys testSelfSignVerify(KeyPair.ALG_EC_F2M, KeyBuilder.LENGTH_EC_F2M_113, Signature.ALG_ECDSA_SHA); // ecfp keys testSelfSignVerify(KeyPair.ALG_EC_FP, KeyBuilder.LENGTH_EC_FP_112, Signature.ALG_ECDSA_SHA); } /** * Base SelfTest sign/verify method * * @param keyAlg - key generation algorithm * @param keySize - key size * @param signAlg - signature algorithm */ public void testSelfSignVerify(byte keyAlg, short keySize, byte signAlg) { // generate keys KeyPair kp = new KeyPair(keyAlg, keySize); kp.genKeyPair(); PrivateKey privateKey = kp.getPrivate(); PublicKey publicKey = kp.getPublic(); // init engine Signature signEngine = Signature.getInstance(signAlg, false); signEngine.init(privateKey, Signature.MODE_SIGN); // sign length + extra space byte[] signature = new byte[128 + 10]; byte[] msg = new byte[65]; RandomData rnd = RandomData.getInstance(RandomData.ALG_PSEUDO_RANDOM); rnd.generateData(msg, (short) 0, (short) msg.length); short signLen = signEngine.sign(msg, (short) 0, (short) msg.length, signature, (short) 10); // issue https://code.google.com/p/jcardsim/issues/detail?id=14 assertEquals(signLen<=signEngine.getLength(), true); Signature verifyEngine = Signature.getInstance(signAlg, false); testEngineVerify(verifyEngine, publicKey, msg, signature, (short) 10, signLen); } /** * Test the method * <code>verify</code> of * <code>Signature</code> engine * * @param engine tested engine * @param publicKey public key * @param etalonMsg etalon message bytes * @param etalonSign etalon signature bytes */ public void testEngineVerify(Signature engine, PublicKey publicKey, byte[] etalonMsg, byte[] etalonSign, short etalonSignOffset) { testEngineVerify(engine, publicKey, etalonMsg, etalonSign, etalonSignOffset, (short) etalonSign.length); } /** * Test the method * <code>verify</code> of * <code>Signature</code> engine * * @param engine tested engine * @param publicKey public key * @param etalonMsg etalon message bytes * @param etalonSign etalon signature bytes */ public void testEngineVerify(Signature engine, PublicKey publicKey, byte[] etalonMsg, byte[] etalonSign, short etalonSignOffset, short etalonSignLength) { engine.init(publicKey, Signature.MODE_VERIFY); boolean result = engine.verify(etalonMsg, (short) 0, (short) etalonMsg.length, etalonSign, etalonSignOffset, (short)(etalonSignLength!=0?etalonSignLength:etalonSign.length)); assertEquals(true, result); } }