Crypto模块:加密、签名

密码与通信:

信息传播离不开加密与解密。密码技术的用途主要源于两个方面,加密/解密签名/验签

在信息传播中,通常有发送者接受者窃听者三个角色。

加密/解密:假设发送者Master想要写信给接受者Ghost,可是又不想信的内容被别人看到,因此Master需要先对信加密,而Ghost收到信之后又能解密。这样别的人即使窃听盗取了密文也无法解密。

签名/验签:如果窃听者并不想破译内容,而是伪造Master发消息给Ghost,那么Master发消息前就得先对机密内容进行签名。

密码技术:

常见的加密方式有RSA, AES等算法。

Python密码库–Crypto:

Python良好的生态,对于加密解密技术都有成熟的第三方库。大名鼎鼎的M2CryptoPycrypto,前者非常容易使用,可是安装却非常头疼,不同的系统依赖软件的版本还有影响。后者则比较方面,直接使用pip安装即可。

pip install pycrypto

RSA 密码算法与签名

RSA是一种公钥密码算法,RSA的密文是对代码明文的数字的 E 次方求mod N 的结果。也就是将明文和自己做E次乘方,然后再将其结果除以 N 求余数,余数就是密文。RSA是一个简洁的加密算法。E 和 N 的组合就是公钥public key)。

对于RSA的解密,即密文的数字的 D 次方求mod N 即可,即密文和自己做 D 次乘方,再对结果除以 N 求余数即可得到明文。D 和 N 的组合就是私钥private key)。

算法的加密和解密还是很简单的,可是公钥和私钥的生成算法却不是随意的。

 

一、生成秘钥对:

使用 Pycrypto生成秘钥对很简单,我们分别为 Master和Ghost各生成一对属于自己的秘钥对。

from Crypto import Random
from Crypto.Hash import SHA
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.PublicKey import RSA
 
# 伪随机数生成器
random_generator = Random.new().read
# rsa算法生成实例,即生成RSA的token
rsa = RSA.generate(1024, random_generator)
 
# master的秘钥对的生成
private_pem = rsa.exportKey()
 
with open('master-private.pem', 'w') as f:
    f.write(private_pem)
 
public_pem = rsa.publickey().exportKey()
with open('master-public.pem', 'w') as f:
    f.write(public_pem)
 
# ghost的秘钥对的生成;rsa实例生成,略
private_pem = rsa.exportKey()
with open('ghost-private.pem', 'w') as f:
    f.write(private_pem)
 
public_pem = rsa.publickey().exportKey()
with open('ghost-public.pem', 'w') as f:
    f.write(public_pem)

 所生成的私钥和公钥大概是这样的:

-----BEGIN RSA PRIVATE KEY-----
MIICXgIBAAKBgQDPa20EODc6UWgw5bWNa9Xb/EMIuLRtDcr+a0VYueh4NXbXYzS8
y9eE8WZUFy7MniVjnWdyu2My1tOsLivAgPG25tvsy5ubQ7a0Xg2QPHGyKWR6UkxE
wGMH3velq56cUbniwjeOXSEj+TJBwkZG+g9WluOMP7FHZ+Q6p6pBvtzdgwIDAQAB
AoGBAK53aMJU2rd2BBKlFRn4a3FXdbcfTbwxDt8DsdfYwB5ksiqnqpNnTkfnmTAA
NAAuwbpRitMppV387xzz1R9eFnFDgBjYBRVXKVyotzo9//7MkBHz7FlGXaklC51Z
8z8pNbi+svnAcTWHEJBRmGiuiy5FoUSncdbJt8Xr0k5v19wpAkEA5DHbijslRD5w
6YasE5kAOAVmNn9U2KAPGTwQhZd5FzunregdDqR7VhUE/GhEtNAR9E4vaCBiMeZ4
5xfIOuGZvQJBAOixhihz7UcXPfhjkInuwUZURQO18/5MmBTLDMZu5dUy61z/1n4Y
6k1K9wm7KxnGf1FDwKNbIEs3YGNhURuEqD8CQQCkytygltXy0qT4ACmEfZmK21tV
P98mEXDV6GqGDz2DabFOBbH2QRJQuB1BqorziM9ufof9ymUfZDErsiEHZKSBAkEA
gl6j2ZpJwGDHOZke7Ai2hJ7GI/QXhcyIEG5K9ApB/pcOwwYbuH5hF3j+u5b/6OsL
fg5FqcBucXXPLR7jAFXspQJAN8uyg8/8NDcMCj5DgxGpMk5VbUDnX6JdRCZM/Oo1
4SyvXBWi53HF1kwekv8MPZuJTwek41ychyHtPs/CGFVVQw==
-----END RSA PRIVATE KEY-----


-----BEGIN PUBLIC KEY-----
MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDPa20EODc6UWgw5bWNa9Xb/EMI
uLRtDcr+a0VYueh4NXbXYzS8y9eE8WZUFy7MniVjnWdyu2My1tOsLivAgPG25tvs
y5ubQ7a0Xg2QPHGyKWR6UkxEwGMH3velq56cUbniwjeOXSEj+TJBwkZG+g9WluOM
P7FHZ+Q6p6pBvtzdgwIDAQAB
-----END PUBLIC KEY-----

二、加密与解密

通常通信的时候,发送者使用接受者的公钥加密,接受者使用接受者私钥解密。

简而言之,Master给Ghost通信,需要加密内容,那么Ghost会生成一个秘钥对,Ghost的公钥ghost-public.pem和私钥ghost-private.pem 。Ghost 把公钥公开给发送者,任何人都可以用来加密,然后Master使用ghost-public.pem进行加密,然后把内容发给Ghost,Ghost再使用ghost-private.pem进行解密。

加密(encrypt):

# Master使用Ghost的公钥对内容进行rsa 加密
 
In [34]: message = 'hello ghost, this is a plian text'
In [34]: message = message.encode()
In [36]: with open('ghost-public.pem') as f:
    ...:     key = f.read()
    ...:     rsakey = RSA.importKey(key)
    ...:     cipher = Cipher_pkcs1_v1_5.new(rsakey)
    ...:     cipher_text = base64.b64encode(cipher.encrypt(message))
    ...:     print(cipher_text)
    ...:    
    ...:    
b'SJNefnhYUHPFTVG8GF+2EzsFCzjkVZZ2TtjksUl25NkMGwjLR0REN39md7zvV00itbVGFN3QuRAhR9yctRAYlqrfv2aaE/OMYlHU9g7rzB+qiuV+DNUObi9/WEsrTThrLKUw8+rMvISZnbgqRwNPH4CQ2TsOctE7uWTzbUFU1oA='

cipher_text 即 Master加密后将要发送给Ghost的密文。

解密(decrypt):

# Ghost使用自己的私钥对内容进行rsa 解密 
 
In [39]: with open('ghost-private.pem') 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)
    ...:     
b'hello ghost, this is a plian text'
In [46]: assert text == message  #验证text和message内容是否相同,若验证成功,没有返回;验证失败,抛出异常

这样Ghost就能看到Master所发的内容了,当然,如果Ghost想要给Master发消息,就需要Master先把其的公钥给Ghost,后者再使用公钥加密,然后发送给Master,最后Master使用自己的私钥解密。

三、签名与验签

当然,对于窃听者,有时候也可以对伪造Master给Ghost发送内容。为此出现了数字签名。也就是Master给Ghost发送消息的时候,先对消息进行签名,表明自己的身份,并且这个签名无法伪造。具体过程即Master使用自己的私钥对内容签名,然后Ghost使用Master的公钥进行验签。

签名:

# Master 使用自己的私钥对内容进行签名

In [49]: with open('master-private.pem') as f:
    ...:     key = f.read()
    ...:     rsakey = RSA.importKey(key)
    ...:     signer = Signature_pkcs1_v1_5.new(rsakey)
    ...:     digest = SHA.new()
    ...:     sign = signer.sign(digest)
    ...:     signature = base64.b64encode(sign)
    ...:     print(signature)
    ...:     
b'RESxC/YUQZdqn/fUnBdwnbTBASlHPTjRXtLeuPNoShSrjlSqC7sYEnJ/e4XeC6QErjJFPsrnYO9e80WTJcsJOSiYJ+tYa3OCIqJk8aoFdHgaGsO0PRtmFueBJmw7LAsynsfZSb6qrWd9wCHqf15BzjbOw1MiRT0oER2Z5dHFnn8='

验签:

# Ghost使用Master的公钥对内容对行验签:
In [50]: with open('master-public.pem') as f:
    ...:     key = f.read()
    ...:     rsakey = RSA.importKey(key)
    ...:     verifier = Signature_pkcs1_v1_5.new(rsakey)
    ...:     digest = SHA.new()
    ...:     # Assumes the data is base64 encoded to begin with
    ...:     digest.update(message)
    ...:     is_verify = signer.verify(digest, base64.b64encode(signature))
    ...:     print(is_verify)
    ...:     
0(True)

总结

Pycrypto提供了比较完善的加密算法。RSA广泛用于加密与解密,还有数字签名通信领域。使用Publick/Private秘钥算法中,加密主要用对方的公钥,解密用自己的私钥。签名用自己的私钥,验签用对方的公钥。

加密解密:公钥加密,私钥解密

签名验签:私钥签名,公钥验签

无论是加密机密还是签名验签都使用同一对秘钥对。

 

posted on 2018-04-04 16:05  myworldworld  阅读(1099)  评论(0)    收藏  举报

导航