Smart Card Solution
User Manual
- R502 Manual
JavaCard API Samples
- Algorithm
Java Card Specification
Knowledge Sharing
Smart Card Solution
User Manual
JavaCard API Samples
Java Card Specification
Knowledge Sharing
Download Sample Code Discussion
/* * @file RSASample.java * @version v1.0 * Package AID: 4A617661436172644F53 * Applet AID: 4A617661436172644F5303 * @brief The ALgorithm of RSA Sample Code in JavaCard API Specification * @comment The purpose of this example is only used to show the usage of API functions and there is no practical significance. * @copyright Copyright(C) 2016 JavaCardOS Technologies Co., Ltd. All rights reserved. */ package JavaCardOS.Sample.Algorithm; import javacard.framework.*; import javacard.security.KeyBuilder; import javacard.security.*; import javacardx.crypto.*; public class RSASample extends Applet { private static final byte INS_GEN_RSA_KEYPAIR = (byte)0x30; private static final byte INS_GET_RSA_PUBKEY = (byte)0x31; private static final byte INS_GET_RSA_PRIKEY = (byte)0x32; private static final byte INS_SET_RSA_PUBKEY = (byte)0x33; private static final byte INS_SET_RSA_PRIKEY = (byte)0x34; private static final byte INS_RSA_SIGN = (byte)0x35; private static final byte INS_RSA_VERIFY = (byte)0x36; private static final byte INS_DO_RSA_CIPHER = (byte)0x37; private byte[] tempBuffer; private byte[] flags; private static final short OFF_INS = (short)0; private static final short OFF_P1 = (short)1; private static final short OFF_P2 = (short)2; private static final short OFF_LEN = (short)3; private static final short FLAGS_SIZE = (short)5; private static final byte ID_N = 0; private static final byte ID_D = 1; private static final byte ID_P = 2; private static final byte ID_Q = 3; private static final byte ID_PQ = 4; private static final byte ID_DP1 = 5; private static final byte ID_DQ1 = 6; private byte[] rsaPubKey; private short rsaPubKeyLen; private byte[] rsaPriKey; private short rsaPriKeyLen; private boolean isRSAPriKeyCRT; private Cipher rsaCipher; private Signature rsaSignature; private static final short SW_REFERENCE_DATA_NOT_FOUND = (short)0x6A88; public RSASample() { //Create a transient byte array to store the temporary data tempBuffer = JCSystem.makeTransientByteArray((short)256, JCSystem.CLEAR_ON_DESELECT); flags = JCSystem.makeTransientByteArray(FLAGS_SIZE, JCSystem.CLEAR_ON_DESELECT); rsaPubKey = new byte[(short) (256 + 32)]; rsaPriKey = new byte[(short)(128 * 5)]; rsaPubKeyLen = 0; rsaPriKeyLen = 0; isRSAPriKeyCRT = false; rsaSignature = null; //Create a RSA(not pad) object instance rsaCipher = Cipher.getInstance(Cipher.ALG_RSA_NOPAD, false); JCSystem.requestObjectDeletion(); } public static void install(byte[] bArray, short bOffset, byte bLength) { new RSASample().register(bArray, (short) (bOffset + 1), bArray[bOffset]); } public void process(APDU apdu) { if (selectingApplet()) { return; } byte[] buf = apdu.getBuffer(); short len = apdu.setIncomingAndReceive(); switch (buf[ISO7816.OFFSET_INS]) { case INS_GEN_RSA_KEYPAIR: //GEN_RSA_KEYPAIR genRsaKeyPair(apdu, len); break; case INS_GET_RSA_PUBKEY: //GET_RSA_PUBKEY getRsaPubKey(apdu, len); break; case INS_GET_RSA_PRIKEY: //GET_RSA_PRIKEY getRsaPriKey(apdu, len); break; case INS_SET_RSA_PUBKEY: // SET_RSA_PUBKEY setRsaPubKey(apdu, len); break; case INS_SET_RSA_PRIKEY: //SET_RSA_PRIKEY setRsaPriKey(apdu, len); break; case INS_RSA_SIGN: //RSA_SIGN rsaSign(apdu, len); break; case INS_RSA_VERIFY: //RSA_VERIFY rsaVerify(apdu, len); break; case INS_DO_RSA_CIPHER: //RSA_CIPHER doRSACipher(apdu, len); break; default: ISOException.throwIt(ISO7816.SW_INS_NOT_SUPPORTED); } } //RSA algorithm encrypt and decrypt private void doRSACipher(APDU apdu, short len) { byte[] buffer = apdu.getBuffer(); byte p1Tmp = buffer[ISO7816.OFFSET_P1]; boolean hasMoreCmd = (p1Tmp & 0x80) != 0; boolean isEncrypt = (p1Tmp & 0x01) != 1; short keyLen = (p1Tmp & 0x08) == (byte)0x00 ? KeyBuilder.LENGTH_RSA_1024 : KeyBuilder.LENGTH_RSA_2048; short offset = (p1Tmp & 0x08) == (byte)0x00 ? (short)128 : (short)256; if (len rsaPubKey.length) { Util.arrayFillNonAtomic(flags, (short)0, (short)flags.length, (byte)0); ISOException.throwIt(ISO7816.SW_WRONG_DATA); } //Copy the value of RSA public key to the global variable 'rsaPubKey'. Util.arrayCopyNonAtomic(buffer, ISO7816.OFFSET_CDATA, rsaPubKey, loadedLen, len); loadedLen += len; if ((buffer[ISO7816.OFFSET_P1] & 0x80) == 0) //last block { Util.arrayFillNonAtomic(flags, (short)0, (short)flags.length, (byte)0); short modLen = (buffer[ISO7816.OFFSET_P1] & 0x01) == 0 ? (short)128 : (short)256; if (loadedLen < modLen + 3 || loadedLen > modLen + 32) { ISOException.throwIt(ISO7816.SW_WRONG_DATA); } rsaPubKeyLen = loadedLen; } else { Util.setShort(flags, OFF_LEN, loadedLen); } } //Set the value of RSA private key private void setRsaPriKey(APDU apdu, short len) { byte[] buffer = apdu.getBuffer(); if (buffer[ISO7816.OFFSET_P2] == 0) // first block { rsaPriKeyLen = (short)0; Util.arrayCopyNonAtomic(buffer, ISO7816.OFFSET_INS, flags, OFF_INS, (short)3); Util.setShort(flags, OFF_LEN, (short)0); } else { if (flags[OFF_INS] != buffer[ISO7816.OFFSET_INS] || (flags[OFF_P1] & 0x7f) != (buffer[ISO7816.OFFSET_P1] & 0x7f) || (short)(flags[OFF_P2] & 0xff) != (short)((buffer[ISO7816.OFFSET_P2] & 0xff) - 1)) { Util.arrayFillNonAtomic(flags, (short)0, (short)flags.length, (byte)0); ISOException.throwIt(ISO7816.SW_INCORRECT_P1P2); } flags[OFF_P2] ++; } short loadedLen = Util.getShort(flags, OFF_LEN); if (loadedLen + len > rsaPriKey.length) { Util.arrayFillNonAtomic(flags, (short)0, (short)flags.length, (byte)0); ISOException.throwIt(ISO7816.SW_WRONG_DATA); } //Copy the value of RSA private key to the global variable 'rsaPriKey'. Util.arrayCopyNonAtomic(buffer, ISO7816.OFFSET_CDATA, rsaPriKey, loadedLen, len); loadedLen += len; if ((buffer[ISO7816.OFFSET_P1] & 0x80) == 0) //last block { Util.arrayFillNonAtomic(flags, (short)0, (short)flags.length, (byte)0); short modLen = (buffer[ISO7816.OFFSET_P1] & 0x01) == 0 ? (short)128 : (short)256; boolean isCRT = (buffer[ISO7816.OFFSET_P1] & 0x40) != 0; if ((isCRT && (loadedLen != modLen / 2 * 5)) || (!isCRT && (loadedLen != modLen * 2))) { ISOException.throwIt(ISO7816.SW_WRONG_DATA); } isRSAPriKeyCRT = isCRT; rsaPriKeyLen = loadedLen; } else { Util.setShort(flags, OFF_LEN, loadedLen); } } // private void genRsaKeyPair(APDU apdu, short len) { byte[] buffer = apdu.getBuffer(); short keyLen = buffer[ISO7816.OFFSET_P1] == 0 ? (short)1024 : (short)2048; byte alg = buffer[ISO7816.OFFSET_P2] == 0 ? KeyPair.ALG_RSA : KeyPair.ALG_RSA_CRT; KeyPair keyPair = new KeyPair(alg, keyLen); if (len > 32) { ISOException.throwIt(ISO7816.SW_WRONG_LENGTH); } if (len > 0) { ((RSAPublicKey)keyPair.getPublic()).setExponent(buffer, ISO7816.OFFSET_CDATA, len); } //(Re)Initializes the key objects encapsulated in this KeyPair instance with new key values. keyPair.genKeyPair(); JCSystem.beginTransaction(); rsaPubKeyLen = 0; rsaPriKeyLen = 0; JCSystem.commitTransaction(); //Get a reference to the public key component of this 'keyPair' object. RSAPublicKey pubKey = (RSAPublicKey)keyPair.getPublic(); short pubKeyLen = 0; //Store the RSA public key value in the global variable 'rsaPubKey', the public key contains modulo N and Exponent E pubKeyLen += pubKey.getModulus(rsaPubKey, pubKeyLen); pubKeyLen += pubKey.getExponent(rsaPubKey, pubKeyLen); short priKeyLen = 0; if (alg == KeyPair.ALG_RSA) { isRSAPriKeyCRT = false; //Returns a reference to the private key component of this KeyPair object. RSAPrivateKey priKey = (RSAPrivateKey)keyPair.getPrivate(); //RSA Algorithm, the Private Key contains N and D, and store these parameters value in global variable 'rsaPriKey'. priKeyLen += priKey.getModulus(rsaPriKey, priKeyLen); priKeyLen += priKey.getExponent(rsaPriKey, priKeyLen); } else //RSA CRT { isRSAPriKeyCRT = true; //The RSAPrivateCrtKey interface is used to sign data using the RSA algorithm in its Chinese Remainder Theorem form. RSAPrivateCrtKey priKey = (RSAPrivateCrtKey)keyPair.getPrivate(); //RSA CRT Algorithm, the Private Key contains P Q PQ DP and DQ, and store these parameters value in global variable 'rsaPriKey'. priKeyLen += priKey.getP(rsaPriKey, priKeyLen); priKeyLen += priKey.getQ(rsaPriKey, priKeyLen); priKeyLen += priKey.getPQ(rsaPriKey, priKeyLen); priKeyLen += priKey.getDP1(rsaPriKey, priKeyLen); priKeyLen += priKey.getDQ1(rsaPriKey, priKeyLen); } JCSystem.beginTransaction(); rsaPubKeyLen = pubKeyLen; rsaPriKeyLen = priKeyLen; JCSystem.commitTransaction(); JCSystem.requestObjectDeletion(); } //RSA Signature private void rsaSign(APDU apdu, short len) { byte[] buffer = apdu.getBuffer(); if (rsaPriKeyLen == 0) { ISOException.throwIt(ISO7816.SW_CONDITIONS_NOT_SATISFIED); } boolean hasMoreCmd = (buffer[ISO7816.OFFSET_P1] & 0x80) != 0; short resultLen = 0; if (buffer[ISO7816.OFFSET_P2] == 0) //first block { Key key; if (!isRSAPriKeyCRT) { short ret; //Creates uninitialized private keys for signature algorithms. key = KeyBuilder.buildKey(KeyBuilder.TYPE_RSA_PRIVATE, (short)(rsaPriKeyLen / 2 * 8), false); ret = getRsaPriKeyComponent(ID_N, tempBuffer, (short)0); ((RSAPrivateKey)key).setModulus(tempBuffer, (short)0, ret); ret = getRsaPriKeyComponent(ID_D, tempBuffer, (short)0); ((RSAPrivateKey)key).setExponent(tempBuffer, (short)0, ret); } else { short ret; //Creates uninitialized private keys for signature algorithms. key = KeyBuilder.buildKey(KeyBuilder.TYPE_RSA_CRT_PRIVATE, (short)(rsaPriKeyLen / 5 * 16), false); ret = getRsaPriKeyComponent(ID_P, tempBuffer, (short)0); ((RSAPrivateCrtKey)key).setP(tempBuffer, (short)0, ret); ret = getRsaPriKeyComponent(ID_Q, tempBuffer, (short)0); ((RSAPrivateCrtKey)key).setQ(tempBuffer, (short)0, ret); ret = getRsaPriKeyComponent(ID_DP1, tempBuffer, (short)0); ((RSAPrivateCrtKey)key).setDP1(tempBuffer, (short)0, ret); ret = getRsaPriKeyComponent(ID_DQ1, tempBuffer, (short)0); ((RSAPrivateCrtKey)key).setDQ1(tempBuffer, (short)0, ret); ret = getRsaPriKeyComponent(ID_PQ, tempBuffer, (short)0); ((RSAPrivateCrtKey)key).setPQ(tempBuffer, (short)0, ret); } // Creates a Signature object instance of the ALG_RSA_SHA_PKCS1 algorithm. rsaSignature = Signature.getInstance(Signature.ALG_RSA_SHA_PKCS1, false); JCSystem.requestObjectDeletion(); //Initializ the Signature object. rsaSignature.init(key, Signature.MODE_SIGN); Util.arrayCopyNonAtomic(buffer, ISO7816.OFFSET_INS, flags, OFF_INS, (short)3); JCSystem.requestObjectDeletion(); } else { if (flags[OFF_INS] != buffer[ISO7816.OFFSET_INS] || (flags[OFF_P1] & 0x7f) != (buffer[ISO7816.OFFSET_P1] & 0x7f) || (short)(flags[OFF_P2] & 0xff) != (short)((buffer[ISO7816.OFFSET_P2] & 0xff) - 1)) { Util.arrayFillNonAtomic(flags, (short)0, (short)flags.length, (byte)0); ISOException.throwIt(ISO7816.SW_INCORRECT_P1P2); } flags[OFF_P2] ++; } if (hasMoreCmd) { // Accumulates a signature of the input data. rsaSignature.update(buffer, ISO7816.OFFSET_CDATA, len); } else { //Generates the signature of all input data. short ret = rsaSignature.sign(buffer, ISO7816.OFFSET_CDATA, len, buffer, (short)0); Util.arrayFillNonAtomic(flags, (short)0, (short)flags.length, (byte)0); apdu.setOutgoingAndSend((short)0, ret); } } //RSA Signature and Verify private void rsaVerify(APDU apdu, short len) { byte[] buffer = apdu.getBuffer(); if (rsaPubKeyLen == 0) { ISOException.throwIt(ISO7816.SW_CONDITIONS_NOT_SATISFIED); } boolean hasMoreCmd = (buffer[ISO7816.OFFSET_P1] & 0x80) != 0; short resultLen = 0; short offset = ISO7816.OFFSET_CDATA; short modLen = rsaPubKeyLen > 256 ? (short)256 : (short)128; if (buffer[ISO7816.OFFSET_P2] == 0) //first block { Key key; // Create uninitialized public keys for signature algorithms. key = KeyBuilder.buildKey(KeyBuilder.TYPE_RSA_PUBLIC, (short)(modLen * 8), false); //Sets the modulus value of the key. ((RSAPublicKey)key).setModulus(rsaPubKey, (short)0, modLen); //Sets the public exponent value of the key. ((RSAPublicKey)key).setExponent(rsaPubKey, modLen, (short)(rsaPubKeyLen - modLen)); //Create a ALG_RSA_SHA_PKCS1 object instance. rsaSignature = Signature.getInstance(Signature.ALG_RSA_SHA_PKCS1, false); JCSystem.requestObjectDeletion(); //Initializes the Signature object with the appropriate Key. rsaSignature.init(key, Signature.MODE_VERIFY); Util.arrayCopyNonAtomic(buffer, ISO7816.OFFSET_INS, flags, OFF_INS, (short)3); Util.setShort(flags, OFF_LEN, (short)0); JCSystem.requestObjectDeletion(); } else { if (flags[OFF_INS] != buffer[ISO7816.OFFSET_INS] || (flags[OFF_P1] & 0x7f) != (buffer[ISO7816.OFFSET_P1] & 0x7f) || (short)(flags[OFF_P2] & 0xff) != (short)((buffer[ISO7816.OFFSET_P2] & 0xff) - 1)) { Util.arrayFillNonAtomic(flags, (short)0, (short)flags.length, (byte)0); ISOException.throwIt(ISO7816.SW_INCORRECT_P1P2); } flags[OFF_P2] ++; } short sigLen = Util.getShort(flags, OFF_LEN); if (sigLen < modLen) { short readLen = (short)(modLen - sigLen); if (readLen > len) { readLen = len; } Util.arrayCopyNonAtomic(buffer, ISO7816.OFFSET_CDATA, tempBuffer, sigLen, readLen); sigLen += readLen; len -= readLen; Util.setShort(flags, OFF_LEN, sigLen); offset += readLen; } if (hasMoreCmd) { if (len > 0) { //Accumulates a signature of the input data. rsaSignature.update(buffer, offset, len); } } else { if (sigLen != modLen) { Util.arrayFillNonAtomic(flags, (short)0, (short)flags.length, (byte)0); ISOException.throwIt(ISO7816.SW_WRONG_DATA); } //Verify the signature of all/last input data against the passed in signature. boolean ret = rsaSignature.verify(buffer, offset, len, tempBuffer, (short)0, sigLen); Util.arrayFillNonAtomic(flags, (short)0, (short)flags.length, (byte)0); buffer[(short)0] = ret ? (byte)1 : (byte)0; apdu.setOutgoingAndSend((short)0, (short)1); } } }
The test script of RSA is as follows: Download Test Script
//The test script of RSA //Copyright(C) JavaCardOS Technologies Co., Ltd. All rights reserved. //RSA Select Applet 00A404000B4A617661436172644F530300; //RSA //generate-keypair-1024 in card 80300000; //get Publck Key - N 80310000; //get Publck Key - E The data of response APDU command is 4 bytes, such as 01 00 01 90 00 80310100; //get RSA Private Key - N 80320000; //get RSA Private Key - D 80320100; //RSA encrypt - 2048 //set RSA Public key 2048bit 80338100C8C24A7A902FA8983CBBAB3F690528F86D5591496374E6B3B4EC47CA644CB55F204C4D5EEBBD9D236B6F74AC209738CB294A7C26F1251D838EDF8ADAF3E287743A5D7C65BBBCFE4A22BEB06D0D65DAFE1D1217E8AB9E5B7AA0D3883A4D6D2F5BE5B295AE6CD495D45D4452876F573C3EDD402E3BA998EC1078F662027A5F7BCE949C3B3F0309B1BE5EE9AAE720C97C2C2F0CBCD298E3FC049A457513DCCC70BDA06949011BC1F0DB6F499685377DF87B3E66890FB4C0CC09CF12DB338394C44E324D0F1931D623C035; 803301013BD00F518C353243CD22A3239811928163DCDA1352044AE4E15F10FEF648E98AE88B7BBA89F29C7EFAE5EE04E299F90F52FEE263AF2DA885FB010001; //set RSA Private Key 2048bit 80348100C8C24A7A902FA8983CBBAB3F690528F86D5591496374E6B3B4EC47CA644CB55F204C4D5EEBBD9D236B6F74AC209738CB294A7C26F1251D838EDF8ADAF3E287743A5D7C65BBBCFE4A22BEB06D0D65DAFE1D1217E8AB9E5B7AA0D3883A4D6D2F5BE5B295AE6CD495D45D4452876F573C3EDD402E3BA998EC1078F662027A5F7BCE949C3B3F0309B1BE5EE9AAE720C97C2C2F0CBCD298E3FC049A457513DCCC70BDA06949011BC1F0DB6F499685377DF87B3E66890FB4C0CC09CF12DB338394C44E324D0F1931D623C035; 80348101C8D00F518C353243CD22A3239811928163DCDA1352044AE4E15F10FEF648E98AE88B7BBA89F29C7EFAE5EE04E299F90F52FEE263AF2DA885FB8FFFDD79122995B3A5B0558E03CA0ADE1606596B42505EAEE0549117E796A18B71A202911C76E3B293E7D84F4B65478631F3747553F9DCF0BE93CE95E5B659198D024EF06731DD468528839AE37BFCCD1504ED688D34E5DD5F0A5F93D531BD9DAFCFAA7874D31B9388B8D6325A68877B3A3F49EEF82D364440F001402B96BA533404EB121B0E6604B0678A5AAA100C56; 8034010270B3ECD17EDDCB4F5BC71BBE1E7A405679380E6D9A777AA8452A2DE5F1FECAA09ACEA4A02940A14F28C7CBF7EE0A1A1519B58ED3161A590BC66B82C13CD43C484AD2D77E8301629F9B1EB4C7505C5A7B46C0171668990775FDF2E62BB695DF424130727CD0ACC61943FE8EF513A0AC9BD1; // RSA Signature SHA1 &2048bit //expect:75A78094B3A63715B85327C2839CE1E1831C39B740DDB9F67F27AEBC540DB94BF95C7DEE200AC60A2BF0F64B9F4772A163E036D8DC8E865EFD5B3E7A9442BDF43BA86660D305C15DB2A3A8F5F6E3D1F50E234B193DD787B89E3EDF045E280285474A027E8985F45D883E14593D91CF79017E3AEBCF8A155DD0B5C85BE0A4301D0F80C99A15D154DF54FFE8EB603DA85184386452ABB47C985EF1D5390FF74516A7F0B8A05380DD186AA6FA584287F8AAE6421D98AD84601D734EA008CE0B37FF574BD1C9FE948DABF0A78F4E691FC0A9CAE6DC1288BD2E295CFB31443F09AF16B5D66886BA7AEF2FF272E443ADBA47798F76EF6B4594CEC399526F21236AD3A29000 8035000080C05DECFACFC439CA7AB1EC89F554FF982FB7E8E95FFFC863DFEFE5883EAD5A5591C90D69097BE26ACB2C2EA5FB386FF41AF33AE593EA7418906BC5E912474A4F41D68A04013CACE7C5EBE79EA869397FBA545CB197A3F68E3F2E104C2171C9DD798C4B13DC8FFF0811F5FDBD236EC701B4E2369594B2B48D9341ACF993B33FC5; //RSA Verify 2048bit 80368000C875A78094B3A63715B85327C2839CE1E1831C39B740DDB9F67F27AEBC540DB94BF95C7DEE200AC60A2BF0F64B9F4772A163E036D8DC8E865EFD5B3E7A9442BDF43BA86660D305C15DB2A3A8F5F6E3D1F50E234B193DD787B89E3EDF045E280285474A027E8985F45D883E14593D91CF79017E3AEBCF8A155DD0B5C85BE0A4301D0F80C99A15D154DF54FFE8EB603DA85184386452ABB47C985EF1D5390FF74516A7F0B8A05380DD186AA6FA584287F8AAE6421D98AD84601D734EA008CE0B37FF574BD1C9FE948DAB; //expect:019000 80360001B8F0A78F4E691FC0A9CAE6DC1288BD2E295CFB31443F09AF16B5D66886BA7AEF2FF272E443ADBA47798F76EF6B4594CEC399526F21236AD3A2C05DECFACFC439CA7AB1EC89F554FF982FB7E8E95FFFC863DFEFE5883EAD5A5591C90D69097BE26ACB2C2EA5FB386FF41AF33AE593EA7418906BC5E912474A4F41D68A04013CACE7C5EBE79EA869397FBA545CB197A3F68E3F2E104C2171C9DD798C4B13DC8FFF0811F5FDBD236EC701B4E2369594B2B48D9341ACF993B33FC5; //RSA -2048 encrypt 80378800643E78AA266AA64FED361D907305CD70438AA5F0E674AAD69E5146AD57ACE20DDA79B71C44B4E055B644B4884F25542257C680AFBDB0AF9DC4695E43F998A8226869176A0F33BAC09359773E326EA3BBF99CD04D3746E60D31EC761A174F4AE137D6419B71; 8037880164315A16EB3C0EB90626E3C390D23ED33B7D78AD4D3E78AA266AA64FED361D907305CD70438AA5F0E674AAD69E5146AD57ACE20DDA79B71C44B4E055B644B4884F25542257C680AFBDB0AF9DC4695E43F998A8226869176A0F33BAC09359773E326EA3BBF9; //expect:50237853BC0EBF1537BACA8022795F75FBCF4DDAF18FB99464F68E2E29D7023159BE25219D4493EADB048811304301507EEECEEC0056665E77960D338B4AB52B00B2235E2CF390B1BFDB77716C82493D719228385B707D56DAB30C06661218F162181E90094E32C5D1879F1401B3B17CE961297977CA7C97B2C10FC0FF104780A360150C797EDFA60677C200AA78F3EDCC99FDA1BCE14961A65C4F41552EE575EFB07F4074C8071F80AE083F1AA2BFDB0007A824A7828BBFB583D96B6D6EAD84F9124CA9B7A41EC522630C605886E8EAD146A6C837ED88BC39D779541B5586B518F20554FF8D1496B9EB17A3954FBCB9F3E7C5B6F01DA8C973E4B41A96B32F5C9000 80370802389CD04D3746E60D31EC761A174F4AE137D6419B71315A16EB3C0EB90626E3C390D23ED33B7D78AD4DA2353B9A1AF1D2AFA2353B9A1AF1D2AF; //RSA -2048 decrypt 80378900C850237853BC0EBF1537BACA8022795F75FBCF4DDAF18FB99464F68E2E29D7023159BE25219D4493EADB048811304301507EEECEEC0056665E77960D338B4AB52B00B2235E2CF390B1BFDB77716C82493D719228385B707D56DAB30C06661218F162181E90094E32C5D1879F1401B3B17CE961297977CA7C97B2C10FC0FF104780A360150C797EDFA60677C200AA78F3EDCC99FDA1BCE14961A65C4F41552EE575EFB07F4074C8071F80AE083F1AA2BFDB0007A824A7828BBFB583D96B6D6EAD84F9124CA9B7A41EC5; 803709013822630C605886E8EAD146A6C837ED88BC39D779541B5586B518F20554FF8D1496B9EB17A3954FBCB9F3E7C5B6F01DA8C973E4B41A96B32F5C; //2048-CRT //set public Key RSA CRT-2048 80338100C8AF536A413B40AD9D363E2A8192986A4F054C1C4BE30D47EDD76A32D1AA7EE9A9F91E5BA81D20819B5A5293D8C39F8549E3695E13BE12B19405110D2FBED0E393016D231B4201408CDE963377F802579313ECBBB49320B09D8216374EC50A70D70AE1DE5E0E05AD1B7A1F57638674309FB544EB35CBB5535D3C4C727FF633C6CFFF44F0E141B38074B5C92EF26A57B173F3DDE85C5D4F0B2A3F06E4F1961BB07712D9D0B901EDC8CEA67AEDDBBA0C7EA08857B6934168AF893E7F419DE51E45EEF8272274D85F89D8; 803301013B95E867318D75FADC8AA35FC053B3E02EABA50B2D7B61F0F3EB7A4BCE1DDB43B6887C93580F8BAED5B5236EC69A7D1C42CCE978A98160AC51010001; //set private Key RSA CRT-2048 8034C100C8E7F037F8E89DF110BA672C16BDE2930EA223E2CF63FC030650DCA03289DD4FBE1056975FCB4566822E18C9A22437FA8685C7978187E1A72860E4BE19BEAA4A88A9C1A64F3186E39E6618039418528006281ADD687842CF8D27198C6D1E16166A4CE5A983263A776A5DCA829FC2F76B1A9369F5B5B2A62382593E8E00B3D36795C183B0BEB5D5171EC3DC28BD4BFE637F76AB6874EB6E7BCDAC5F782C7FD38C3A71394FA503DA1519413D60577AD831257E8C77356952B9F1BDF909FADC609F05002A532D6FFBEBAD; 8034C101C84E68A2FF5914E2A331CFC001586F74ACE4FFD23C2FB584B175070E2C3AC414259DC831536116BA669DB636FA82E65CE1C2D873E2B40552CDCAEDFEE1BCFBF77E31D1F82908A8B54CE471F58FF3B0B79EB00DE1D195033D52EA0DA48401961227A4D48E488081701DF08997D4C29BEAD4BF2F3BD1AB9431AA9775ED5A63958984BA30868AAE23BD2BBB1815764F5896BFD5AEC2FF2B08D23A7EC18D358C3D2E99798E0C9DABDD145A3F7E7FC741097762853E882DFCFEF0165153C60C9D646456FD45980C11611537; 8034C102C8985B04F8BB926E6D14858816B088CDA15391495AE9A7D81DE594037FBB3B75B91DC7B2B454B5272BDD6DD7CAA73487160C903E849E55321324B15EEFDAE772C4B5E355A78023CD2B2D7EA3E2CF1DE7963688813BDF77B8CFAF3B873A05DF43CAF9CDB9BE9079F91187C18B816B8CC151720904B29DBC80EF6443ECCE00665C83D48E95F3B0795F0388BC89B8CF6AFE8BC2051FE6022B159BD8522EDFDE48604DD4113A7E831E78ECF82235BB5AFAA53AF129FFF21AB7BDDE57025A6B57377386EFE7992231D71C4E; 803441032876743A93B519A6A45C6E57EFC081A3CDB6F92DF81092B02DA06AAC635B981CCBFD62488823C5AF51; //sign RSA CRT-2048 80358000C8111111413B40AD9D363E2A8192986A4F054C1C4BE30D47EDD76A32D1AA7EE9A9F91E5BA81D20819B5A5293D8C39F8549E3695E13BE12B19405110D2FBED0E393016D231B4201408CDE963377F802579313ECBBB49320B09D8216374EC50A70D70AE1DE5E0E05AD1B7A1F57638674309FB544EB35CBB5535D3C4C727FF633C6CFFF44F0E141B38074B5C92EF26A57B173F3DDE85C5D4F0B2A3F06E4F1961BB07712D9D0B901EDC8CEA67AEDDBBA0C7EA08857B6934168AF893E7F419DE51E45EEF8272274D85F89D8; //expect: 7008B8ACE976C4024F5148DCCF30DE9CEF6D330FE803B8516A8099CF795C9C57EF9092F1BA7CB75018BF0A7378062FC6D23208CE916F55E0BA471A977CE86FB3E6AAD1282E33E8E5B8FCCF31B2FF689127C292F9B8CC0F07DDDA17A4B870510F6E19187184C3749D1CA957AB2CDE752D459C3D9427A16168BDF1705536E87A97FAAEC1485F90857A0EB2A8DAF5EEDD59F8285D2E65B8D4DEB24EE59A72645B263D02D604EEE03F93EC04EDC8CBC08619E863B2C4A521244A101C6D2EA3E789F1616CE2DFA11190A6C928C0BE4117DF4555DEA280645454CFD755C3B547813FC46667C96223EC5458A9FCB51BBF9524183F0CF3A00A89B812F597CC7285573E7D9000 803500013895E867318D75FADC8AA35FC053B3E02EABA50B2D7B61F0F3EB7A4BCE1DDB43B6887C93580F8BAED5B5236EC69A7D1C42CCE978A98160AC51; //verify RSA CRT-2048 80368000C87008B8ACE976C4024F5148DCCF30DE9CEF6D330FE803B8516A8099CF795C9C57EF9092F1BA7CB75018BF0A7378062FC6D23208CE916F55E0BA471A977CE86FB3E6AAD1282E33E8E5B8FCCF31B2FF689127C292F9B8CC0F07DDDA17A4B870510F6E19187184C3749D1CA957AB2CDE752D459C3D9427A16168BDF1705536E87A97FAAEC1485F90857A0EB2A8DAF5EEDD59F8285D2E65B8D4DEB24EE59A72645B263D02D604EEE03F93EC04EDC8CBC08619E863B2C4A521244A101C6D2EA3E789F1616CE2DFA11190A6; 80368001C8C928C0BE4117DF4555DEA280645454CFD755C3B547813FC46667C96223EC5458A9FCB51BBF9524183F0CF3A00A89B812F597CC7285573E7D111111413B40AD9D363E2A8192986A4F054C1C4BE30D47EDD76A32D1AA7EE9A9F91E5BA81D20819B5A5293D8C39F8549E3695E13BE12B19405110D2FBED0E393016D231B4201408CDE963377F802579313ECBBB49320B09D8216374EC50A70D70AE1DE5E0E05AD1B7A1F57638674309FB544EB35CBB5535D3C4C727FF633C6CFFF44F0E141B38074B5C92EF26A57B173; //expect:01 90 00 8036000270F3DDE85C5D4F0B2A3F06E4F1961BB07712D9D0B901EDC8CEA67AEDDBBA0C7EA08857B6934168AF893E7F419DE51E45EEF8272274D85F89D895E867318D75FADC8AA35FC053B3E02EABA50B2D7B61F0F3EB7A4BCE1DDB43B6887C93580F8BAED5B5236EC69A7D1C42CCE978A98160AC51; //encrypt RSA CRT-2048 8037C800C8111111413B40AD9D363E2A8192986A4F054C1C4BE30D47EDD76A32D1AA7EE9A9F91E5BA81D20819B5A5293D8C39F8549E3695E13BE12B19405110D2FBED0E393016D231B4201408CDE963377F802579313ECBBB49320B09D8216374EC50A70D70AE1DE5E0E05AD1B7A1F57638674309FB544EB35CBB5535D3C4C727FF633C6CFFF44F0E141B38074B5C92EF26A57B173F3DDE85C5D4F0B2A3F06E4F1961BB07712D9D0B901EDC8CEA67AEDDBBA0C7EA08857B6934168AF893E7F419DE51E45EEF8272274D85F89D8; //expect:45ACD17EE02228DE45096F1153EF89DBF72933925A17803142A093FD2300CE27CF26A1B38F402E167647035227E0CBB238208A7E166E9DD4F563E04D48C9916C6812AA40AF4715C2D70D32190BC4F9EC2DA0FAD7EFE703AE2808401AA389698BC7428E9172B868E328DA5698CACDBE489EA871225DBEBB238B015828E4B68B274175910D1F72D8D684D24A40077F3A5C75F086A57B733C74CC94C7377A8F555DCB638A4A336344D9B2D53594E7C24BF3FA85705C2E6818B9703EDBBEFDCFA2FC42D3791816025BE4D3045ABF37AEEDF290B90D93E151AFA128E50A271A19AAA7988EBBACF17D26AAF8AAEA0C027186E2715E3A850971F5F16E44DB4FFACE07D09000 803748013895E867318D75FADC8AA35FC053B3E02EABA50B2D7B61F0F3EB7A4BCE1DDB43B6887C93580F8BAED5B5236EC69A7D1C42CCE978A98160AC51; //decrypt RSA CRT-2048 8037C900C845ACD17EE02228DE45096F1153EF89DBF72933925A17803142A093FD2300CE27CF26A1B38F402E167647035227E0CBB238208A7E166E9DD4F563E04D48C9916C6812AA40AF4715C2D70D32190BC4F9EC2DA0FAD7EFE703AE2808401AA389698BC7428E9172B868E328DA5698CACDBE489EA871225DBEBB238B015828E4B68B274175910D1F72D8D684D24A40077F3A5C75F086A57B733C74CC94C7377A8F555DCB638A4A336344D9B2D53594E7C24BF3FA85705C2E6818B9703EDBBEFDCFA2FC42D3791816025BE4; //expect:111111413B40AD9D363E2A8192986A4F054C1C4BE30D47EDD76A32D1AA7EE9A9F91E5BA81D20819B5A5293D8C39F8549E3695E13BE12B19405110D2FBED0E393016D231B4201408CDE963377F802579313ECBBB49320B09D8216374EC50A70D70AE1DE5E0E05AD1B7A1F57638674309FB544EB35CBB5535D3C4C727FF633C6CFFF44F0E141B38074B5C92EF26A57B173F3DDE85C5D4F0B2A3F06E4F1961BB07712D9D0B901EDC8CEA67AEDDBBA0C7EA08857B6934168AF893E7F419DE51E45EEF8272274D85F89D895E867318D75FADC8AA35FC053B3E02EABA50B2D7B61F0F3EB7A4BCE1DDB43B6887C93580F8BAED5B5236EC69A7D1C42CCE978A98160AC519000 8037490138D3045ABF37AEEDF290B90D93E151AFA128E50A271A19AAA7988EBBACF17D26AAF8AAEA0C027186E2715E3A850971F5F16E44DB4FFACE07D0;