当前位置: 首页 > 知识库问答 >
问题:

RSA我应该使用X.509还是PKCS#1

楚茂实
2023-03-14

用例:I有一个用例,其中客户机生成私钥和公钥,将64位编码的公钥发送给服务器。

在服务器端,我将使用此公钥加密消息,并将加密的消息发送到客户端,客户端使用其私钥对其进行解密。商定的算法是“RSA”。

问题是在服务器端,我看到某些密钥正在使用X509EncodedKeySpec作为密钥规范工作

byte[] publicBytes = Base64.decodeBase64(base64EncodedPubKey);
X509EncodedKeySpec keySpec = new X509EncodedKeySpec(publicBytes);
KeyFactory keyFactory = KeyFactory.getInstance("RSA");
PublicKey pubKey = keyFactory.generatePublic(keySpec);

虽然一些键抛出异常(造成:java.security.InvalidKeyExc0019: IOExc0019: algid解析错误,不是序列)使用X509EncodedKeySpec但使用RSAPublicKeySpec工作:

byte[] publicBytes = Base64.decodeBase64(base64EncodedPubKey);
org.bouncycastle.asn1.pkcs.RSAPublicKey.RSAPublicKey pkcs1PublicKey = org.bouncycastle.asn1.pkcs.RSAPublicKey.RSAPublicKey.getInstance(publicBytes);
BigInteger modulus = pkcs1PublicKey.getModulus();
BigInteger publicExponent = pkcs1PublicKey.getPublicExponent();
RSAPublicKeySpec keySpec = new RSAPublicKeySpec(modulus, publicExponent);
KeyFactory keyFactory = KeyFactory.getInstance("RSA");
PublicKey pubKey = keyFactory.generatePublic(keySpec);

所以,我开始理解的是,客户端和服务器需要同意是否使用:PKCS#1X.509来编码密钥。我的问题是哪一个更适合我的用例?什么时候使用哪种格式?

共有1个答案

方风华
2023-03-14

差别很小。Java的密钥格式调用X.509,更确切地说是ASN。1 X.509中定义的结构SubjectPublicKeyInfo(或SPKI),或RFC5280第4.1节中定义的等效且更方便的结构,是处理大型灵活算法集的一种非常简单的方法:它包括子结构算法标识符,用于识别算法及其参数(如适用),然后是一个不透明的位字符串,它包含实际的密钥信息(已编码),其格式取决于算法标识符(所识别的算法)。

对于RSA,依赖于算法的部分是ASN。PKCS1或更方便的RFC8017附录A.1中定义的结构。1及其早期版本,并在RFC3279第2.3节中复制。1.因此,对于RSA,X.509(SPKI)格式包含PKCS1格式,并且由于RSA没有参数(或者至少没有与密钥相关的参数),唯一的真正区别是X.509格式明确指定密钥为RSA——在您的应用程序中,您已经知道了这一点。

您已经发现,vanilla(Oracle是Sun现在的OpenJDK)Java crypto,也称为JCA Java加密体系结构,直接只支持X.509(SPKI)格式,这是一个次要的优势。但是,如果您使用BouncyCastle,则与Q中的代码相比,来回转换要容易得多;您只需使用org。弹跳船舱。asn1。x509。SubjectPublicKeyInfo类以添加或放弃算法标识符:

    // test data source
    KeyStore ks = KeyStore.getInstance("JKS"); ks.load (new FileInputStream (args[0]), args[1].toCharArray());
    byte[] spkienc = ks.getCertificate(args[2]).getPublicKey().getEncoded();
    System.out.println (DatatypeConverter.printHexBinary(spkienc));

    // extract PKCS1 part of original SPKI
    byte[] pkcs1enc = SubjectPublicKeyInfo.getInstance(spkienc).parsePublicKey().getEncoded();
    System.out.println (DatatypeConverter.printHexBinary(pkcs1enc));

    // rebuild SPKI from the PKCS1
    AlgorithmIdentifier algid = new AlgorithmIdentifier(PKCSObjectIdentifiers.rsaEncryption, DERNull.INSTANCE);
    byte[] spki2enc = new SubjectPublicKeyInfo (algid, pkcs1enc).getEncoded();
    System.out.println (DatatypeConverter.printHexBinary(spki2enc));

请参阅我对类似golang x509的回答。MarshallpkixPublicey对x509。MarshallPKCS1PublicKey(),尤其是以下链接:
将SubjectPublicKeyInfo格式的公钥转换为RSPublicKey格式java
以java
生成PKCS#1格式的RSA密钥传输RSA公钥、javaME、bouncy castle时出现问题

如果你没有BouncyCastle,这就有点难了;你需要编写一个部分ASN.1解析器或生成器。完整的ASN.1处理相当复杂,但是对于这种情况,您只需要一个不算太坏的小子集。(是的,那是微弱的赞美。)如果我有更多的时间,我可能会在以后补充这一点。

一个更大的潜在问题是您的密钥没有经过身份验证。公钥分发的难点在于确保只分发合法密钥,这比微小的格式细节要困难得多。如果攻击者可以用他们的公钥替换正确的公钥,那么受害者就会以攻击者可以轻松读取的方式对假定的机密数据进行加密,而你所有花哨的密码都一文不值。

这就是为什么大多数实际系统不分发裸公钥,而是分发允许验证密钥是否正确的证书。有一些证书方案,但最广泛的是X.509及其Internet配置文件PKIX——事实上,我上面提到的RFC 5280和3279是PKIX的一部分。SSL现在TLS使用X.509。代码签名使用X.509。S/MIME电子邮件使用X.509。(PGP/GPG使用不同类型的证书,不是X.509,而是证书。)Java直接支持X.509证书,与“X.509”(SPKI)公钥一样好,甚至更好。

 类似资料:
  • 问题内容: 我正在使用Clean Architecture开发Android应用程序,并将其迁移到RxJava2.x。我必须向soap服务发出一些网络请求,因此我在域模块中定义了api接口: 我已经读过,由于背压管理,网络请求应使用“ ”进行,因为它是“冷可观察的”。在另一方面,我知道请求的结果将是成功的(与响应)或错误,所以我不知道我是否应该使用或甚至。 此外,我有这样的数据库访问权限: 我不知

  • 问题内容: 我正在使用c / c 为osx和linux开发命令行界面可执行文件。该项目将链接到opencv。我应该使用libc 还是libstdc ++? 问题答案: 我会为每个操作系统使用本机库,即GNU / Linux上的libstdc 和Mac OS X上的libc 。 libc 在GNU / Linux上不是100%完整的,而libstdc 更完整时使用libc并没有真正的优势。另外,如果

  • 问题内容: 和CSS 和有什么不一样?我应该使用哪一个?为什么? 问题答案: 所有这些答案似乎都是不正确的。与直觉相反,在CSS 中不是pixel 。至少不是在简单的物理意义上。 从W3C,EM,PX,PT,CM,IN…阅读本文,了解如何为CSS发明一个“神奇的”单元。的含义因硬件和分辨率而异。(该文章是最新的,最新更新为2014-10。) 我自己的思考方式: px单位是CSS的魔术单位。它与当前

  • 问题内容: 我正在一个将Angular和Underscore都作为依赖项的项目。 当我需要创建对象的副本时,根据当时的心情,我可以使用或 在我看来,这些方法中的一种可能比另一种更快速/可靠/健壮。 假设已经包含两个库,那么这两个函数中的任何一个是否存在使另一个函数更好或更坏使用的已知问题? 问题答案: 关于您的问题: angular.copy和_.clone是不同的。这不是哪个更好的问题,而是关于

  • 问题内容: 我想从文本文件中读取每一行并将它们存储在ArrayList中(每一行是ArrayList中的一项)。 到目前为止,我知道BufferedInputStream写入缓冲区,并且仅在缓冲区为空时才进行另一次读取,这可以最大程度地减少或至少减少操作系统的操作量。 我正确吗-我说得通吗? 如果以上情况是在任何情况下,任何人都想使用DataInputStream。最后,我应该使用这两个中的哪一个

  • 问题内容: 从目前的情况来看,这个问题不适合我们的问答形式。我们希望答案会得到事实,参考或专业知识的支持,但是这个问题可能会引起辩论,争论,民意调查或扩展讨论。如果您认为此问题可以解决并且可以重新提出,请访问帮助中心以获取指导。 8年前关闭。 Python 3.0是beta版,即将发布最终版本。显然,要普遍采用它并最终取代2.x会花费一些时间。 我正在编写有关Python编程某些方面的教程。我想知