首页 > 解决方案 > 将 SMIME 编码为 pkijs 到 Openssl 并返回

问题描述

我在从pkijs编码 smime和在 openssl 中解码时遇到问题。

pkijs 示例使用邮件标题中的行尾问题进行编码,在复制时需要更正该问题。

我注意到两个实现之间的输出中尾随“A”的不同,这让我认为这可能是填充的不同。但是,我看不到如何在 S/MIME 的任一实现中更改填充。我尝试了 OpenSSL 的 -stream 开关,因为它确实改变了填充,但增加了太多。

首先,这是示例密钥/证书:

-----BEGIN CERTIFICATE-----
MIIC0zCCAb2gAwIBAgIBATALBgkqhkiG9w0BAQswHjEcMAkGA1UEBhMCUlUwDwYD
VQQDHggAVABlAHMAdDAeFw0xNjAyMDEwNTAwMDBaFw0xOTAyMDEwNTAwMDBaMB4x
HDAJBgNVBAYTAlJVMA8GA1UEAx4IAFQAZQBzAHQwggEiMA0GCSqGSIb3DQEBAQUA
A4IBDwAwggEKAoIBAQDdZqM9YUi5NLmuYwJGZ7AIjFttRNop/m0AgLemdzn5+99X
cM5fdljRehv4Fnwr6s8KVn86k63LeHaj7v760ZpzudpFWoT8uEbTmUQbixniBg4I
BVIuB7NRVqR+ee8KjVKQqnRsjGDRBmq+H1s5IKmIrYYxS+jYx5bE702hDniy6/yO
N75ABMaiQA0cKkTkvIeCfisMSFhZBasuyDfvbF+Wra4sPPU7Nrt10BJLBDaba84f
tS/fKCqcn8GiZ96evhW/2b2YiV9GLAdBblr+HKydTEfizWZluRasQI2tVMgSx2Qb
6R+/QsKene/IV8pkp+hgm1SXIJ+JLIyYOifCLJ5LAgMBAAGjIDAeMA8GA1UdEwQI
MAYBAf8CAQMwCwYDVR0PBAQDAgAGMAsGCSqGSIb3DQEBCwOCAQEAEnbp8gEOIHXr
QJ/eGJ2C1nP3MaUYNomR96mrQVvr8nddqYBro5Pm441xqmFMbnEmlDzkgLFz8qeH
qgAVD5YIlzAboJRGIUM0gX4L+dThrwvAvMlYXNCc77hE6WXJqboOKI7pmnfhu9Iy
fuZE/njX93ywVNPiAAZ/qnvX3rJUBv6U05vHnu9P8FCqdrd7M4wxo3s7cOguvgMI
CUepOyzWYgtbqlFOBtVl/TbeY2KNzMUhD+NpNs5VGci9OH06icJQIfYA4Lm0uaMd
KUFH1hkdoJdMZ/nbAYBOL2BAQJOh52ELSgPz6KGNvDMMU7z1BQNE8zHbyXWwIcJG
iwAY4ZS5gA==
-----END CERTIFICATE-----
-----BEGIN PRIVATE KEY-----
MIIEvwIBADANBgkqhkiG9w0BAQEFAASCBKkwggSlAgEAAoIBAQDdZqM9YUi5NLmu
YwJGZ7AIjFttRNop/m0AgLemdzn5+99XcM5fdljRehv4Fnwr6s8KVn86k63LeHaj
7v760ZpzudpFWoT8uEbTmUQbixniBg4IBVIuB7NRVqR+ee8KjVKQqnRsjGDRBmq+
H1s5IKmIrYYxS+jYx5bE702hDniy6/yON75ABMaiQA0cKkTkvIeCfisMSFhZBasu
yDfvbF+Wra4sPPU7Nrt10BJLBDaba84ftS/fKCqcn8GiZ96evhW/2b2YiV9GLAdB
blr+HKydTEfizWZluRasQI2tVMgSx2Qb6R+/QsKene/IV8pkp+hgm1SXIJ+JLIyY
OifCLJ5LAgMBAAECggEARAzJjNKrhx2BGuwcpWY2UZJOganhgnnMqBRoHjbUL5Vu
otIt5GKcTxqAoULL/LWp2GwYo/kDOKB4ms+ZOJ+XIQ3VXG7DpGfBgUVBDVQ2auXg
hy+XgEVmpNAENEmnIu+oGoYBzeFh2q1lvrUllUwIP9XSArHpykOigDprel7X02op
1wlIdXmEECMlFOL160l9E+KrJQ1OHarO98VkCXkMSvnjpOCwkva3d2F/ty/STt+l
+Hh8xJkkXrIcY1N1+NcJaWDtBnbA6/vRtqtnnsA3uCraXMfz5NMnkAYFJEYTraWs
AujbPmiQtl41/QARvBsPW2CsznUnIwupf4WJFFSakQKBgQD4HjdV2/mmJqf40wDs
ufC2eKndpQEXchRlvV7/sJQ61Rns9qRW9b1V+PvLR5/63WIFMFhxTakYozoZNlHt
6g+C5BCung21rbIjtGPMBO9ef0NqnH6+jEuIYgabP8qeJxjVvMJjDoANVOQbZApx
cK06QdFgYDsdzc57TYbSABwVOwKBgQDkbyYGoz6l31/qjLVT/ttKj8ovjdGF9lCS
rGg5eT8gRqe7QHu+k0Lbgbw5iH8wVw2K1pZEkAk3JkjttiKyNNTF7hNPnEtjtpLq
l34kN6Lx1W9CRrdeInpEHNk2NOTMGe//h6mPRawUHZu0inQJViHKwQd5mR36KHml
JnEdS2TKMQKBgQDcyZaYEo1OqqtiIfF6teNbnHgbwY79HAjGmAMHKExfJe5SDRAk
SbxX2p3FQFE93O4yi9jHykGkqOs0MEAro9J1uRiXKhItDwmr+AOuMt4Gityk6+ll
ClbUX9ZdJCDbJxNUbwnTN73/HwF01krss0WSx6rXRgqU9OS+mDhWer6CrQKBgQCE
rMm5MTdBv+tFn1Px5SQYuksEM6pt1BIYHmqqdvFjHaZt65XzqjQ6qa9Y+x5kRSto
aBn+2GmBzoqtBgxA1M5/5zbwFibzUychebuZ7XaGXyCvrcLyubOpu9es1CvPH4F1
OKYSwLShOlElGwUqJwyZZmOhDH2MvdVpRlqMWS3BAQKBgQCDvoAQsQLfHxo5HJJS
JtJ8u74ovseWtgQ69fSdvNSvltPywqnf4B2/3pNIqiHwKRE37Pkud9jrSkGwmwVy
I6jRv2D1e/pZoJ4D02t9SJyR5mlcYi4o7aS55zc+vmmCxbkjEW2URSIAzN9Na+1H
jWJB9zp+KqVdmEMJ0mEAGkS15A==
-----END PRIVATE KEY-----

输入文本:

Test message.

pkjs 的输出:

Content-Type: application/pkcs7-mime; name=smime.p7m;
 smime-type=enveloped-data
Content-Description: Enveloped Data
Content-Disposition: attachment; filename=smime.p7m
Content-Transfer-Encoding: base64
From: sender@example.com
To: recipient@example.com
Subject: Example S/MIME encrypted message
Date: Tue, 15 May 2018 17:00:32 +0000
Message-Id: <1526403632814-3b7a2ea4-7320c042-592c9bb6@example.com>
MIME-Version: 1.0

MIIBzAYJKoZIhvcNAQcDoIIBvTCCAbkCAQIxggFuMIIBagIBADAjMB4xHDAJBgNVBAYTAlJVMA8G
A1UEAx4IAFQAZQBzAHQCAQEwPAYJKoZIhvcNAQEHMC+gDzANBglghkgBZQMEAgMFAKEcMBoGCSqG
SIb3DQEBCDANBglghkgBZQMEAgMFAASCAQBl6V6YXtfHy311tnekTnpL+3c+jCYTc0sd0zU66qrH
Twnc+HsyYmELgiNhJflIeqnJmzDNr2h0kGCOjCkk5P3qQJf7Bg5iwL9nSgoNCZ3mstem4Htw2eTE
3CxxlnThL3MMG59N9rzod6PAx8LMCNC//G9c4oFttaBVeoF4ajYCc2eD86jQeq6lfKr/G3jzv3Kh
eASvTjfnr+lMdCfEl5vQf1F+ze5HLv1WTSJTU3Pg6yCy7m7f5qD8t6f4zeuCZpXHtBgkEvnAGP8F
TksSkMdXlBWTc4p1oU6qpZZZ8CIbRi0Te3CB/Xv7hJ2FYMXJeER8vHGuUjg9Lh7mW59ljESKMIAG
CSqGSIb3DQEHATAdBglghkgBZQMEAQIEEKg1Uq+ZtYZOsznseHSCoCiggAQQZcFd4TBnsu8jujXB
7cNEfQAAAAA=

我修复了第一行以使消息邮件确认。我用来解码 pkijs 输出的命令是:

`openssl smime -decrypt -inkey privkey.pem -in smime2.txt
`

失败了:

解密 PKCS#7 结构 140101493268928 时出错:错误:06065064:数字信封例程:EVP_DecryptFinal_ex:错误解密:crypto/evp/evp_enc.c:536:

我可以使用相同的两个密钥通过 OpenSSL 使用以下命令加密消息:

openssl smime -encrypt -aes-128-cbc -to recipient@example.com -from sender@example.com -subject 'Example S/MIME encrypted message' -recip cert.pem -inkey privkey.pem cert.pem < text.txt

和输出:

To: recipient@example.com
From: sender@example.com
Subject: Example S/MIME encrypted message
MIME-Version: 1.0
Content-Disposition: attachment; filename="smime.p7m"
Content-Type: application/x-pkcs7-mime; smime-type=enveloped-data; name="smime.p7m"
Content-Transfer-Encoding: base64

MIICagYJKoZIhvcNAQcDoIICWzCCAlcCAQAxggE/MIIBOwIBADAjMB4xHDAJBgNV
BAYTAlJVMA8GA1UEAx4IAFQAZQBzAHQCAQEwDQYJKoZIhvcNAQEBBQAEggEAjRqC
OSNTOeCh1ahGIthW6vcXY9igY7596TkPbKQ2PRaDm37bUVd3149rPs7oKu2x+76d
ef71tZwomQeGVbgOYjWWtvz0hXXQEfPZLKHHzW9xu8EDnVQ56/wMBv0iRm4MoUS7
GlFfX/n+njx0QrkOvF2jbfvXp8RvLlns4D+jBJRolN8fbnGvTJBinBC6vp/294rU
a9dZT700+183SaJk0Ae9V1RmmOf84l02LL5CiWV8yI2xXzZ1X9LavykcsCp/2/p6
JsC+gs6SWQbLSRMhvsLk6GPAnydU4NZwDrsvHiKJeTee/1j8rGUrYNSSUWfrY4dx
ntqpD7rVHTXdw1rYATCCAQ0GCSqGSIb3DQEHATAdBglghkgBZQMEAQIEEO4cxDny
6P70fYp8TIzkmxSAgeAH9a+r7a1li2npEH7gx+kOZXvwrLwbEXy0/yb5y7OMW+y5
OKra4VuyprXUldhBKVlUNSdvhNSHFJqVPeK16YufUlwOJEMGPjDuiz4jyhrAMzQS
zo7jstOGZu8erY8cFzbEYapX5NpMbedZa0RhRJ23706v5dUtxzz5jgGBwjcg5XFe
hKwKvqlX+ISl2aiAQAXdf/GsTbP1QCn1eIuQmGQf/CiU4haNsIDF0WmwJlKa15QM
K7mUdsKbCAgPD4WpAweL9yGBAJ4nFIOIOi6CmZAqxns6gi4VIHmgBKH80080kA==

尝试在 pkijs 中对此进行解码有一些问题,需要修改标准示例代码。我克隆了在线示例并将 SMIMEEncryptionExample.js 文件内容更改为 sed,将所有“innerHTML”实例替换为“value”,以便脚本可以访问用户发布的数据。

尝试以 pkijs 形式解码此数据会导致:

解密过程中的错误:错误:对象的架构未针对 RSAESOAEPParams 的输入数据进行验证


更新。查看源代码发现 pkijs 使用 CMS,我能够使用以下命令解码浏览器编码的消息:

openssl cms -decrypt -aes-128-cbc -recip cmscertkey.pem -inkey cmskey.pem

此命令可用于查看编码消息的结构:

openssl cms -decrypt -aes-128-cbc -recip cmscertkey.pem -inkey cmskey.pem -noout -cmsout -print

以下是浏览器生成消息的一些有趣输出:

         keyEncryptionAlgorithm: 
          algorithm: rsaesOaep (1.2.840.113549.1.1.7)
          parameter: SEQUENCE:
    0:d=0  hl=2 l=  47 cons: SEQUENCE          
    2:d=1  hl=2 l=  15 cons:  cont [ 0 ]        
    4:d=2  hl=2 l=  13 cons:   SEQUENCE          
    6:d=3  hl=2 l=   9 prim:    OBJECT            :sha512
   17:d=3  hl=2 l=   0 prim:    NULL              
   19:d=1  hl=2 l=  28 cons:  cont [ 1 ]        
   21:d=2  hl=2 l=  26 cons:   SEQUENCE          
   23:d=3  hl=2 l=   9 prim:    OBJECT            :mgf1
   34:d=3  hl=2 l=  13 cons:    SEQUENCE          
   36:d=4  hl=2 l=   9 prim:     OBJECT            :sha512
   47:d=4  hl=2 l=   0 prim:     NULL              

以下命令将使用来自 openssl 的 RSA-OAEP 对消息进行编码:

`openssl cms -encrypt -in text2.txt -from sender@example.com -to recipient@example.com -subject Testing -aes-128-cbc -recip cmscert.pem -keyopt rsa_padding_mode:oeap`

此命令生成的消息:

    收件人:receiver@example.com
    来自:sender@example.com
    主题:测试
    MIME 版本:1.0
    内容处置:附件;文件名="smime.p7m"
    内容类型:application/pkcs7-mime;smime-type=封装数据;名称="smime.p7m"
    内容传输编码:base64

    MIIBpwYJKoZIhvcNAQcDoIIBmDCCAZQCAQAxggE/MIIBOwIBADAjMB4xHDAJBgNV
    BAYTAlJVMA8GA1UEAx4IAFQAZQBzAHQCAQEwDQYJKoZIhvcNAQEHMAAEggEArEtI
    zD/OyE2y4cDuBenOuVQOK5brGsTLrSfpaSU1yJxPxA69oF5YmDi6Fo192IykhVQQ
    2gLaxq7rQv6+8z98RJ/R2vBm0kncKJ6908rd5O0y7Fg3GGnI4qDvrqxOmr47lHOb
    qZ8HJgrMTKn4S1LBVBENcnhtQFzAfMleLnc6hw6VDjowPYm8CTdtbjVCf1fNQ/wW
    E9QMLn3DVcDW861rK7oqf6ZT5srDVmHxNqlC17WcUR0Uhhfe8Zru8GMw4lM9/xhy
    PamXyBoCjhYLDhh9H+Ti7sQxXOEbgGz7HP5K5v7wofdStwAnbX42y7iasqpV0lvy
    RIRe32VGNw9wJBN82jBMBgkqhkiG9w0BBwEwHQYJYIZIAWUDBAECBBCSb7qkkRBQ
    d9bbdRTPY+ZigCDLIZ/IJjcCmjpmEXPT3UwXyWf5EP5S80CpRma4MvnMjQ==

这会在浏览器中解码时清除 RSAESOAEPParams 错误,但会导致新的错误:

解密过程中的错误:DataError:JWK“alg”成员与 Web Crypto 调用指定的成员不一致

OpenSSL 与最新命令输出的 cms 结构的有趣区别:

        密钥加密算法:
          算法:rsaesOaep (1.2.840.113549.1.1.7)
          参数: 序列:
    0:d=0 hl=2 l= 0 缺点:序列          

主要是缺少包括mgf1在内的密钥加密算法参数。

我查看了源代码,找不到通过命令更改 OpenSSL 中这些参数的方法。

标签: javascriptopensslpkismimeclient-side-scripting

解决方案


我在 PKI.js 网站上发布了一个问题,他们修补了他们的示例代码 javascript 代码。我现在可以在 PKI.js 和 OpenSSL 之间使用双向加密。


推荐阅读