您好我有一个应用程序,我生成密钥对和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);
}
}
由于某种原因,这不起作用,我回来一个空的String回来没有这个代码中提到的错误。
我想知道是否 1.使用openssl加密并使用java充气城堡进行解密。这可以吗?
+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ **
在调试过程中,我发现数据正在被正确解密并附加到MimeBodyPart的标题,但事情变得糟糕,如下所示。
我已经缩小到导致问题的代码。
public MimeBodyPart(InputStream is)抛出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;
}
size = is.available();总是返回0;
+++++++++++++++++++++++++++++++++++++++++++++++++++++ ** 我现在使用java的BC作为提供者生成了另一个加密消息。 这两个创建的加密消息之间的区别在标题方面是这样的。
Bouncy castle生成加密消息:
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 genarted加密邮件头。
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在传递给它时生成了加密消息 final MimeBodyPart res = SMIMEUtil.toMimeBodyPart(... content ...)导致MimeBodyPart标头的设置不同于当弹跳城堡生成消息时通过相同的api时的情况。