Flutter中是否有用于执行RSA OAEP(SHA 256和MGF1)的包或库?

huangapple go评论109阅读模式
英文:

Is there any package or library avaiable in flutter for performing rsa oaep(sha 256 and mgf1)?

问题

在Java中,使用Bouncy Castle库,我们可以执行带有OAEP参数(例如SHA256和MGF1)的RSA OAEP加密。

但在Flutter中,我们只有支持RSA-OAEP和SHA256的库,没有直接支持具体参数(如RSA-OAEP(SHA256和MGF1))的包。

我找到了这个信息,指出PointyCastle的OAEP实现与RSAES-OAEP v2.1或更高版本不兼容(请参见此处):

RSAES-OAEP v2.0

此实现基于RFC 2437 PKCS#1中第7.1节中指定的RSAES-OAEP(RSA加密方案 - 最优非对称加密填充)版本2.0。

重要提示:这与RSAES-OAEP v2.1或更高版本(如RFC 3447,RFC 8017等中所指定的版本)不兼容。这些更新版本在传递给RSA加密原语的编码消息(EM)的开头有一个额外的0x00字节。因此,这个实现与之不兼容,因为这是v2.0的实现,不包含那个0x00字节。这是标准的一个重大变化!

目前,此实现具有以下限制:

  • 散列函数硬编码为SHA-1或SHA-256;
  • 掩码生成函数硬编码为MGF1;以及
  • 无法接受任何编码参数(即P始终为空)
英文:

in java, using bouncy castle library we perform rsa oaep encryprtion with oaep parameters like sha256 and mgf1.

But in flutter, we have only library for rsa-oaep, sha256 sperately. so is there any package that specifies oaep encryption with parametrs specific like, rsa-oaep(sha 256 and mgf1)?

I found this, stating that PointyCastle's OAEP implementation is not compatible with RSAES-OAEP v2.1 or later (see here):

> RSAES-OAEP v2.0
>
> This implementation is based on the RSAES-OAEP (RSA Encryption Scheme - Optimal Asymmetric Encryption Padding) as specified in section 7.1 of RFC 2437 PKCS #1: RSA Cryptography Specifications Version 2.0.
>
> Important: this is not compatible with RSAES-OAEP v2.1 or later (as
> specified in RFC 3447, RFC 8017, etc.) Those newer versions have an
> extra 0x00 byte at the beginning of the encoded message (EM) that is
> passed to the RSA encryption primitive. Therefore, this implementation
> is incompatible with it, since this is an implementation of v2.0 which
> does not have that 0x00 byte. A breaking change in the standard!
>
> Currently, this implementation has the following restrictions:
>
> - the hash function is hard-coded to be SHA-1 or SHA-256;
> - the mask generation function is hard-coded to MGF1; and
> - it cannot accept any encoding parameters (that is, P is always empty)

答案1

得分: 1

RFC3447(从2003年2月起)及其后续RFC确实与RFC2437(从1998年10月起)不同,具体表现为在RFC3447中使用了额外的前导0x00字节,参见RFC2437,第9.1.1.1节,步骤11RFC3447,第7.1.1节,步骤2i

也就是说,在RFC2437中,EM被定义为maskedSeed || maskedDB,其大小为k-1字节,而在RFC3447中,EM被定义为0x00 || maskedSeed || maskedDB,其大小为k字节,其中k是以字节为单位的密钥大小(即以字节为单位的模数大小)。

然而,仔细检查后,这种差异似乎不会导致RFC2437与后续RFC之间的不兼容性:

  • 在加密过程中,字节序列EM随后被转换为正整数m,在RFC中描述为OS2IP(Octet Stream to Integer Primitive),请参阅RFC3447,第4.2节。在此,字节序列按大端顺序解释,因此额外的0x00字节贡献了额外的项0x00 * 256^(k-1)。这是0,因此在两种情况下都得到相同的整数。由于其余步骤相同,因此两个RFC的结果是相同的密文。

  • 在解密过程中,整数m被转换为字节序列EM,按照RFC中描述的I2OSP(Integer to Octet Stream Primitive)的大端顺序进行,参见RFC3447,第4.1节。在这里,与加密一致,在RFC2437中,整数转换为k-1字节(RFC2437,第7.1.2节,步骤4),而在RFC3447中,转换为k字节(RFC3447,第7.1.2节,步骤2c),两者仅在k字节序列的附加前导字节上有所不同(在有效解密的情况下为0x00)。由于相同的剩余步骤,因此两个RFC产生相同的解密值。

因此,从RFC2437到RFC3447(或更高版本)似乎没有任何破坏性的变化。

仍然有可能由于实现本身引起不兼容性。但是,目前没有证据表明存在这种情况:

在我的测试中,使用Dart/PointyCastle实现生成的密文成功地在Java/JDK17和在线工具(例如CyberChef,自2016年以来)中解密。相反,使用Java/JDK17生成的密文成功地在Dart/PointyCastle中解密。

总之,似乎不存在这种破坏性变化。可能RFC被误解,或者已经在不删除警告的情况下修复了实现问题。

因此,您可以使用PointyCastle实现在Java中进行跨平台加密/解密。请注意,Java(SunJCE和BouncyCastle)允许为OAEP和MGF1摘要指定不同的摘要,而Dart/PointyCastle似乎只允许相同的摘要用于OAEP和MGF1。

英文:

It is true that in RFC3447 (from Feb 2003) and later RFCs, in contrast to RFC2437 (from Oct 1998), an additional leading 0x00 byte is used, cf. RFC2437, sec. 9.1.1.1, step 11, and RFC3447, sec. 7.1.1, step 2i.

I.e. in RFC2437 EM is defined as maskedSeed || maskedDB with a size of k-1 bytes and in RFC3447 as 0x00 || maskedSeed || maskedDB with a size of k bytes, where k is the key size in bytes (i.e. the size of the modulus in bytes).

However, on closer inspection, this difference does not appear to result in an incompatibility between RFC2437 and the later RFCs:

  • During encryption, the byte sequence EM is next converted to a positive integer m, described in RFC as OS2IP (Octet Stream to Integer Primitive), see e.g. RFC3447, sec. 4.2. Here, the byte sequence is interpreted in big endian order, so that the additional 0x00 byte contributes the additional term 0x00 * 256<sup>k-1</sup>. This is 0, so that in both cases the same integer results. Since the remaining steps are identical, the same ciphertext results for both RFCs.

  • During decryption, the integer m is converted to a byte sequence EM in big endian order, described in the RFCs as I2OSP (Integer to Octet Stream Primitive), see e.g. RFC3447, sec. 4.1. Here, consistent with encryption, in RFC2437 the integer is converted to k-1 bytes (RFC2437, sec. 7.1.2, step 4) and in RFC3447 to k bytes (RFC3447, sec. 7.1.2, step 2c), both differing only in the additional front byte of the k bytes sequence (which is 0x00 in the case of a valid decryption). From the identical rest, maskedSeed and maskedDB are determined and since the remaining steps are identical, the same decrypted value results for both RFCs.

So there seems to be no breaking change from RFC2437 to RFC3447 (or later).

It is still possible that an incompatibility is caused by the implementation itself. However, there is no evidence for this:
In my tests, ciphertexts generated with the Dart/PointyCastle implementation were successfully decrypted with Java/JDK17 and online tools (e.g. CyberChef, since 2016). Conversely, ciphertexts generated with Java/JDK17 were successfully decrypted with Dart/PointyCastle.

All in all, this breaking change does not seem to exist. Possibly the RFCs were misinterpreted or there was an implementation issue that has been fixed in the meantime without removing the warning.

So you could use the PointyCastle implementation for cross-platform encryption/decryption with Java. Note that Java (SunJCE and BouncyCastle) allows to specify different digests for the OAEP and MGF1 digest, while Dart/PointyCastle seems to allow only identical digests for the OAEP and MGF1 digest.

huangapple
  • 本文由 发表于 2023年8月5日 16:41:36
  • 转载请务必保留本文链接:https://go.coder-hub.com/76840814.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定