测试 EMV 卡的 RSA 密钥

Posted

技术标签:

【中文标题】测试 EMV 卡的 RSA 密钥【英文标题】:Test RSA Keys For EMV card 【发布时间】:2015-08-05 11:33:58 【问题描述】:

根据 EMV 标准,我们需要两个 RSA 密钥。

1) 颁发者 RSA 密钥(将使用 1408 位)

2) ICC RSA 密钥(将使用 1152 位)

这里 Issuer RSA 私钥用于计算 ICC 公钥证书。一张 EMV 卡包含各种标签,如 8F90 (颁发者公钥证书) 9F46 (ICC PUBLIC KEY CERTIFICATE) 等在 SDA/DDA 中使用。

其实我想用java语言个性化一张EMV卡,想自己处理所有的计算。这需要 RSA 密钥(SDA/DDA 需要 RSA Stuff)

EMV 也有 DGI8201-8205

包含 CRT 格式的 ICC RSA 私钥。

我知道这很复杂,但这是深入了解 EMV 技术的唯一方法。任何人都可以告诉我如何获得可以解决我的目的并可以在 EMV 计算中使用它的 RSA 密钥。提前致谢。

【问题讨论】:

【参考方案1】:

如何获取 RSA 密钥

您可以轻松生成自己的 RSA CRT 密钥用于测试目的。我为您编写了以下代码 sn-p 来生成 RSA CRT 1408 位。注意,我使用的所有接口和类都会在java.security.*中找到

public static String byteToHex(byte[] data)
    String r = "";
    for(int i=0;i<data.length;i++)
        r+=Integer.toString(  (data[i] & 0xff) + 0x100,16).substring(1);
       
    return r;
   

public static void main(String[] args) throws NoSuchAlgorithmException       
    KeyPairGenerator keyGen = KeyPairGenerator.getInstance("RSA");
    keyGen.initialize(1408);

    KeyPair keyPair = keyGen.generateKeyPair();

    RSAPublicKey publicKey = (RSAPublicKey ) keyPair.getPublic();
    RSAPrivateCrtKey privateKey = (RSAPrivateCrtKey) keyPair.getPrivate();

    System.out.println("Public Modulus: "+  byteToHex(publicKey.getModulus().toByteArray()));
    System.out.println("Public Exponent: "+byteToHex(publicKey.getPublicExponent().toByteArray()));

    System.out.println("Private Modulus: "+byteToHex(privateKey.getModulus().toByteArray()));

    System.out.println("Private Private Exponent: "+byteToHex(privateKey.getPrivateExponent().toByteArray()));
    System.out.println("Private Prime Exponent DP : "+byteToHex(privateKey.getPrimeExponentP().toByteArray())); // d mod (p-1)
    System.out.println("Private Prime Exponent DQ: "+byteToHex(privateKey.getPrimeExponentQ().toByteArray())); // d mod (q-1)

    System.out.println("Private Prime P: "+byteToHex(privateKey.getPrimeP().toByteArray())); // P

    System.out.println("Private Prime Q: "+byteToHex(privateKey.getPrimeQ().toByteArray())); // Q

    System.out.println("Private Coefficient PQ : "+byteToHex(privateKey.getCrtCoefficient().toByteArray()));  // PQ 

生成的关键组件将如下所示:

Public Modulus: 0095c606a1ca4c5e97afa469c29d0bba478ed9d44f736877ab370a003409a1f04598de1638a394d56e296cd8e52ca37883fd43faa6af299c63180068070ee2f5dbb898d65cc76d0f07a5f2ae6c2b703b069ae5edd4b8c07f2cf642f7f687b5da40a0e877bc5e34c6e0a7fcfbd5f0be1504c03eb0e9b6b3893b4f502e495a56d2e5bce8f28bc2d520aac69af021c1646e285ce226a138e8775164f870856b3f327efaeecf77fa67e520fe37aa053e3a7145
Public Exponent: 010001
Private Modulus: 0095c606a1ca4c5e97afa469c29d0bba478ed9d44f736877ab370a003409a1f04598de1638a394d56e296cd8e52ca37883fd43faa6af299c63180068070ee2f5dbb898d65cc76d0f07a5f2ae6c2b703b069ae5edd4b8c07f2cf642f7f687b5da40a0e877bc5e34c6e0a7fcfbd5f0be1504c03eb0e9b6b3893b4f502e495a56d2e5bce8f28bc2d520aac69af021c1646e285ce226a138e8775164f870856b3f327efaeecf77fa67e520fe37aa053e3a7145
Private Private Exponent: 455cab4f9c4f97f329bdbbd90c401529f4a73ee2f8b0a5d31e2f3c7edd0329322224a027e4e215a1e9ff65c764cfe40d446a8a174dc1b8924fd848551478d9a1c330ccfdb4c1f616f5ac9948b1294dbcb659cbb61b45d2df363499320ce43c04c038b3988f062fcc1d6d3dfcc7a6ff6ad160ace5c8f14662c9f8cc69f790463d65e20cfffea2a3ecd0626b207acad31b25d46688d3facd157285847e08511e8127dc4bdea9ffc1c3b57f1e8be04f9275
Private Prime Exponent DP : 00d634ed8f011db920750a594d23b6066a2181ae8378d5f90b4e701b634f9378c1215015c875b7e852118ed92433772b01f6d315813d45de63edd9f8acee4d819f320e7b50c819160621450a673ea7b61678d1b50a2a13059f
Private Prime Exponent DQ: 1e6bf49a032f5168cfb5817f51f6dac5613bd769c56b96008ca3b1f2e62824efcefd1cfc827c08efd42190db0de54d12b2296b67f71dfc24e9d58927ad61ff3b5492225a84d35188a38f32a9aea0287fe597af3d76540e49
Private Prime P: 00f88b11b520fc307cdddc8f0526172b7d0d25bffb3f46005bfc686101ebea8df24b657abe2118c74968e3106f39ef1b080d9eb134efcaf85a603ae9e8b0a9d5dc8bee0ee3d1de88a57b432080afd99657cdf6bc3a35962fcb
Private Prime Q: 009a445bb5fe1ff143eca24abb8852a76c3b4a40ec5dead5602948f1f2b0e8365a3e885bc886dd48e4219f46d898c465936fb8536144a7674c1a31f9c3c11f63623e8b1c60ce4746d53c737c55479555f7e16871e135aba12f
Private Coefficient PQ : 00b21001cee21e109dfd63dc39c7315bbf45faa835c22c9d0cd1d109c9843fc00285adc7f6bc0cf66e855c2e7155d104858845b9ab5c5ce8db95c65dd566e41ef938d5c594de5af8fda13a32e82162d4b730a453625c2d7783

编辑:您可以创建自己的密钥生成规范,例如:

RSAKeyGenParameterSpec keyGenParameterSpec = 
              new RSAKeyGenParameterSpec(1408, RSAKeyGenParameterSpec.F0);

KeyPairGenerator keyGen = KeyPairGenerator.getInstance("RSA");
keyGen.initialize(keyGenParameterSpec);
//.... rest of the code will be the same I posted above

这一次你会得到:

Public Exponent: 03

【讨论】:

你好 Rakeb,真的很棒。我测试了一下,发现没问题。你能告诉我我们如何确定我们有指数 = 03 而不是 65537 的键吗?此代码为 1152 位和 1408 位密钥返回 65537。 真的是您的大力支持。在这里,我们可以使用这些键开始一些计算。

以上是关于测试 EMV 卡的 RSA 密钥的主要内容,如果未能解决你的问题,请参考以下文章

为 RSA OpenSSL 设置特定密钥

使用密钥大小小于2048的RSA安全密钥创建JWT令牌时出错

使用密钥大小小于 2048 的 RSA 安全密钥创建 JWT 令牌时出错

前后端RSA互相加解密加签验签密钥对生成(Java)

在 powershell 中生成 RSA 密钥对

(转)Linux使用RSA密钥登录远程服务器