【OpenSSL】使用SMIME傳送簽名和加密郵件
1,通訊雙方的證書生成
1.1生成根節點證書
openssl genrsa -out cakey.pem 2048
openssl req -new -key cakey.pem -subj "/CN=rootca.bitbaba.com" -out cacsr.pem
openssl x509 -req -in cacsr.pem -days 999 -signkey cakey.pem -out cacert.pem
1.2生成alice的證書
openssl genrsa -out alicekey.pem 2048
openssl req -new -key cakey.pem -subj "/ [email protected]" -out alicecsr.pem
openssl x509 -req -in alicecsr.pem -days 999 -CA cacert.pem -CAKey cakey.pem -set_serial 01 -name "alice" -out alicecert.pem
openssl pkcs12 -export -in alicecert.pem -inkey alicekey.pem -certfile cacert.pem -out alice.p12
1.3生成bob的證書
openssl genrsa -out bobkey.pem 2048
openssl req -new -key bobkey.pem -subj "/ [email protected]" -out bobcsr.pem
openssl x509 -req -in bobcsr.pem -days 999 -CA cacert.pem -CAkey cakey.pem -set_serial 02 -name "bob" -out bobcert.pem
openssl pkcs12 -export -in bobcert.pem -inkey bobkey.pem -certfile cacert.pem -out bob.p12
2,郵件簽名
openssl smime -sign -in /tmp/msg.txt -signer alicecert.pem -inkey alicekey.pem -nocerts -nodetach -text -out /tmp/alicesigned.eml
提醒:
-nodetach 把資訊原文也包含到base64塊裡面,而不是用mime格式的分隔符單獨放置,比較容易保證資訊不被郵件收發伺服器重構,導致驗證失敗。
-nocerts 是一個可選選項,如果設定的話,alice的證書(公鑰等)不會被包含到簽名信息裡面(base64塊)
-signer 在簽發郵件的時候,指定傳送人的證書位置,這裡指定alice的證書
3,簽名驗證
openssl smime -verify -in /tmp/alicesigned.eml -certfile alicecert.pem -CAfile cacert.pem
注意:
-signer 引數這個時候的意思:匯出簽發郵件的證書儲存。所以要小心覆蓋原有證書
-CAfile 設定信任的ca位置,否則驗證不通過
-certfile 是一個可選選項,如果簽名的時候指定了-nocerts,這裡可以指定驗證證書(alice),這樣網路傳輸經濟。
4,郵件加密
smime -encrypt -in /tmp/msg.txt -from [email protected] -to [email protected] -des3 -out /tmp/msg.eml bobcert.pem
5,郵件解密
openssl smime -decrypt -in /tmp/msg.eml -recip bobcert.pem -inkey bobkey.pem
6, 簽名並加密
openssl smime -sign -in msg.txt -signer alicecert.pem -inkey alicekey.pem -nocerts -nodetach -text | openssl smime -encrypt -des3 -from [email protected] -to [email protected] -subject HiBob bobcert.pem
To: [email protected]
From: [email protected]
Subject: HiBob
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
MIIGKQYJKoZIhvcNAQcDoIIGGjCCBhYCAQAxggFmMIIBYgIBADBKMEUxCzAJBgNV
BAYTAkFVMRMwEQYDVQQIDApTb21lLVN0YXRlMSEwHwYDVQQKDBhJbnRlcm5ldCBX
aWRnaXRzIFB0eSBMdGQCAQMwDQYJKoZIhvcNAQEBBQAEggEAdmR6L5KWIhmIFBwj
UV2wxBb8S20+TH+ZsQ7NtHN/FucV+LMkRWsif03ExRqnsLwigQSXinigsOrgpovn
X8JpfiOQp3cg6KEyhX0+q2Ziiu4qRNZLCKoWXZ4oxyYORe8PT1R9NwSfnfVcHvec
duyOMYdp3T50844CXQ0NMv/FjEv5bdhN5TdPvEhyOcaQ4g/Fhsh0kPPFVNWnLFIw
6p+2K5sZr749RvGuzmZuwd4WvAtPO/bgBks7sbR8mR7jXLZaq8Q/NHN913Jq5Pf2
VATbIDUbvbD2Znv22NJOt600Et+yi4xHT/TG5TXVYZSuayOPhVkX032Gycgp3c35
UaYHozCCBKUGCSqGSIb3DQEHATAUBggqhkiG9w0DBwQI525g7nh7tU6AggSAxAL5
yGDcR3M+xZZELlG1/JcUKWLUmZQoqKyKtT5gk61lMJ6Si4LcQSlYP+IySeAYB9fw
RY+uKepW0snNHMO/IrT+EtKn/qJgm/OJSEf5YrCwmJx/k1Pv2BZu4GeTmnB5cfKx
xTus0bhiGR7tqWRv9XrexhdeUKumyJMzr9Vxzfnz+ahTk510npW3Ei+4rKkQOO3z
mrwRUril/J9onvInkvjAOwMceKTyjrCzEJv3f5JMreqwSjeTnxQcihJHdqPo1NpZ
RSNIsG83Hz2/mMNuRgVQi7DVWqJlcsv4OG9J6Dw6Xp7bnskppoMYMsZzOon0X4o+
JTjb9lyhxcXPE8htbd3qg1EroMByoWD/HcKLYv00vo1Gd5mgHCEqp0a6/WrpLlGQ
JDJDFqJ2TEJCbgAiTejxns+t/zQyC9iOVSP+S1/rkzuZV28O7zCDjJwxGK1rUFa1
Epa4jlciFyppuzzxYICxSDNVAfFsGLW3heuxFqew3aUufDcjzhkDYGrZpWd91C0/
WYqVQM5VYtpqTZHUfNAkFvyuB2jqi265/rvsgpIb1mlC3ee4DbAqAz9a8HMMajkN
rRWGuGm9S/Zz4QskAaNYdQXqmv2UT2NmDhcv+zGqH0vzlGs0k9Ae0My1cucBPmFO
NjbM11yHTSKN1sqlRtzQiCi7IbM5B4Q2O8/jhvO07ezRz5Fj4o4PxpElQ/7mtusg
Fz97HA4guZ+8Ig/NoG7HkdJh5Ju0fTGnqDosG3jXJWtJlXrsA3qHwdbk1Z8ux7xf
L6fVmO2dEBUkc6ihMvDgyZByUbyauEfyCwSb0UfJeJbbfY9UmsBWbU635rLn5Fcx
MTY9JwoD/SgEYRm3XhxphO+xy2LAVal4GULlcqtXeGKLUzuRavn/MCP7V5xLEX8Z
3hih/eJ/OFOUL/Hndr5py3oLavhV+mFwNTJrQ2Jrk9DwnsnUS70Z8nEKbe9O41Xl
rcll6nLMnY6qXmA47tz5NM7uPGBpus5cInRnI2ndGnGJt0pW30ubn1gH/sYA6iwR
aWTz4gxo1h9pVfJ6z8P6guXJaS5X6NLGVfl6EPs1EwEEbc0zd3r9iphcARtnI4U6
fOa5QeRWd8KI/XpSS9KXM90Jdphxz1E1iD9VGkFPhxRq0HMaEZu2ggD2HUTHibyZ
9fV9f6wf2Hx4Wng1Eh1PDiffnIYkrEYdfu2Uqt7HaYxz1T0qbrkHNJOjT8eZ3aZW
yLn/bEDeyxeLcsGDOt6hdW0C0PaoLzv6okKbprLgx4Dfxfh0ytu1m/M6WoVO3/QB
ELvxshSBc77P4+UAAlDjRhpQRuDOa0xU5DHeb3DDogRGw8nWpleyqQsTlgQmzYWJ
w8ps+VbrGTn3hNkGcLgkqXWy5uLocuj+61RB8HZAdNMhjAKHvr9pGhac1hbLW7aP
uehFCfCo4P0vDNJpjV7JDG8y+j89guGbC8ew3Hd7LYGucdGYWgnKxBRpmG5dJ7Vi
swGNTSOWATI+Lz+sySCVHyrKbsf3IfFsjdMZxQrZttnm63q5rRam/F0VMbEE
7,解密並驗證
openssl smime -decrypt -in enc.eml -recip bobcert.pem -inkey bobkey.pem | openssl smime -verify -certfile alicecert.pem -CAfile cacert.pem
Content-Type: text/plain
Hello, World !
Verification successful
管道命令
openssl smime -sign -in msg.txt -signer alicecert.pem -inkey alicekey.pem -nocerts -nodetach -text | \
openssl smime -encrypt -des3 -from [email protected] -to [email protected] -subject HiBob bobcert.pem | \
openssl smime -decrypt -recip bobcert.pem -inkey bobkey.pem | \
openssl smime -verify -certfile alicecert.pem -CAfile cacert.pem
8,郵件傳送
9,郵件接收
備註:
1)關於cms的一些資料結構定義
struct CMS_ContentInfo_st {
ASN1_OBJECT *contentType;
union {
ASN1_OCTET_STRING *data;
CMS_SignedData *signedData;
CMS_EnvelopedData *envelopedData;
CMS_DigestedData *digestedData;
CMS_EncryptedData *encryptedData;
CMS_AuthenticatedData *authenticatedData;
CMS_CompressedData *compressedData;
ASN1_TYPE *other;
/* Other types ... */
void *otherData;
} d;
};
PKCS7的遞推定義
/*-
Encryption_ID DES-CBC
Digest_ID MD5
Digest_Encryption_ID rsaEncryption
Key_Encryption_ID rsaEncryption
*/
typedef struct pkcs7_issuer_and_serial_st {
X509_NAME *issuer;
ASN1_INTEGER *serial;
} PKCS7_ISSUER_AND_SERIAL;
typedef struct pkcs7_signer_info_st {
ASN1_INTEGER *version; /* version 1 */
PKCS7_ISSUER_AND_SERIAL *issuer_and_serial;
X509_ALGOR *digest_alg;
STACK_OF(X509_ATTRIBUTE) *auth_attr; /* [ 0 ] */
X509_ALGOR *digest_enc_alg;
ASN1_OCTET_STRING *enc_digest;
STACK_OF(X509_ATTRIBUTE) *unauth_attr; /* [ 1 ] */
/* The private key to sign with */
EVP_PKEY *pkey;
} PKCS7_SIGNER_INFO;
DECLARE_STACK_OF(PKCS7_SIGNER_INFO)
DECLARE_ASN1_SET_OF(PKCS7_SIGNER_INFO)
typedef struct pkcs7_recip_info_st {
ASN1_INTEGER *version; /* version 0 */
PKCS7_ISSUER_AND_SERIAL *issuer_and_serial;
X509_ALGOR *key_enc_algor;
ASN1_OCTET_STRING *enc_key;
X509 *cert; /* get the pub-key from this */
} PKCS7_RECIP_INFO;
DECLARE_STACK_OF(PKCS7_RECIP_INFO)
DECLARE_ASN1_SET_OF(PKCS7_RECIP_INFO)
typedef struct pkcs7_signed_st {
ASN1_INTEGER *version; /* version 1 */
STACK_OF(X509_ALGOR) *md_algs; /* md used */
STACK_OF(X509) *cert; /* [ 0 ] */
STACK_OF(X509_CRL) *crl; /* [ 1 ] */
STACK_OF(PKCS7_SIGNER_INFO) *signer_info;
struct pkcs7_st *contents;
} PKCS7_SIGNED;
/*
* The above structure is very very similar to PKCS7_SIGN_ENVELOPE. How about
* merging the two
*/
typedef struct pkcs7_enc_content_st {
ASN1_OBJECT *content_type;
X509_ALGOR *algorithm;
ASN1_OCTET_STRING *enc_data; /* [ 0 ] */
const EVP_CIPHER *cipher;
} PKCS7_ENC_CONTENT;
typedef struct pkcs7_enveloped_st {
ASN1_INTEGER *version; /* version 0 */
STACK_OF(PKCS7_RECIP_INFO) *recipientinfo;
PKCS7_ENC_CONTENT *enc_data;
} PKCS7_ENVELOPE;
typedef struct pkcs7_signedandenveloped_st {
ASN1_INTEGER *version; /* version 1 */
STACK_OF(X509_ALGOR) *md_algs; /* md used */
STACK_OF(X509) *cert; /* [ 0 ] */
STACK_OF(X509_CRL) *crl; /* [ 1 ] */
STACK_OF(PKCS7_SIGNER_INFO) *signer_info;
PKCS7_ENC_CONTENT *enc_data;
STACK_OF(PKCS7_RECIP_INFO) *recipientinfo;
} PKCS7_SIGN_ENVELOPE;
typedef struct pkcs7_digest_st {
ASN1_INTEGER *version; /* version 0 */
X509_ALGOR *md; /* md used */
struct pkcs7_st *contents;
ASN1_OCTET_STRING *digest;
} PKCS7_DIGEST;
typedef struct pkcs7_encrypted_st {
ASN1_INTEGER *version; /* version 0 */
PKCS7_ENC_CONTENT *enc_data;
} PKCS7_ENCRYPT;
typedef struct pkcs7_st {
/*
* The following is non NULL if it contains ASN1 encoding of this
* structure
*/
unsigned char *asn1;
long length;
# define PKCS7_S_HEADER 0
# define PKCS7_S_BODY 1
# define PKCS7_S_TAIL 2
int state; /* used during processing */
int detached;
ASN1_OBJECT *type;
/* content as defined by the type */
/*
* all encryption/message digests are applied to the 'contents', leaving
* out the 'type' field.
*/
union {
char *ptr;
/* NID_pkcs7_data */
ASN1_OCTET_STRING *data;
/* NID_pkcs7_signed */
PKCS7_SIGNED *sign;
/* NID_pkcs7_enveloped */
PKCS7_ENVELOPE *enveloped;
/* NID_pkcs7_signedAndEnveloped */
PKCS7_SIGN_ENVELOPE *signed_and_enveloped;
/* NID_pkcs7_digest */
PKCS7_DIGEST *digest;
/* NID_pkcs7_encrypted */
PKCS7_ENCRYPT *encrypted;
/* Anything else */
ASN1_TYPE *other;
} d;
} PKCS7;
PKCS#7 is an old standard from RSA Labs, published later on as an "informational RFC". Then, a new versions was produced, as an "Internet standard", i.e. with the seal of approval from the powers-that-be at IETF; a new name was invented for that: CMS. Newer versions were subsequently defined: RFC 3369, RFC 3852, RFC 5652. You can consider CMS and PKCS#7 to both designate the same standard, which has several versions.
CMS (PKCS#7) is a format for applying encryption, signatures and/or integrity checks on arbitrary binary messages (which can be large). It can be nested. It is the basis for some protocols such as time stamping. It is also frequently (ab)used as a container for X.509 certificates: the SignedData type includes a field for a set of signatures (and that set can be empty), and also a field to store arbitrary X.509 certificates which are considered as "potentially useful" for whoever processes the object.
CMS is nominally backward compatible: there are version fields at various places, and a library which understands a version of CMS should be able to process messages from older versions; moreover, such a library should also produce messages which are compatible with other versions, inasmuch as it is feasible given the message contents. See section 5.1 for an example: the "version" fields are set to the minimal values which still make sense given what else is in the structure.
if (noout) {
if (print)
CMS_ContentInfo_print_ctx(out, cms, 0, NULL);
} else if (outformat == FORMAT_SMIME) {
if (to)
BIO_printf(out, "To: %s\n", to);
if (from)
BIO_printf(out, "From: %s\n", from);
if (subject)
BIO_printf(out, "Subject: %s\n", subject);
if (operation == SMIME_RESIGN)
ret = SMIME_write_CMS(out, cms, indata, flags);
else
ret = SMIME_write_CMS(out, cms, in, flags);
} else if (outformat == FORMAT_PEM)
ret = PEM_write_bio_CMS_stream(out, cms, in, flags);
else if (outformat == FORMAT_ASN1)
ret = i2d_CMS_bio_stream(out, cms, in, flags);
else {
BIO_printf(bio_err, "Bad output format for CMS file\n");
goto end;
}
else {
if (to)
BIO_printf(out, "To: %s\n", to);
if (from)
BIO_printf(out, "From: %s\n", from);
if (subject)
BIO_printf(out, "Subject: %s\n", subject);
if (outformat == FORMAT_SMIME) {
if (operation == SMIME_RESIGN)
SMIME_write_PKCS7(out, p7, indata, flags);
else
SMIME_write_PKCS7(out, p7, in, flags);
} else if (outformat == FORMAT_PEM)
PEM_write_bio_PKCS7_stream(out, p7, in, flags);
else if (outformat == FORMAT_ASN1)
i2d_PKCS7_bio_stream(out, p7, in, flags);
else {
BIO_printf(bio_err, "Bad output format for PKCS#7 file\n");
goto end;
}
2) smtp如何傳送郵件
https://technet.microsoft.com/en-us/library/dd441082.aspx
https://tools.ietf.org/html/rfc821
https://tools.ietf.org/html/rfc2554
https://tools.ietf.org/html/rfc2821
http://tools.ietf.org/html/rfc5321
如何通過郵件地址字尾的domain來查詢郵件伺服器(smtp)的地址:nslookup -type=mx sina.com
相關推薦
【OpenSSL】使用SMIME傳送簽名和加密郵件
1,通訊雙方的證書生成 1.1生成根節點證書 openssl genrsa -out cakey.pem 2048 openssl req -new -key cakey.pem -subj "/CN=rootca.bitbaba.com" -out cacsr.pem
【OpenSSL】使用SMIME/CMS傳送簽名和加密郵件
1,通訊雙方的證書生成 1.1生成根節點證書 openssl genrsa -out cakey.pem 2048 openssl req -new -key cakey.pem -subj "/CN=rootca.bitbaba.com" -out cacsr.pem
【NetApp】使用powershell mount和umount Volume
netapp powershell mount-ncvol dismount-ncvol 1)連接DataOntap Cmode控制器 Connect-NCController 10.20.30.40 該IP地址是Cluster 管理地址。2)Mount 現有volumeMount-NcV
【轉】 javaweb 基礎知識和 Tomcat 是什麽
att logic 資源 spa 文件系統 png intra 很快 應用開發 JavaWeb學習總結(一)——JavaWeb開發入門 一、基本概念 1.1、WEB開發的相關知識 WEB,在英語中web即表示網頁的意思,它用於表示Internet主機上供外界訪問的資
【MySQL】配置MySQL安裝和遠程訪問步驟
image 新建 oar 最新 rest word clas 字段 sql安裝 以遠程服務器為例,安裝Mysql到Linux並配置遠程訪問,步驟如下: 1.下載安裝最新的rpm文件 方法一: rpm -Uvh http://repo.mysql.com/mysql-co
【轉】哈希(Hash)與加密(Encrypt)的基本原理、區別及工程應用
phy 理論 靈活運用 十分 實際應用 廣泛 tle 多網站 net 0、摘要 今天看到吉日嘎拉的一篇關於管理軟件中信息加密和安全的文章,感覺非常有實際意義。文中作者從實踐經驗出發,討論了信息管理軟件中如何通過哈希和加密進行數據保護。但是從文章評論中也可以
【Java】基本類型和引用類型(值傳遞)
適合 and span print pri right bre enc this 【關鍵詞】 【問題】 · 加深對基本類型和引用類型的理解; 【效果圖】 【分析】 參見最後的【參考資料】 【解決方式】 【代碼】 public
【轉載】Java中Comparable和Comparator比較
import 比較器 todo itl 復制代碼 ack div array open 【本文轉自】http://www.cnblogs.com/skywang12345/p/3324788.html Comparable 簡介 Comparable 是排序接口。 若一
【Java】日誌知識總結和經常使用組合配置(commons-logging,log4j,slf4j,logback)
ng- binder mono leading black auto erb param 1.2 Log4j Apache的一個開放源碼項目,通過使用Log4j,我們能夠控制日誌信息輸送的目的地是控制臺、文件、GUI組件、甚至是套接口服務 器
【轉】使用ssh-keygen和ssh-copy-id三步實現SSH無密碼登錄
works message targe auth mes unix use ner not 【原】http://blog.chinaunix.net/uid-26284395-id-2949145.html ssh-keygen 產生公鑰與私鑰對. ssh-copy-id
【bzoj1415】[Noi2005]聰聰和可可 期望記憶化搜索
def 小數 所在 技術分享 alt tdi line 都是 包含 題目描述 輸入 數據的第1行為兩個整數N和E,以空格分隔,分別表示森林中的景點數和連接相鄰景點的路的條數。 第2行包含兩個整數C和M,以空格分隔,分別表示初始時聰聰和可可所在的景點的編號。 接下來E
【轉】FTP主動模式和被動模式的比較
edit 兩個 int cti 了解 選擇 監聽端口 通訊 mod 總是記不住FTP主動和被動模式的區別。放在這裏,以備日後查閱。 FTP是僅基於TCP的服務,不支持UDP。與眾不同的是FTP使用2個端口,一個數據端口和一個命令端口(也可叫做控制端口)。通常來說這兩個端
【轉】RAID技術介紹和總結
允許 pos distrib 數據讀取 body web服務器 data- 也有 丟失 轉自http://blog.jobbole.com/83808/ 簡介 RAID是一個我們經常能見到的名詞。但卻因為很少能在實際環境中體驗,所以很難對其原理 能有很清楚的認識和掌握。本文
【轉載】如何自動生成和安裝requirements.txt依賴
生成 構建 文件 自動 file title clas 人的 安裝 如何自動生成和安裝requirements.txt依賴 在查看別人的Python項目時,經常會看到一個requirements.txt文件,裏面記錄了當前程序的所有依賴包及其精確版本號。這個文件有點類似
Fiddler抓包【7】_次要功能和第三方插件
lang ont 類型 host 第三方插件 發生 p地址 lec 命令行 1、替換HTTP Request Host 應用場景:進行開發時,線上去測試跳轉調試 替換命令:urlreplace news.baidu.com www.baidu.com; 清除命令:urlre
【轉】C# list介紹和用法
php 檢索 排序 c# reac ont 面向對象 類型 大型 一、LIST概述 所屬命名空間:System.Collections.Generic public class List<T> : IList<T>, ICollection
【轉】有助於事業發展和幸福感提升的四個約定
堅守 做到 提升 但是 html blog 盡心 希望 調整 先做人,後做事,調節好自己的心態,調整好對人對事的方式,才能更好的做事。 以下是我聽到過的4個約定,可以幫助人發展事業並且提高自己的幸福感。每條約定後面是我對這條約定的一些看法,希望大家能談談自己的看法
【練習】友元類和友元函數
turn main spa std return col print pri circle #include <iostream> using namespace std; class Circle; class Point { private: fl
【轉】斜率優化DP和四邊形不等式優化DP整理
dex add ive mat 整理 off code 斜率dp 好的 當dp的狀態轉移方程dp[i]的狀態i需要從前面(0~i-1)個狀態找出最優子決策做轉移時 我們常常需要雙重循環 (一重循環跑狀態 i,一重循環跑 i 的所有子狀態)這樣的時間復雜度是O(N^2)而 斜
python全棧開發【補充】map函數和reduce函數的區別
lambda mage 多個 計算 兩個 數值 ima 所有 post ①從參數方面來講:map()函數: map()包含兩個參數,第一個是參數是一個函數,第二個是序列(列表或元組)。其中,函數(即map的第一個參數位置的函數)可以接收一個或多個參數。reduce()函數