1

嗨,我有一个应用程序,我在其中生成密钥对和 x509 证书,然后我使用公钥 (key.pem) 并使用 openssl 将我的数据加密为 smime 格式,如图所示。

openssl smime -encrypt -out encrypted_smime.p7m -in token.json out form SMIME key.pem

加密文件看起来像

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

......

在此之后,我将其作为 serverTokenBytes 的输入作为我的应用程序的输入,它尝试使用此逻辑对其进行解密。

   public static String decryptServerToken(final byte[] serverTokenBytes, final X509Certificate certificate, final PrivateKey privateKey) {
        try {
            final RecipientId recId = new JceKeyTransRecipientId(certificate);
            final Properties props = System.getProperties();
            final Session session = Session.getDefaultInstance(props, null);
            final MimeMessage msg = new MimeMessage(session, new ByteArrayInputStream(serverTokenBytes));
            if (msg.getSize() <= 0 || !(msg.isMimeType("application/pkcs7-mime") || msg.isMimeType("application/x-pkcs7-mime"))) {
                // log error...and throw
            }
            final SMIMEEnveloped m = new SMIMEEnveloped(msg);
            final RecipientInformationStore recipients = m.getRecipientInfos();

            final RecipientInformation recipient = recipients.get(recId);
            if (recipient == null) {
                LOG.error("Error in decrypting the uploaded server token file, the certificate serial number used for encryption differ from the one used for decryption");
                return null;
            }
            final MimeBodyPart res = SMIMEUtil.toMimeBodyPart(recipient.getContent(new JceKeyTransEnvelopedRecipient(privateKey)));
            return res.getContent().toString();
        } catch (final MessagingException | CMSException | SMIMEException | IOException exn) {
            throw new IllegalStateException("Error in decrypting the server token", exn);
        }
    }

出于某种原因,这不起作用,我返回一个空字符串而没有此代码中提到的错误。

我想知道 1. 用 openssl 加密和用 java bouncy castle 解密。这个可以吗 ?

  1. 解密没有失败,只是给了我一个空字符串,有人看到这段代码有什么问题吗?

+++++++++++++++更新1 +++++++++++++++**

好吧,在调试时,我看到数据已正确解密并附加到 MimeBodyPart 的标头,但随后情况变糟,如下所示。

我已经缩小到导致问题的这段代码。

公共 MimeBodyPart(InputStream 是)抛出 MessagingException {

if (!(is instanceof ByteArrayInputStream) &&
    !(is instanceof BufferedInputStream) &&
    !(is instanceof SharedInputStream))
    is = new BufferedInputStream(is);

headers = new InternetHeaders(is);

if (is instanceof SharedInputStream) {
    SharedInputStream sis = (SharedInputStream)is;
    contentStream = sis.newStream(sis.getPosition(), -1);
} else {
    try {
    content = ASCIIUtility.getBytes(is);
    } catch (IOException ioex) {
    throw new MessagingException("Error reading input stream", ioex);
    }
}

并且 ASCIIUtility getBytes 返回 []

public static byte[] getBytes(InputStream is) throws IOException {

int len;
int size = 1024;
byte [] buf;


if (is instanceof ByteArrayInputStream) {
    size = is.available();
    buf = new byte[size];
    len = is.read(buf, 0, size);
}
else {
    ByteArrayOutputStream bos = new ByteArrayOutputStream();
    buf = new byte[size];
    while ((len = is.read(buf, 0, size)) != -1)
    bos.write(buf, 0, len);
    buf = bos.toByteArray();
}
return buf;
}

大小 = is.available(); 总是返回 0;

+++++++++++++++更新2 +++++++++++++++++** 我现在使用java的BC作为提供者生成了另一个加密消息。这两者创建的加密消息之间的差异在标头方面是这样的。

充气城堡生成加密消息:

Content-Type: application/pkcs7-mime; name="smime.p7m"; smime-type=enveloped-data
Content-Transfer-Encoding: base64
MIME-Version: 1.0
Message-ID: <621547276.1.1394777375030.JavaMail.abcd@localhost>

......

openssl 生成的加密消息头。

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

……

openssl 生成的加密消息在传递到最终的 MimeBodyPart res = SMIMEUtil.toMimeBodyPart(...content...) 时会导致 MimeBodyPart 标头的设置与通过相同 api 传递时充气城堡生成的消息不同。

4

0 回答 0