TLS:(Transport Layer Security)为安全传输层协议,所以属于传输层;
SSL与TLS的区别以及介绍
CA 生成
自动生成
- 在OpenSSL的安装目录下的misc目录下,运行脚本
/usr/local/etc/openssl@1.1/misc/CA.pl -newca
手动生成
无法进行下去了,因为只从中间CA生成开始而根CA没生成,需要先生成根CA,没尝试过。
创建root CA私钥和证书然后进一步创建中间CA。为了便于区分,我们将创建中间CA(intermediate CA)
的CA称为根CA(root CA)
。
中间CA是root CA的代理,其证书由root CA签发,同时中间CA能够代表根CA签发用户证书,由此建立起信任链。
创建中间CA的好处是即使中间CA的私钥泄露,造成的影响也是可控的,我们只需要使用root CA撤销对应中间CA的证书即可。此外root CA的私钥可以脱机妥善保存,只需要在撤销和更新中间CA证书时才会使用。
- 生成 CA 目录
//mkdir [-p] dirName
//-p 确保目录名称存在,不存在的就建一个
mkdir -p /Users/harleyhuang/Documents/Gitee/SSL/CA
//生成 certs、 crl、 newcerts、 private四个文件夹
mkdir certs crl newcerts private
//chmod abc file: 文件使用权限
//a,b,c各为一个数字,分别表示User、Group、及Other的权限。
//若r=4,w=2,x=1,要rwx属性则4+2+1=7
chmod 777 private
// touch命令用于修改文件或者目录的时间属性,包括存取时间和更改时间。若文件不存在,系统会建立一个新的文件
touch index.txt
//echo: 指令与 PHP 的 echo 指令类似,都是用于字符串的输出
//echo "It is a test" > myfile:显示结果定向至文件
echo 1000 > serial
- 创建中间CA的私钥,采用AES-256算法加密中间CA的私钥,中途会让我们输入加密密钥,最后修改中间CA的私钥访问权限
openssl genrsa -aes256 -out private/cakey.pem 4096
chmod 400 private/cakey.pem
- 中间CA要向root CA申请公钥证书,就要首先产生一个CSR(证书签名请求,Certificate Signing Request都有作用)格式的请求文件,将其发送给root CA后等待其对中间CA的审查。
将创建root CA时使用的配置文件拷贝到中间CA证书目录下,该配置文件在生成CSR文件和后续签发用户证书时都有用。
创建并编辑intermediate_CA.cnf,若是demoCA中没有rootCA.cnf文件夹可以去/System/Library/OpenSSL/openssl.cnf
进行拷贝一份:
cp /Users/harleyhuang/Documents/Gitee/SSL/demoCA/rootCA.cnf /Users/harleyhuang/Documents/Gitee/SSL/intermediateCA/intermediateCA.cnf
cd cd /Users/harleyhuang/Documents/Gitee/SSL/intermediateCA
vim intermediateCA.cnf
//编辑
...
[ CA_default ]
dir = /Users/harleyhuang/Documents/Gitee/SSL/intermediateCA
今后我们每次使用中间CA创建新的证书时,以”-config /Users/harleyhuang/Documents/Gitee/SSL/intermediateCA/intermediateCA.cnf“
的形式告诉OpenSSL中间CA的信息。
intermediateCA.cnf.cnf
默认申请的有效期是365天,如果想要修改这个时长,可以在[ CA_default ]的"default_days"
字段进行修改。
- 生成CSR文件
cd /Users/harleyhuang/Documents/Gitee/SSL/intermediateCA
openssl req -config intermediateCA.cnf -sha256 -new -key private/cakey.pem -out cacsr.pem
随后系统会要求我们输入中间CA的私钥密码,设置中间CA的一些身份信息等等,注意”Organization Name“
一项一定要与root CA时设置的相同。
正确输入中间CA的身份信息后我们就得到了中间CA的CSR。
接下来我们用root CA同意中间CA的请求,因为我们将使用root CA的私钥签名中间CA的证书,这时系统会要求我们输入root CA的私钥密码,选择签名证书如下:
cd /Users/harleyhuang/Documents/Gitee/SSL/demoCA
openssl ca -config rootCA.cnf -extensions v3_ca -notext -md sha256 -in /Users/harleyhuang/Documents/Gitee/SSL/intermediateCA/cacsr.pem -out /Users/harleyhuang/Documents/Gitee/SSL/intermediateCA/cacert.pem
根证书生成
新建一个SSL的文件夹
终端定位到这个文件夹
cd /Users/harleyhuang/Documents/Gitee/SSL
创建根证书密钥文件(自己做CA)root.key
openssl genrsa -des3 -out root.key
- 创建根证书的申请文件root.csr
openssl req -new -key root.key -out root.csr
- 创建一个自当前日期起为期十年的根证书root.crt
openssl x509 -req -days 3650 -sha1 -extensions v3_ca -signkey root.key -in root.csr -out root.crt
服务器SSL证书生成
- 创建服务器证书密钥文件(在SSL文件夹中生成私钥)
使用openssl工具生成一个RSA私钥,
openssl genrsa -des3 -out server.key 2048
生成rsa私钥,des3算法,2048位强度,server.key是秘钥文件名。
注意
:生成私钥,需要提供一个至少4位的密码。
- 创建服务器证书的申请文件root.csr(生成CSR[证书签名请求])
生成私钥之后,便可以创建csr文件了。
此时可以有两种选择。理想情况下,可以将证书发送给证书颁发机构(CA),CA验证过请求者的身份之后,会出具签名证书(很贵)。另外,如果只是内部或者测试需求,也可以使用OpenSSL实现自签名,具体操作如下:
openssl req -new -key server.key -out server.csr
//或者生成如下证书,注意2者不同,这里使用上面的
//openssl req -new -sha256 -x509 -days 365 -key server.key -out server.crt
说明:需要依次输入国家,地区,城市,组织,组织单位,Common Name和Email。其中Common Name,可以写自己的名字或者域名,如果要支持https,Common Name应该与域名保持一致,否则会引起浏览器警告。
- 删除私钥中的密码
在【创建根证书密钥文件】过程中,由于必须要指定一个密码。而这个密码会带来一个副作用,那就是在每次Apache启动Web服务器时,都会要求输入密码,这显然非常不方便。要删除私钥中的密码,操作如下:
cp server.key server.key.org
openssl rsa -in server.key.org -out server.key
- 生成自签名证书(创建一个自当前日期起为期十年的根证书)
如果你不想花钱让CA签名,或者只是测试SSL的具体实现。那么,现在便可以着手生成一个自签名的证书了。
需要注意的是,在使用自签名的临时证书时,浏览器会提示证书的颁发机构是未知的。
openssl x509 -req -days 365 -in server.csr -signkey server.key -out server.crt
证书查看
说明:crt上有证书持有人的信息,持有人的公钥,以及签署者的签名等信息。当用户安装了证书之后,便意味着信任了这份证书,同时拥有了其中的公钥。证书上会说明用途,例如服务器认证,客户端认证,或者签署其他证书。当系统收到一份新的证书的时候,证书会说明,是由谁签署的。如果这个签署者确实可以签署其他证书,并且收到证书上的签名和签署者的公钥可以对上的时候,系统就自动信任新的证书。
- 或者使用根证书生成crt
openssl x509 -req -days 730 -sha1 -extensions v3_req -CA root.crt -CAkey root.key -CAserial root.csr -CAcreateserial -in server.csr -out server2.crt
- 安装私钥和证书
将私钥(server.key)和证书文件(server.crt)复制到Apache的配置目录下即可,在Mac 10.10系统中,复制到/etc/apache2/目录中即可。
- 客户端利用AF3.0使用自定义证书
第一步:
// 1.初始化单例类
AFHTTPSessionManager *manager = [AFHTTPSessionManager manager];
manager.securityPolicy.SSLPinningMode = AFSSLPinningModeCertificate;
// 2.设置证书模式
NSString * cerPath = [[NSBundle mainBundle] pathForResource:@"xxx" ofType:@"cer"];
NSData * cerData = [NSData dataWithContentsOfFile:cerPath];
manager.securityPolicy = [AFSecurityPolicy policyWithPinningMode:AFSSLPinningModeCertificate withPinnedCertificates:[[NSSet alloc] initWithObjects:cerData, nil]];
// 客户端是否信任非法证书
mgr.securityPolicy.allowInvalidCertificates = YES;
// 是否在证书域字段中验证域名
[mgr.securityPolicy setValidatesDomainName:NO];
第二步:使用AFNetworking进行请求
AFNetworking首先需要配置AFSecurityPolicy类,AFSecurityPolicy类封装了证书校验的过程
/**
AFSecurityPolicy分三种验证模式:
AFSSLPinningModeNone:只是验证证书是否在信任列表中
AFSSLPinningModeCertificate:该模式会验证证书是否在信任列表中,然后再对比服务端证书和客户端证书是否一致
AFSSLPinningModePublicKey:只验证服务端证书与客户端证书的公钥是否一致
*/
AFSecurityPolicy *securityPolicy = [AFSecurityPolicy policyWithPinningMode:AFSSLPinningModeCertificate];
securityPolicy.allowInvalidCertificates = YES;//是否允许使用自签名证书
securityPolicy.validatesDomainName = NO;//是否需要验证域名,默认YES
AFHTTPSessionManager *_manager = [AFHTTPSessionManager manager];
_manager.responseSerializer = [AFHTTPResponseSerializer serializer];
_manager.securityPolicy = securityPolicy;
//设置超时
[_manager.requestSerializer willChangeValueForKey:@"timeoutinterval"];
_manager.requestSerializer.timeoutInterval = 20.f;
[_manager.requestSerializer didChangeValueForKey:@"timeoutinterval"];
_manager.requestSerializer.cachePolicy = NSURLRequestReloadIgnoringCacheData;
_manager.responseSerializer.acceptableContentTypes = [NSSet setWithObjects:@"application/xml",@"text/xml",@"text/plain",@"application/json",nil];
__weak typeof(self) weakSelf = self;
[_manager setSessionDidReceiveAuthenticationChallengeBlock:^NSURLSessionAuthChallengeDisposition(NSURLSession *session, NSURLAuthenticationChallenge *challenge, NSURLCredential *__autoreleasing *_credential) {
SecTrustRef serverTrust = [[challenge protectionSpace] serverTrust];
/**
* 导入多张CA证书
*/
NSString *cerPath = [[NSBundle mainBundle] pathForResource:@"ca" ofType:@"cer"];//自签名证书
NSData* caCert = [NSData dataWithContentsOfFile:cerPath];
NSArray *cerArray = @[caCert];
weakSelf.manager.securityPolicy.pinnedCertificates = cerArray;
SecCertificateRef caRef = SecCertificateCreateWithData(NULL, (__bridge CFDataRef)caCert);
NSCAssert(caRef != nil, @"caRef is nil");
NSArray *caArray = @[(__bridge id)(caRef)];
NSCAssert(caArray != nil, @"caArray is nil");
OSStatus status = SecTrustSetAnchorCertificates(serverTrust, (__bridge CFArrayRef)caArray);
SecTrustSetAnchorCertificatesOnly(serverTrust,NO);
NSCAssert(errSecSuccess == status, @"SecTrustSetAnchorCertificates failed");
NSURLSessionAuthChallengeDisposition disposition = NSURLSessionAuthChallengePerformDefaultHandling;
__autoreleasing NSURLCredential *credential = nil;
if ([challenge.protectionSpace.authenticationMethod isEqualToString:NSURLAuthenticationMethodServerTrust]) {
if ([weakSelf.manager.securityPolicy evaluateServerTrust:challenge.protectionSpace.serverTrust forDomain:challenge.protectionSpace.host]) {
credential = [NSURLCredential credentialForTrust:challenge.protectionSpace.serverTrust];
if (credential) {
disposition = NSURLSessionAuthChallengeUseCredential;
} else {
disposition = NSURLSessionAuthChallengePerformDefaultHandling;
}
} else {
disposition = NSURLSessionAuthChallengeCancelAuthenticationChallenge;
}
} else {
disposition = NSURLSessionAuthChallengePerformDefaultHandling;
}
return disposition;
}];
上述代码通过给AFHTTPSessionManager重新设置证书验证回调来自己验证证书,然后将自己的证书加入到可信任的证书列表中,即可通过证书的校验。
创建客户端证书密钥文件client.key
openssl genrsa -des3 -out client.key 2048
创建客户端证书的申请文件client.csr
openssl req -new -key client.key -out client.csr
-
创建一个自当前日期起有效期为两年的客户端证书client2.crt
openssl x509 -req -days 730 -sha1 -extensions v3_req -CA server.crt -CAkey server.key -CAserial server.csr -CAcreateserial -in client.csr -out client2.crt
发现它unable to load CA Private Key
将客户端证书文件client.crt和客户端证书密钥文件client.key合并成客户端证书安装包client.pfx
openssl pkcs12 -export -in client2.crt -inkey client.key -out client.pfx
-
保存生成的文件备用,其中server.crt和server.key是配置单向SSL时需要使用的证书文件,client.crt是配置双向SSL时需要使用的证书文件,client.pfx是配置双向SSL时需要客户端安装的证书文件
.crt文件和.key可以合到一个文件里面,把2个文件合成了一个.pem文件(直接拷贝过去就行了)
参考资料
HTTPS 证书链的验证 US
OpenSSL证书生成及Mac上Apache服务器配置HTTPS
搭建CA服务器 US