Introduction to the S/MIME Toolkit

本文介绍了S/MIME工具包API及其与Cryptographic Message Syntax (CMS)的关系,详细阐述了CMS中定义的主要消息类型——SignedData和EnvelopedData的工作原理。通过具体的MIME消息示例,展示了如何使用这些消息类型进行消息签名和加密。

Overview of CMS

This document provides a brief introduction to the S/MIME Toolkit API. More complete descriptions of individual types and functions will be provided at a later time.

The S/MIME Toolkit API reflects the Cryptographic Message Syntax (CMS) Specification (RFC 2630). You should read that document before attempting to use the S/MIME Toolkit API. For information on other relevant RFCs, see Referemces.

CMS, which is based on PKCS #7, describes various message types that can be used to digitally sign and/or encrypt messages transmitted over an unencrypted communications channel. Two of the message types defined by RFC 2630 are relevant for S/MIME: SignedData and EnvelopedData. The corresponding types in the S/MIME Toolkit API are NSSCMSSignedData and NSSCMSSignedData.

This overview uses the RFC names to discuss basic concepts and procedures. The remainder of this document refers to specific S/MIME Toolkit types and functions listed in http://lxr.mozilla.org/mozilla/source/security/nss/lib/smime/cmst.h and http://lxr.mozilla.org/mozilla/source/security/nss/lib/smime/cms.h, respectively.

EnvelopedData

An EnvelopedData message contains an "inner" message that is encrypted for a set of recipients. The "inner" message is encrypted with a random key using a fast symmetric encryption algorithm such as RC2 or 3DES. The random key itself is transmitted with the EnvelopedData, encrypted with each recipient's public key, so that it can be decrypted only by the recipients using their private keys.

An EnvelopedData message includes:

  • a set of RecipientInfo structures, each of which contains the encrypted content key and the ID of the recipient's certificate used for this encryption. There is one RecipientInfo per recipient.
  • the encrypted "inner" content
  • information about the encryption algorithms used

SignedData

A SignedData message contains an unencrypted message, plus one or more "signer" blocks. Each signer block contains the signer�s certificate, digest values for the message that are encrypted using the signer's private key, and other information, such as the signing time.

By decrypting the digest values with the signer's public key, and then checking whether they are equal to newly computed digests, the receiving software can make reasonably sure that (1) the message has not been altered since the signer signed it, and (2) the message was, in fact, signed by the entity/person identified in the message (assuming that the signer's certificate verified correctly and its issuer is trusted by the receiver).

A SignedData message includes:

  • the "inner" content
  • a set of certificates used in processing the message
  • a set of SignerInfo structures, each of which contains signer identification (pointer to signer's certificate), encrypted digest value(s), and other attributes.
  • for S/MIME messages, an attribute that specifies S/MIME preferences, including the sender's encryption algorithm preferences and identification of the certificate the sender prefers to be used for sending encrypted mail back to the sender
  • information about the algorithms used

Since SignedData messages can contain certificate information, they can also be used for simple transport of certificates. In this case, there is no "inner" content and no SignerInfo structures.

Use of Enveloped Data and SignedData in a MIME Message

Content-Type: application/pkcs7-mime

Depending on the smime-type subheader, MIME messages can be signed or enveloped (encrypted) messages. The content is a DER-encoded CMS message that contains the "inner" content of a SignedData or EnvelopedData structure.

Here's an example of a signed message:

Content-Type: application/pkcs7-mime; smime-type=signed-data; name=smime.p7m Content-Transfer-Encoding: base64 Content-Disposition: attachment; filename=smime.p7m 567GhIGfHfYT6ghyHhHUujpfyF4f8HHGTrfvhJhjH776tbB9HG4VQbnj7 77n8HHGT9HG4VQpfyF467GhIGfHfYT6rfvbnj756tbBghyHhHUujhJhjH HUujhJh4VQpfyF467GhIGfHfYGTrfvbnjT6jH7756tbB9H7n8HHGghyHh 6YT64V0GhIGfHfQbnj75

In this example, the binary data contains a SignedData message, which is the "inner" content plus signature information. The inner content could, for example, expand to this text:

Content-Type: text/plain This is a signed message.

To be displayed appropriately in an email program, the binary data must be fed to a MIME parser and tagged with information about the signatures and their validity.

Alternatively, the inner content can be another S/MIME message, up to arbitrary levels of recursion, with each message in the hierarchy signed or encrypted. A single message that is both signed and encrypted consists of two nested MIME messages.

Binary CMS messages can (but need not) be encoded for 7-bit channels. The information in the Content-Transfer-Encoding header must be used for parsing.

Here's an example of an encrypted message:

Content-Type: application/pkcs7-mime; smime-type=enveloped-data; name=smime.p7m Content-Transfer-Encoding: base64 Content-Disposition: attachment; filename=smime.p7m rfvbnj756tbBghyHhHUujhJhjH77n8HHGT9HG4VQpfyF467GhIGfHfYT6 7n8HHGghyHhHUujhJh4VQpfyF467GhIGfHfYGTrfvbnjT6jH7756tbB9H f8HHGTrfvhJhjH776tbB9HG4VQbnj7567GhIGfHfYT6ghyHhHUujpfyF4 0GhIGfHfQbnj756YT64V

The binary content is a DER-encoded CMS EnvelopedData message containing inner content that must be decrypted before further processing occurs.

Content-Type: multipart/signed

The multipart/signed content type designates clear-signed messages. [what does this mean?] The content to be signed is in the first part (in readable form, with the appropriate content type), and the signature is in the second part (using a SignedData CMS message without inner content). This format is preferred for generation because it can be used even with non-S/MIME enabled user agents. [generation of original message? does this mean that this content type is readable even if the receiving software doesn�t support S/MIME? whereas the other one isn�t?]

Here�s an example of a multipart/signed CMS message:

Content-Type: multipart/signed; protocol="application/pkcs7-signature"; micalg=sha1; boundary=boundary42 --boundary42 Content-Type: text/plain

This is a clear-signed message.

--boundary42 Content-Type: application/pkcs7-signature; name=smime.p7s Content-Transfer-Encoding: base64 Content-Disposition: attachment; filename=smime.p7s ghyHhHUujhJhjH77n8HHGTrfvbnj756tbB9HG4VQpfyF467GhIGfHfYT6 4VQpfyF467GhIGfHfYT6jH77n8HHGghyHhHUujhJh756tbB9HGTrfvbnj n8HHGTrfvhJhjH776tbB9HG4VQbnj7567GhIGfHfYT6ghyHhHUujpfyF4 7GhIGfHfYT64VQbnj756 --boundary42--

add the rest of Christian�s text here? heads are:

Advanced Topics Triple-Wrapped Messages Secure Mail Lists Security Labels Signed Receipts Implications for a Mail User Agent Implementation MIME Parser Glue Code MIME Generator Glue Code Message Composition UI Message Presentation UI Address Book Integration S/MIME Preferences

S/MIME Types and Structures

- follows RFC 2630, Cryptographic Message Syntax, exactly.

Basically, you create a NSSCMSMessage structure and populate it with the info re algorithms, data to be signed or encrypted, certs, etc. and then stream your data through it. [???]

A ContentUnion structure is a Container that specifies the type of content and the content itself. The content can be unstructured data (SEC_Item), structured data (NSSCMSDigestedData, NSSCMSEncryptedData, NSSCMSEnvelopedData, NSSCMSSignedData), or a pointer to something.

A NSSCMSMessage structure contains an NSSCMSSignedData ocbject

SignedData ::= SEQUENCE { version CMSVersion, digestAlgorithms DigestAlgorithmIdentifiers, encapContentInfo EncapsulatedContentInfo, certificates [0] IMPLICIT CertificateSet OPTIONAL, crls [1] IMPLICIT CertificateRevocationLists OPTIONAL, signerInfos SignerInfos } NSSCMSMessage NSSCMSContentInfo - type & content of �outer� data memory stuff inner stuff: algorithm sectitem (digests) callback for getting decryption key

Overview of an S/MIME Application

[say something about streaming model here? anything else? e.g. process of building up nested messages?]

Initialization

Initialization includes initializing the NSPR and NSS libraries, opening the certificate database, and setting the default certificate database. Functions used in the initialization part of an application can include the following:

  • PR_Init. Initializes NSPR. Must be called before any other NSS or S/MIME Toolkit functions.
  • SECU_PKCS11Init. [Initializes PKCS #11? not in SSL Ref, where to document?]
  • SEC_Init. [Initializes NSS library? not in SSL Ref, where to document? Why this and not NSS_Init?]
  • OpenCertDB. Opens the cert database. [Specifies a callback?]
  • CERT_SetDefaultCertDB. Sets the opened cert database to be the default cert database. [not documented in SSL Ref; add it to CERT chapter?]

Building the NSSCMSMessage Object

An NSSCMSMessage object in turn contains nested NSSCMSSignedData, NSSCMSEnvelopedData, and other objects. Each of these CMS objects consists of a content type and content, plus other information required for processing. The basic procedure is to create an NSSCMSMessage, which is the outermost container, and build up the nested objects as necessary for signing or encrypting nested messages.

These are the functions that an S/MIME application typically calls initially to create an NSSCMSMessage object and the chain of objects it contains:

  • NSS_CMSMessage_Create allocates memory for an empty NSSCMSMessage object.
  • NSS_CMSSignedData_Create adds an empty NSSCMSSIgnedData object to an existing NSSCMSMessage object.
  • [others here, e.g. NSS_CMSEnvelopedData_Create?]
  • NSS_CMSMessage_GetContentInfo returns a pointer to the top level contentInfo structure.
  • NSS_CMSSignedData_GetContentInfo returns a pointer to a specified NSSCMSSignedData object's contentinfo. - need to talk more about contentInfo
misc. notes follow
build chain of objects: create signeddata object (sigd) with a call to NSS_CMSSignedData_Create get ref. to contentinfo of your cmsg (cinfo) with a call to NSS_CMSMessage_GetContentInfo get ref. to contentinfo of your signeddata (sigd) with a call to NSS_CMSSignedData_GetContentInfo set content of your data with a call to NSS_CMSContentInfo_SetContent create and attach signer info with NSS_CMSSignerInfo_Create, passing in a cert and an algorithm if you want to include the cert chain, call NSS_CMSSignerInfo_IncludeCerts NSS_CMSSignerInfo_AddSigningTime adds signing time to signer info NSS_CMSSignerInfo_AddSMIMECaps adds profile info (?) to signerinfo ContentInfo ::= SEQUENCE { contentType ContentType, content [0] EXPLICIT ANY DEFINED BY contentType } ContentType ::= OBJECT IDENTIFIER
a name="refs">

References

[formatting to come]

RFC2633 S/MIME v3 Message Specification. The authoritative document. RFC2634 Enhanced Security Services for S/MIME. Some extensions for S/MIME - not required, but growing importance for some. RFC2630 Cryptographic Message Syntax. Describes the format of cryptographic messages used in S/MIME (SignedData, EnvelopedData), plus some others RFC2045-2049 MIME. The basic MIME framework RFC2459 Internet X.509 Public Key Infrastructure. 
### S/MIME 电子邮件安全协议的使用与配置 S/MIME 是一种广泛使用的电子邮件安全协议,能够提供数字签名和加密功能,从而确保邮件的安全性和隐私性。以下是有关其工作原理、配置方法及相关工具的具体说明。 #### 工作原理 S/MIME 使用公钥基础设施 (PKI) 来实现邮件的数字签名和加密。发件人可以通过签署邮件来证明其真实性,并通过加密技术防止未经授权的人读取邮件内容。接收方则需使用与其公钥配对的私钥才能解密并查看邮件内容[^1]。 #### 配置教程 为了启用 S/MIME 功能,通常需要完成以下几个关键步骤: 1. **获取 S/MIME 证书** 用户可以从受信任的证书颁发机构 (CA) 购买或申请免费的 S/MIME 证书。这些证书包含了用户的公钥信息,用于验证身份和加密通信[^3]。 2. **安装证书至邮件客户端** 将获得的 S/MIME 证书导入到所使用的邮件客户端中。例如,在 Windows 的 Outlook 中,可通过“文件 -> 选项 -> 信任中心 -> 电子邮件安全”路径找到设置入口;而在 macOS Mail 应用程序中,则可以在钥匙串访问中管理证书[^3]。 3. **启用签名与加密功能** - 对于签名操作,只需勾选“对此消息附加数字签名”的选项即可。 - 若要加密邮件,应先确认收件人的公共证书已存在于本地地址簿或者联系人列表里,之后再激活“加密此消息的内容和附件”开关[^1]。 4. **测试发送与接收流程** 完成上述配置后,尝试向其他同样具备 S/MIME 支持的用户发送一封经过签名及加密处理过的测试信件,以检验整个系统的正常运作情况[^1]。 #### 示例代码:基于 Go 实现基础 SMTP 发送(未涉及具体 S/MIME 加密逻辑) 虽然直接编码实现完整的 S/MIME 流程较为复杂,但下面给出了一段利用 Go 标准库 `net/smtp` 进行简单文本邮件发送的例子作为参考起点[^2]: ```go package main import ( "fmt" "net/smtp" ) func main() { from := "sender@example.com" pass := "password" to := []string{"recipient@example.com"} msg := "From: " + from + "\n" + "To: " + to[0] + "\n" + "Subject: Hello!\n\n" + "This is a test email." err := smtp.SendMail("smtp.example.com:587", smtp.PlainAuth("", from, pass, "smtp.example.com"), from, to, []byte(msg)) if err != nil { fmt.Println(err) return } fmt.Println("Email sent successfully!") } ``` #### 注意事项 - 在实际部署过程中,务必妥善保管个人私钥以防泄露风险。 - 不同操作系统上的主流邮件应用程序均内置了不同程度的支持程度,请依据实际情况选取合适的方案实施。
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值