Send email via openssl command line

root@localhost$ openssl s_client -crlf -quiet -starttls smtp -connect mail.server.com:465
depth=0 OU = GT85507400, OU = See www.rapidssl.com/resources/cps (c)14, OU = Domain Control Validated - RapidSSL(R), CN = *.name.com
verify ...
250 HELP
> EHLO client.com
250-mail.server.com Hello client.com [192.168.1.2]
250-SIZE 52428800
250-8BITMIME
250-PIPELINING
250-AUTH PLAIN LOGIN
250 HELP
> AUTH LOGIN
334 VXNlcm5hbWU6
> [base64 code of username]
334 UGFzc3dvcmQ6
> [base64 code of password]
235 Authentication succeeded
> MAIL FROM:support@server.com
250 OK
> RCPT TO:yang@client.com
250 Accepted
> DATA
354 Enter message, ending with "." on a line by itself
> Subject:mail sending with mail.server.com
> This is a test mail from mail.server.com, sent by openssl.
> .
250 OK id=1YGmlz-0049vF-0V
> quit
221 mail.server.com closing connection

> 开始的行是客户端需要输入的命令。

OpenSSL

PLACEHOLDER

  1. OpenSSL 基本配置
  2. 生成自签名CA证书及密钥
  3. 为域名生成CSR及密钥 – dev.ymeng.net
  4. 用CA的私钥为dev.ymeng.net签名,生成用户证书
  5. 转换证书为pkcs12格式
  6. 查看pkcs12证书
  7. 使用openssl验证SSL双向认证
  8. 根据已有的证书和私钥生成CSR

1. OpenSSL基本配置  TOP

dir = /etc/apache2/ssl-cert/ca
 
[ req ]
default_bits = 2048 # Size of keys
default_keyfile = key.pem # name of generated keys
default_md = md5 # message digest algorithm
string_mask = nombstr # permitted characters
distinguished_name = req_distinguished_name
req_extensions = v3_req 
 
[ req_distinguished_name ]
# Variable name   Prompt string
#----------------------   ----------------------------------
0.organizationName = Organization Name (company)
organizationalUnitName = Organizational Unit Name (department, division)
emailAddress = Email Address
emailAddress_max = 40
localityName = Locality Name (city, district)
stateOrProvinceName = State or Province Name (full name)
countryName = Country Name (2 letter code)
countryName_min = 2
countryName_max = 2
commonName = Common Name (hostname, IP, or your name)
commonName_max = 64 
 
# Default values for the above, for consistency and less typing.
# Variable name   Value
#------------------------------   ------------------------------
0.organizationName_default = Company Technologies Co., Ltd.
organizationalUnitName_default = Development Dept.
emailAddress_default = ca@company.com
localityName_default = Helsinki
# stateOrProvinceName_default =
countryName_default = FI
 
[ v3_ca ]
basicConstraints = CA:TRUE
subjectKeyIdentifier = hash
authorityKeyIdentifier = keyid:always,issuer:always 
 
[ v3_req ]
basicConstraints = CA:FALSE
subjectKeyIdentifier = hash 
 
[ ca ]
default_ca = CA_default 
 
[ CA_default ]
serial = $dir/serial
database = $dir/index.txt
new_certs_dir = $dir/newcerts
certificate = $dir/cacert.pem
private_key = $dir/private/cakey.pem
default_days = 365
default_md = md5
preserve = no
email_in_dn = no
nameopt = default_ca
certopt = default_ca
policy = policy_match 
 
[ policy_match ]
countryName = match
stateOrProvinceName = optional
organizationName = match
organizationalUnitName = optional
commonName = supplied
emailAddress = optional

2. 生成自签名CA证书及密钥  TOP

openssl req -new -x509 -extensions v3_ca -keyout private/cakey.pem -out cacert.pem -days 3650 -config ./openssl.conf

查看证书:

openssl x509 -in cacert.pem -noout -text

3. 为域名生成CSR及密钥 – dev.ymeng.net  TOP

openssl req -new -nodes -out dev.ymeng.net-csr.pem -keyout private/dev.ymeng.net-key.pem -config ./openssl.conf

查看CSR:

openssl req -in dev.ymeng.net-csr.pem -text -verify -noout

4. 用CA的私钥为dev.ymeng.net签名,生成用户证书  TOP

openssl ca -out dev.ymeng.net-cert.pem -config ./openssl.conf -infiles dev.ymeng.net-csr.pem

签名用到的CA密钥在配置文件中指定 [ CA_default ]

5. 转换证书为pkcs12格式  TOP

openssl pkcs12 -export -in dev.ymeng.net-cert.pem -out dev.ymeng.net-cert.p12 -inkey private/dev.ymeng.net-key.pem

6. 查看pkcs12证书  TOP

openssl pkcs12 -info -in keyStore.p12

7. 使用openssl验证SSL双向认证  TOP

openssl s_client -connect testgw.girogate.de:443 -cert customer.crt -key customer.key -CAfile ca.crt

8. 根据已有的证书和私钥生成CSR  TOP

openssl x509 -x509toreq -in certificate.crt -out certificate-request.csr -signkey private-key.key

HttpClient: SSL双向认证

拿到PPro支付的文档后,发现PPro需要客户端在与其交互的过程中,使用SSL双向认证。

也就是说,申请测试账户后,PPro会为测试账户生成一个ssl客户端证书,该证书是由PPro自签名CA签发的。

在PPro分配测试账号时,用户会得到

  • ca.crt – PPro自签名CA根证书
  • customer.crt – 用户证书
  • customer.key – 用户私钥

为了在Java中使用这些证书及私钥,需要将其导入到KeyStore中,需要创建两个KeyStore,分别存放CA证书,用户证书及私钥

1. 导入ca.crt至caKeyStore

keytool -importcert -alias pproca -file ca.crt -storetype jks -keystore caKeyStore.jks

需要指定别名、KeyStore类型(JKS),并指定KeyStore的访问密码

2. 导入customer.crt和customer至clientKeyStore

openssl pkcs12 -export -in customer.crt -out clientKeyStore.p12 -inkey customer.key -name customer

导入客户证书及密钥不能使用keytool命令,而需要使用openssl中的pkcs12 -export,并指定证书、密钥,以及别名(-name),并且需要根据提示输入export密码。keytool不能导入密钥。

openssl命令在此处生成的clientKeyStore.p12可以直接在Java中当作类型为PKCS12的KeyStore来使用。

加载KeyStore

InputStream keyStoreStream = loadKeyStoreIntoInputStream(keyStoreLocation);
KeyStore keyStore = KeyStore.getInstance("pkcs12"); // jks for CA
keyStore.load(keyStoreStream, keyStorePassword.toCharArray());

HttpClient调用KeyStore实现双向SSL认证

        HttpClient httpClient = new DefaultHttpClient();
 
        SSLSocketFactory sslSocketFactory = new SSLSocketFactory(clientKeyStore, clientKeyStorePassword, caKeyStore);
        Scheme protocolScheme = new Scheme("HTTPS", 443, sslSocketFactory);
 
        httpClient.getConnectionManager().getSchemeRegistry().register(protocolScheme);
 
        HttpPost httpPost = new HttpPost(url);

代码中的clientKeyStorePassword即是生成p12库时指定的export密码。

参考:OpenSSL设置、配置 及相关命令, KeyStore in Java