内容待补充。。。。。。
上一篇文章中的 # 测试 RSA 加密结合base64编码 (内容中需要生成的.pem文件在本篇文章中可生成)
代码参考:
# 1. 公钥加密,私钥解密
# 2. 私钥加密,公钥验签
import unittest
class CipherSign(unittest.TestCase):
"""
密码学中的签名和验签
"""
def test_rsa(self):
"""
测试rsa加密
"""
import base64
from Crypto import Random
from Crypto.PublicKey import RSA
from Crypto.Cipher import PKCS1_v1_5 as Cipher_pkcs1_v1_5
from Crypto.Signature import PKCS1_v1_5 as Signature_pkcs1_v1_5
from Crypto.Hash import SHA256
# 伪随机数生成器
random_generator = Random.new().read
# rsa算法生成实例
rsa = RSA.generate(1024, random_generator)
# master的秘钥对的生成
private_pem = rsa.exportKey()
with open("master-private.pem", "wb") as f:
f.write(private_pem)
public_pem = rsa.publickey().exportKey()
with open("master-public.pem", "wb") as f:
f.write(public_pem)
# ghost的秘钥对的生成
rsa = RSA.generate(1024, random_generator)
private_pem = rsa.exportKey()
with open("ghost-private.pem", "wb") as f:
f.write(private_pem)
public_pem = rsa.publickey().exportKey()
with open("ghost-public.pem", "wb") as f:
f.write(public_pem)
# ghost使用master的公钥对数据进行加密
with open("master-public.pem", "rb") as f:
key = f.read()
rsakey = RSA.importKey(key)
cipher = Cipher_pkcs1_v1_5.new(rsakey)
text = "ghost"
cipher_text = base64.b64encode(cipher.encrypt(text.encode()))
print(cipher_text)
# master使用自己的私钥对数据进行签名
with open("master-private.pem", "rb") as f:
key = f.read()
rsakey = RSA.importKey(key)
signer = Signature_pkcs1_v1_5.new(rsakey)
digest = SHA256.new()
digest.update(text.encode())
sign = signer.sign(digest)
signature = base64.b64encode(sign)
print(signature)
# ghost使用master的公钥对数据进行验签
with open("master-public.pem", "rb") as f:
key = f.read()
rsakey = RSA.importKey(key)
verifier = Signature_pkcs1_v1_5.new(rsakey)
digest = SHA256.new()
digest.update(text.encode())
is_verify = verifier.verify(digest, base64.b64decode(signature))
print(is_verify)
# master使用自己的私钥对数据进行解密
with open("master-private.pem", "rb") as f:
key = f.read()
rsakey = RSA.importKey(key)
cipher = Cipher_pkcs1_v1_5.new(rsakey)
text = cipher.decrypt(base64.b64decode(cipher_text), random_generator)
print(text.decode())
class CaSign(unittest.TestCase):
"""
测试证书签发
数字签名(server):1. 私钥加密,公钥验签
2. 公钥加密,私钥解密
证书签发(CA):1. CA先通过自己的私钥公钥为自己签发证书(ca.crt)
2. 服务端通过自己的私钥公钥为生成请求CA签发证书的请求(csr)
3. CA通过自己的私钥和自己的签发证书(ca.crt)为服务端签发证书(server.crt)
英文缩写:
CA: Certificate Authority
CSR: Certificate Signing Request
CRT: Certificate
PEM: Privacy Enhanced Mail
"""
def test_create_ca(self):
"""
测试生成CA证书
"""
from OpenSSL import crypto
# 获取秘钥对象
k = crypto.PKey()
# 生成RSA秘钥对(这里的2048是秘钥的长度)
k.generate_key(crypto.TYPE_RSA, 2048) # generate RSA key-pair
# 生成证书对象
cert = crypto.X509()
# 证书的国家名
cert.get_subject().C = "CN"
# 证书的州/省名
cert.get_subject().ST = "GuangDong"
# 证书的地理位置
cert.get_subject().L = "ShenZhen"
# 证书的机构名称
cert.get_subject().O = "BS, Inc."
# 证书的机构单元名称
cert.get_subject().OU = "BS"
# 证书的通用名称
cert.get_subject().CN = "localhost"
# 证书的电子邮箱地址
cert.get_subject().emailAddress = "123456@qq.com"
# 添加证书的扩展信息:subjectAltName,创建X509Extension对象,设置IP为127.0.1.1,DNS为localhost,testmysite.com
cert.add_extensions([crypto.X509Extension(b"subjectAltName", False, b"IP.1:127.0.0.1,DNS.1:localhost,DNS.2:testmysite.com")])
# 证书的序列号
cert.set_serial_number(1000)
# 证书有效期
cert.gmtime_adj_notBefore(0)
# 有效期10年
cert.gmtime_adj_notAfter(10*365*24*60*60)
# 设置证书签发者
cert.set_issuer(cert.get_subject())
# 设置证书公钥
cert.set_pubkey(k)
# 签名证书
cert.sign(k, 'sha256')
# 保存证书
open("ca_selfsign.crt", 'wb').write(crypto.dump_certificate(crypto.FILETYPE_PEM, cert))
# 保存私钥
open("ca_private.key", 'wb').write(crypto.dump_privatekey(crypto.FILETYPE_PEM, k))
# 保存公钥
open("ca_public.key", 'wb').write(crypto.dump_publickey(crypto.FILETYPE_PEM, k))
def test_parse_ca_crt(self):
import OpenSSL
from dateutil import parser
# cert = OpenSSL.crypto.load_certificate(OpenSSL.crypto.FILETYPE_PEM, open("ca_selfsign.crt").read())
cert = OpenSSL.crypto.load_certificate(OpenSSL.crypto.FILETYPE_PEM, open("server.crt").read())
certIssue = cert.get_issuer()
print ("证书版本: ",cert.get_version() + 1)
print ("证书序列号: ",hex(cert.get_serial_number()))
print ("证书中使用的签名算法: ",cert.get_signature_algorithm().decode("UTF-8"))
print ("颁发者: ",certIssue.commonName)
print("颁发者信息: ", certIssue.get_components())
print("颁发对象: ", cert.get_subject().commonName)
print("颁发对象信息: ", cert.get_subject().get_components())
datetime_struct = parser.parse(cert.get_notBefore().decode("UTF-8"))
print ("有效期从: ",datetime_struct.strftime('%Y-%m-%d %H:%M:%S'))
datetime_struct = parser.parse(cert.get_notAfter().decode("UTF-8"))
print ("到: ",datetime_struct.strftime('%Y-%m-%d %H:%M:%S'))
print ("证书是否已经过期: ",cert.has_expired())
print("公钥长度" ,cert.get_pubkey().bits())
print("公钥:\n" ,OpenSSL.crypto.dump_publickey(OpenSSL.crypto.FILETYPE_PEM, cert.get_pubkey()).decode("utf-8"))
print("颁发者主体信息:")
print("CN : 通用名称 OU : 机构单元名称")
print("O : 机构名 L : 地理位置")
print("S : 州/省名 C : 国名")
for item in certIssue.get_components():
print(item[0].decode("utf-8"), " —— ",item[1].decode("utf-8"))
# 查看证书的扩展信息
for index in range(cert.get_extension_count()):
ext = cert.get_extension(index)
print("type name: %s, value : %s" % (ext.get_short_name(), ext.get_data()))
print(cert.get_extension_count())
subject = cert.get_subject()
print("域名:\n" ,subject.CN)
def test_create_csr(self):
"""
测试服务端生成csr,用于向CA申请证书(server.crt)
csr: 证书签发请求
csr = 服务的的公钥 + 服务端的信息
公钥:被服务端的私钥绑定
"""
def create_csr(common_name, country=None, state=None, city=None,
organization=None, organizational_unit=None,
email_address=None):
"""
Args:
common_name (str).
country (str).
state (str).
city (str).
organization (str).
organizational_unit (str).
email_address (str).
Returns:
(str, str). Tuple containing private key and certificate
signing request (PEM).
"""
import OpenSSL.crypto
key = OpenSSL.crypto.PKey()
key.generate_key(OpenSSL.crypto.TYPE_RSA, 2048)
# 类似CA证书签名过程,区别在这是一个证书签发请求(CSR)
# 证书签发请求(CSR)是一个公钥和一些相关信息,这些信息将包含在最终的证书中
req = OpenSSL.crypto.X509Req()
req.get_subject().CN = common_name
if country:
req.get_subject().C = country
if state:
req.get_subject().ST = state
if city:
req.get_subject().L = city
if organization:
req.get_subject().O = organization
if organizational_unit:
req.get_subject().OU = organizational_unit
if email_address:
req.get_subject().emailAddress = email_address
# 添加证书的扩展信息:subjectAltName,创建X509Extension对象,设置DNS为localhost
# 添加了扩展信息,浏览器访问会校验失败:ERR_SSL_SERVER_CERT_BAD_FORMAT。不符合相关安全标准
# 不扩展python requests访问又需要这个subjectAltName参数
req.add_extensions([OpenSSL.crypto.X509Extension(b"subjectAltName", False, b"IP.1:127.0.0.1,DNS.1:localhost,DNS.2:testmysite.com")])
req.set_pubkey(key)
req.sign(key, 'sha256')
_private_key = OpenSSL.crypto.dump_privatekey(OpenSSL.crypto.FILETYPE_PEM, key).decode("utf-8")
_public_key = OpenSSL.crypto.dump_publickey(OpenSSL.crypto.FILETYPE_PEM, key).decode("utf-8")
_csr = OpenSSL.crypto.dump_certificate_request(OpenSSL.crypto.FILETYPE_PEM, req).decode("utf-8")
with open("server_private.pem", "wb") as f:
f.write(_private_key.encode())
with open("server_public.pem", "wb") as f:
f.write(_public_key.encode())
with open("server.csr", "wb") as f:
f.write(_csr.encode())
return _public_key, _private_key, _csr
common_name = "localhost"
country = "CN"
state = "GuangDong"
city = "ShenZhen"
organization = "my organization"
organizational_unit = "my organizational unit"
email_address = "my email address"
public_key, private_key, csr = create_csr(common_name, country, state, city, organization, organizational_unit, email_address)
print("public_key: %s" % public_key)
print("private_key: %s" % private_key)
print("csr: %s" % csr)
def test_sign_server_crt(self):
"""
测试用ca证书签发服务端证书(将服务端传来的csr文件发送给CA,由CA签发证书crt)
"""
def sign_csr(csr, ca_crt, ca_key, days=3650):
"""
Args:
csr (str): Certificate signing request (PEM).
ca_crt (str): CA certificate (PEM).
ca_key (str): CA private key (PEM).
days (int): Certificate validity period in days.
Returns:
str: Signed certificate (PEM).
"""
import OpenSSL.crypto
# Convert to OpenSSL objects
csr_obj = OpenSSL.crypto.load_certificate_request(OpenSSL.crypto.FILETYPE_PEM, csr)
ca_crt_obj = OpenSSL.crypto.load_certificate(OpenSSL.crypto.FILETYPE_PEM, ca_crt)
ca_key_obj = OpenSSL.crypto.load_privatekey(OpenSSL.crypto.FILETYPE_PEM, ca_key)
# Create a new certificate
cert = OpenSSL.crypto.X509()
cert.set_subject(csr_obj.get_subject())
# 将请求者的扩展信息添加到证书中
cert.add_extensions(csr_obj.get_extensions())
cert.set_serial_number(0)
cert.gmtime_adj_notBefore(0)
cert.gmtime_adj_notAfter(days * 24 * 60 * 60)
cert.set_issuer(ca_crt_obj.get_subject())
cert.set_pubkey(csr_obj.get_pubkey())
cert.sign(ca_key_obj, 'sha256')
_cert = OpenSSL.crypto.dump_certificate(OpenSSL.crypto.FILETYPE_PEM, cert).decode("utf-8")
with open("server.crt", "wb") as f:
f.write(_cert.encode())
return _cert
csr = open("server.csr").read()
ca_crt = open("ca_selfsign.crt").read()
ca_key = open("ca_private.key").read()
cert = sign_csr(csr, ca_crt, ca_key)
print("服务端证书: %s" % cert)
def test_associate_cert_with_pri(self):
"""
测试生成的证书文件包含的公钥信息(crt)与其私钥的关联
即:查看证书中的公钥与属于的私钥是否匹配
"""
def check_associate_cert_with_private_key(cert, private_key):
"""
:type cert: str
:type private_key: str
:rtype: bool
"""
import OpenSSL
try:
private_key_obj = OpenSSL.crypto.load_privatekey(OpenSSL.crypto.FILETYPE_PEM, private_key)
except OpenSSL.crypto.Error:
raise Exception('private key is not correct: %s' % private_key)
try:
cert_obj = OpenSSL.crypto.load_certificate(OpenSSL.crypto.FILETYPE_PEM, cert)
except OpenSSL.crypto.Error:
raise Exception('certificate is not correct: %s' % cert)
context = OpenSSL.SSL.Context(OpenSSL.SSL.TLSv1_METHOD)
context.use_privatekey(private_key_obj)
context.use_certificate(cert_obj)
try:
context.check_privatekey()
return True
except OpenSSL.SSL.Error:
return False
ca_cert_name = "ca_selfsign.crt"
ca_pri_name = "ca_private.key"
server_cert_name = "server.crt"
server_pri_name = "server_private.pem"
ca_cert = open(ca_cert_name).read()
ca_private_key = open(ca_pri_name).read()
server_cert = open(server_cert_name).read()
server_private_key = open(server_pri_name).read()
ca_result = check_associate_cert_with_private_key(ca_cert, ca_private_key)
print("CA的自签证书中的公钥与CA私钥是否关联: %s" % ca_result)
ca_server_result = check_associate_cert_with_private_key(server_cert, ca_private_key)
print("服务端证书的公钥与CA私钥是否关联: %s" % ca_server_result)
server_result = check_associate_cert_with_private_key(server_cert, server_private_key)
print("服务端证书的公钥与服务端私钥是否关联: %s" % server_result)
def test_verify_server_crt(self):
"""
测试服务端的server.crt是否由ca.crt签发
"""
def verify_cert(cert, ca_cert):
"""
:type cert: str
:type ca_cert: str
:rtype: bool
"""
import OpenSSL
try:
cert_obj = OpenSSL.crypto.load_certificate(OpenSSL.crypto.FILETYPE_PEM, cert)
except OpenSSL.crypto.Error:
raise Exception('certificate is not correct: %s' % cert)
try:
ca_cert_obj = OpenSSL.crypto.load_certificate(OpenSSL.crypto.FILETYPE_PEM, ca_cert)
except OpenSSL.crypto.Error:
raise Exception('ca certificate is not correct: %s' % ca_cert)
store = OpenSSL.crypto.X509Store()
store.add_cert(ca_cert_obj)
store_ctx = OpenSSL.crypto.X509StoreContext(store, cert_obj)
try:
store_ctx.verify_certificate()
return True
except OpenSSL.crypto.X509StoreContextError:
return False
ca_cert_name = "ca_selfsign.crt"
server_cert_name = "server.crt"
ca_cert = open(ca_cert_name).read()
server_cert = open(server_cert_name).read()
result = verify_cert(server_cert, ca_cert)
print("服务端证书是否由CA证书签发: %s" % result)