【问题标题】:How to get exponent and modulus value of RSA public key from pfx file/pem file in java如何从java中的pfx文件/pem文件中获取RSA公钥的指数和模值
【发布时间】:2023-11-06 06:43:01
【问题描述】:

我想使用 java 从 pfx 文件中提取有关 RSA 公钥的信息。

我有一个 pfx 文件并转换为 x509 Pem 文件。从 pem 文件中,在终端中使用以下命令:

openssl x509 -in file.pem -text

我可以查看公钥指数和模值


主题公钥信息:

Public Key Algorithm: rsaEncryption
    Public-Key: (2048 bit)
    Modulus:
        00:da:7c:e0:3e:c4:62:8d:ce:29:04:2f:93:78:7c:
        :
         6a:e7:c9:7c:8b:6f:09:5c:75:5f:8c:5e:9c:6a:b9:
        7:32:90: a4:4b
    Exponent: 65537 (0x10001)

如何在java中提取以上信息?

输入: pfxfile 和密码

输出:公钥指数和模值。

我正在使用下面的代码来提取公钥指数和模数,但我没有得到使用 openssl 提取的值。我怀疑 java.security.cert.Certificate 是否使用其他一些 DER 格式??

openssl 的 java 等价物是什么?

代码:

KeyStore ks = KeyStore.getInstance("pkcs12");
ks.load(new FileInputStream(file), password.toCharArray());
Enumeration enumeration = ks.aliases();
while (enumeration.hasMoreElements()) {
    String alias = (String) enumeration.nextElement();
    java.security.cert.Certificate certificate = ks.getCertificate(alias);
    PublicKey publickey = certificate.getPublicKey();
}

【问题讨论】:

    标签: java security openssl keystore pfx


    【解决方案1】:

    您需要向下转换为透明的java.security.interfaces.RSAPublicKey 类型。然后您可以访问模数和公共指数。

    KeyStore ks = KeyStore.getInstance("pkcs12");
    ks.load(new FileInputStream(file), password.toCharArray());
    Enumeration<String> enumeration = ks.aliases();
    while (enumeration.hasMoreElements()) {
      String alias = enumeration.nextElement();
      Certificate certificate = ks.getCertificate(alias);
      RSAPublicKey pub = (RSAPublicKey) certificate.getPublicKey();
      System.out.println(pub.getModulus().toString(16));
      System.out.println(pub.getPublicExponent().toString(16));
    }
    

    【讨论】:

    • 真的非常感谢.. 我不知道模值是一个大整数。现在我得到了类似于 openssl 输出的值。
    【解决方案2】:

    我添加了这个答案,因为我最近尝试使用 java 从原始公钥字符串中获取模数和指数(另请参阅https://crypto.stackexchange.com/questions/18031/how-to-find-modulus-from-a-rsa-public-key,从中获得以下公钥)并认为其他人可能会找到以下代码有帮助:

    String publicKey = "MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCqGKukO1De7zhZj6+H0qtjTkVxwTCpvKe4eCZ0FPqri0cb2JZfXJ/DgYSF6vUpwmJG8wVQZKjeGcjDOL5UlsuusFncCzWBQ7RKNUSesmQRMSGkVb1/3j+skZ6UtW+5u09lHNsj6tQ51s1SPrCBkedbNf0Tp0GbMJDyR4e9T04ZZwIDAQAB";
    
    try {
            KeyFactory keyFactory = KeyFactory.getInstance("RSA");
            byte[] keyBytes = Base64.getDecoder().decode(publicKey.getBytes("UTF-8"));
            X509EncodedKeySpec spec = new X509EncodedKeySpec(keyBytes);
            PublicKey fileGeneratedPublicKey = keyFactory.generatePublic(spec);
            RSAPublicKey rsaPub  = (RSAPublicKey)(fileGeneratedPublicKey);
            BigInteger publicKeyModulus = rsaPub.getModulus();
            BigInteger publicKeyExponent  = rsaPub.getPublicExponent();
            System.out.println("publicKeyModulus: " + publicKeyModulus);
            System.out.println("publicKeyExponent: " + publicKeyExponent);
        } catch (NoSuchAlgorithmException | UnsupportedEncodingException | InvalidKeySpecException e) {
            System.out.println(e.getMessage());
            e.printStackTrace();
        }
    

    给出预期的输出:

    publicKeyModulus: 119445732379544598056145200053932732877863846799652384989588303737527328743970559883211146487286317168142202446955508902936035124709397221178664495721428029984726868375359168203283442617134197706515425366188396513684446494070223079865755643116690165578452542158755074958452695530623055205290232290667934914919
    publicKeyExponent: 65537
    

    【讨论】:

      【解决方案3】:
      Adding to the above Java Program to extract the n-modulus and e-exponent of the Base64 format of RSA would be as follows.
      
      import java.io.UnsupportedEncodingException;
      import java.math.BigInteger;
      import java.security.KeyFactory;
      import java.security.NoSuchAlgorithmException;
      import java.security.PublicKey;
      import java.security.interfaces.RSAPublicKey;
      import java.security.spec.InvalidKeySpecException;
      import java.security.spec.X509EncodedKeySpec;
      import java.util.Base64;
      
      public class ModulusExpFromPublicKeyRSA {
          public static void main(String args[]) {
              String publicKey = "MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCqGKukO1De7zhZj6+H0qtjTkVxwTCpvKe4eCZ0FPqri0cb2JZfXJ/DgYSF6vUpwmJG8wVQZKjeGcjDOL5UlsuusFncCzWBQ7RKNUSesmQRMSGkVb1/3j+skZ6UtW+5u09lHNsj6tQ51s1SPrCBkedbNf0Tp0GbMJDyR4e9T04ZZwIDAQAB";
      
              try {
                  KeyFactory keyFactory = KeyFactory.getInstance("RSA");
                  byte[] keyBytes = Base64.getDecoder().decode(publicKey.getBytes("UTF-8"));
                  X509EncodedKeySpec spec = new X509EncodedKeySpec(keyBytes);
                  PublicKey fileGeneratedPublicKey = keyFactory.generatePublic(spec);
                  RSAPublicKey rsaPub  = (RSAPublicKey)(fileGeneratedPublicKey);
                  BigInteger publicKeyModulus = rsaPub.getModulus();
                  BigInteger publicKeyExponent  = rsaPub.getPublicExponent();
                  System.out.println("publicKeyModulus: " + publicKeyModulus);
                  System.out.println("publicKeyExponent: " + publicKeyExponent);
                  String nModulus=Base64.getUrlEncoder().encodeToString(publicKeyModulus.toByteArray());
                  String eExponent=Base64.getUrlEncoder().encodeToString(publicKeyExponent.toByteArray());
                  System.out.println("n Modulus for RSA Algorithm: " + nModulus);
                  System.out.println("e Exponent for RSA Algorithm: " + eExponent);
              } catch (NoSuchAlgorithmException | UnsupportedEncodingException | InvalidKeySpecException e) {
                  System.out.println(e.getMessage());
                  e.printStackTrace();
              }
      
      
          }
      
      }
      
      
      publicKeyModulus: 119445732379544598056145200053932732877863846799652384989588303737527328743970559883211146487286317168142202446955508902936035124709397221178664495721428029984726868375359168203283442617134197706515425366188396513684446494070223079865755643116690165578452542158755074958452695530623055205290232290667934914919
      publicKeyExponent: 65537
      n Modulus for RSA Algorithm: AKoYq6Q7UN7vOFmPr4fSq2NORXHBMKm8p7h4JnQU-quLRxvYll9cn8OBhIXq9SnCYkbzBVBkqN4ZyMM4vlSWy66wWdwLNYFDtEo1RJ6yZBExIaRVvX_eP6yRnpS1b7m7T2Uc2yPq1DnWzVI-sIGR51s1_ROnQZswkPJHh71PThln
      e Exponent for RSA Algorithm: AQAB
      

      【讨论】:

      • 虽然此代码可能会回答问题,但提供有关此代码为何和/或如何回答问题的额外上下文可提高其长期价值。
      【解决方案4】:

      根据 JWKS URL 验证 JSON WebToken 会很有帮助。例如,示例 JWKS 密钥如下所示。

      {
        "keys": [
          {
            "use": "sig",
            "kty": "RSA",
            "kid": "c424b67b-fe28-45d7-b015-f79da50b5b21",
            "alg": "RS256",
            "n": "AKoYq6Q7UN7vOFmPr4fSq2NORXHBMKm8p7h4JnQU-quLRxvYll9cn8OBhIXq9SnCYkbzBVBkqN4ZyMM4vlSWy66wWdwLNYFDtEo1RJ6yZBExIaRVvX_eP6yRnpS1b7m7T2Uc2yPq1DnWzVI-sIGR51s1_ROnQZswkPJHh71PThln",
            "e": "AQAB"
          },
          {
            "use": "sig",
            "kty": "RSA",
            "kid": "9b9d0b47-b9ed-4ba6-9180-52fc5b161a3a",
            "alg": "RS256",
            "n": "AKoYq6Q7UN7vOFmPr4fSq2NORXHBMKm8p7h4JnQU-quLRxvYll9cn8OBhIXq9SnCYkbzBVBkqN4ZyMM4vlSWy66wWdwLNYFDtEo1RJ6yZBExIaRVvX_eP6yRnpS1b7m7T2Uc2yPq1DnWzVI-sIGR51s1_ROnQZswkPJHh71PThln",
            "e": "AQAB"
          }
        ]
      }
      

      JWKS的描述如下。

      n:    Modulus of the Public Key
      alg:  the signing algorithm.
      kid:  a unique id for every key in the set.
      e:    Exponent part of RSA algorithm
      use:  This denotes the Signature Validation
      

      【讨论】: