python RSA加密、解密、签名

python中用于RSA加解密的库有好久个,本文主要讲解rsa、M2Crypto、Crypto这三个库对于RSA加密、解密、签名、验签的知识点。

知识基础

加密是为了保证传输内容隐私,签名是为了保证消息真实性。

服务器存私钥,客户端存公钥。(服务器和客户端关系可以考虑为 1:N)

客户端往服务器传输内容,更多考虑是隐私性,所以公钥签名、私钥解密。

服务器往客户端传输内容,更多考虑真实性,所以私钥签名,公钥验签。

消息的摘要生的算法常用的是MD5或者SHA1,消息内容不一样,生成的摘要信息一定不一样。

真实性的考虑一方面是内容由私钥拥有者发出,另一方面内容在传输过程中没有改变过,所以签名的对象是传输信息生成的消息摘要(摘要内容短,签名也会快些)。

每次加密的长度需要小于密钥长度-特殊位(128位公钥,最长可加密128-11=117位明文)。

每次解密的长度需要小于密钥的长度(128位私钥解密,解密密文长度需要小于等于128位)。

如果加解密内容过长,就需要分段加密、解密。

PEM格式的密钥为base64位文本格式。

环境配置

环境:MAC

python版本:2.7.15(因为公司用的版本都是这个,建议用python3的)

IED:PyCharm

密钥:PEM文件

rsa

示例代码

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

38

39

40

41

42

43

44

45

46

47

48

49

50

51

52

53

54

55

56

57

58

59

60

61

62

63

64

65

66

67

68

69

70

71

72

73

74

75

76

77

78

79

80

81

82

83

84

85

86

87

88

89

90

91

92

93

94

95

96

97

98

99

100

101

102

103

104

105

106

107

108

109

110

111

112

# -*- coding: UTF-8 -*-

# ! /usr/bin/env python

import base64

import rsa

from rsa import common

 

 

# 使用 rsa库进行RSA签名和加解密

class RsaUtil(object):

    PUBLIC_KEY_PATH = '/Users/anonyper/Desktop/key/company_rsa_public_key.pem'  # 公钥

    PRIVATE_KEY_PATH = '/Users/anonyper/Desktop/key/company_rsa_private_key.pem'  # 私钥

 

    # 初始化key

    def __init__(self,

                 company_pub_file=PUBLIC_KEY_PATH,

                 company_pri_file=PRIVATE_KEY_PATH):

 

        if company_pub_file:

            self.company_public_key = rsa.PublicKey.load_pkcs1_openssl_pem(open(company_pub_file).read())

        if company_pri_file:

            self.company_private_key = rsa.PrivateKey.load_pkcs1(open(company_pri_file).read())

 

    def get_max_length(self, rsa_key, encrypt=True):

        """加密内容过长时 需要分段加密 换算每一段的长度.

            :param rsa_key: 钥匙.

            :param encrypt: 是否是加密.

        """

        blocksize = common.byte_size(rsa_key.n)

        reserve_size = 11  # 预留位为11

        if not encrypt:  # 解密时不需要考虑预留位

            reserve_size = 0

        maxlength = blocksize - reserve_size

        return maxlength

 

    # 加密 支付方公钥

    def encrypt_by_public_key(self, message):

        """使用公钥加密.

            :param message: 需要加密的内容.

            加密之后需要对接过进行base64转码

        """

        encrypt_result = b''

        max_length = self.get_max_length(self.company_public_key)

        while message:

            input = message[:max_length]

            message = message[max_length:]

            out = rsa.encrypt(inputself.company_public_key)

            encrypt_result += out

        encrypt_result = base64.b64encode(encrypt_result)

        return encrypt_result

 

    def decrypt_by_private_key(self, message):

        """使用私钥解密.

            :param message: 需要加密的内容.

            解密之后的内容直接是字符串,不需要在进行转义

        """

        decrypt_result = b""

 

        max_length = self.get_max_length(self.company_private_key, False)

        decrypt_message = base64.b64decode(message)

        while decrypt_message:

            input = decrypt_message[:max_length]

            decrypt_message = decrypt_message[max_length:]

            out = rsa.decrypt(inputself.company_private_key)

            decrypt_result += out

        return decrypt_result

 

    # 签名 商户私钥 base64转码

    def sign_by_private_key(self, data):

        """私钥签名.

            :param data: 需要签名的内容.

            使用SHA-1 方法进行签名(也可以使用MD5)

            签名之后,需要转义后输出

        """

        signature = rsa.sign(str(data), priv_key=self.company_private_key, hash='SHA-1')

        return base64.b64encode(signature)

 

    def verify_by_public_key(self, message, signature):

        """公钥验签.

            :param message: 验签的内容.

            :param signature: 对验签内容签名的值(签名之后,会进行b64encode转码,所以验签前也需转码).

        """

        signature = base64.b64decode(signature)

        return rsa.verify(message, signature, self.company_public_key)

 

 

message = 'hell world'

print("明文内容:>>> ")

print(message)

rsaUtil = RsaUtil()

encrypy_result = rsaUtil.encrypt_by_public_key(message)

print("加密结果:>>> ")

print(encrypy_result)

decrypt_result = rsaUtil.decrypt_by_private_key(encrypy_result)

print("解密结果:>>> ")

print(decrypt_result)

sign = rsaUtil.sign_by_private_key(message)

print("签名结果:>>> ")

print(sign)

print("验签结果:>>> ")

print(rsaUtil.verify_by_public_key(message, sign))

 

#执行结果

明文内容:>>>

hell world

加密结果:>>>

sWx9r30CCLXip0iemCb2r1gsZIedgLp1Vmk9uCDaQttcQNftwQyI98shN2Hpn7snE27ziJnH6qYmaf68TWBerhJVGEzr16wLYInVft0Bj0+kcCmLL7tMJRZWydqHi/YzgIfsFEvqLOUFv6E9bCAXhJkikacBAG4FWTMBrXUQHjE=

解密结果:>>>

hell world

签名结果:>>>

GS3MPpb4zMLIL7mqcxZEevOoH1Fse9fjHefWIUpDaMplhoPUNK85TreYmOwvF8QJNxgLcJoKKfRm51gemsQd1/e1FBPo/4VS3kvneJyLUtQAPdOOl+R4h//0gFec+ELI+KS8A74Dkm2bFKztZ4BxIcWD63pHRiGAnS8+cQeq2QM=

验签结果:>>>

True

  

知识点

  • rsa计算密钥长度的方式是 common.byte_size(rsa_key.n)
  • rsa加密:rsa.encrypt(message, pub_key)
  • rsa解密:rsa.decrypt(crypto, priv_key)
  • rsa签名:rsa.sign(message, priv_key, hash)
  • rsa验签:rsa.verify(message, signature, pub_key)
  • rsa默认没有私钥加密,公钥解密的方法(加解密传入错误的key会报错,如果想实现私钥加密,公钥解密可以自行模拟底层代码实现)
  • 签名只能用私钥(用到私钥的n值,公钥没有n值,n、d、e具体什么意思请百度RSA算法原理)
  • rsa加载公钥和私钥的方法不同
  • rsa私钥签名时,需要传入的是不是具体的摘要信息(字符串),而是签名信息的hash对象(对象)
  • 不同版本的rsa验签成功之后返回结果不一样,有的是True,有的是返回生成摘要算法名:如sha1

Crypto

示例代码

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

38

39

40

41

42

43

44

45

46

47

48

49

50

51

52

53

54

55

56

57

58

59

60

61

62

63

64

65

66

67

68

69

70

71

72

73

74

75

76

77

78

79

80

81

82

83

84

85

86

87

88

89

90

91

92

93

94

95

96

97

98

99

100

101

102

103

104

105

106

107

108

109

110

111

112

113

114

115

116

117

118

119

120

121

122

123

124

125

126

127

128

129

130

131

132

133

134

135

136

137

138

139

140

141

142

143

144

145

146

147

148

149

150

151

152

153

154

155

156

157

158

159

160

161

# -*- coding: UTF-8 -*-

# ! /usr/bin/env python

import base64

from Crypto.Cipher import PKCS1_v1_5 as PKCS1_v1_5_cipper

from Crypto.Signature import PKCS1_v1_5

from Crypto.PublicKey import RSA

from Crypto.Hash import SHA

 

import Crypto

 

 

# 使用 rsa库进行RSA签名和加解密

 

 

class RsaUtil(object):

    PUBLIC_KEY_PATH = '/Users/anonyper/Desktop/key/company_rsa_public_key.pem'  # 公钥

    PRIVATE_KEY_PATH = '/Users/anonyper/Desktop/key/company_rsa_private_key.pem'  # 私钥

 

    # 初始化key

    def __init__(self,

                 company_pub_file=PUBLIC_KEY_PATH,

                 company_pri_file=PRIVATE_KEY_PATH):

 

        if company_pub_file:

            self.company_public_key = RSA.importKey(open(company_pub_file).read())

        if company_pri_file:

            self.company_private_key = RSA.importKey(open(company_pri_file).read())

 

    def get_max_length(self, rsa_key, encrypt=True):

        """加密内容过长时 需要分段加密 换算每一段的长度.

            :param rsa_key: 钥匙.

            :param encrypt: 是否是加密.

        """

        blocksize = Crypto.Util.number.size(rsa_key.n) / 8

        reserve_size = 11  # 预留位为11

        if not encrypt:  # 解密时不需要考虑预留位

            reserve_size = 0

        maxlength = blocksize - reserve_size

        return maxlength

 

    # 加密 支付方公钥

    def encrypt_by_public_key(self, encrypt_message):

        """使用公钥加密.

            :param encrypt_message: 需要加密的内容.

            加密之后需要对接过进行base64转码

        """

        encrypt_result = b''

        max_length = self.get_max_length(self.company_public_key)

        cipher = PKCS1_v1_5_cipper.new(self.company_public_key)

        while encrypt_message:

            input_data = encrypt_message[:max_length]

            encrypt_message = encrypt_message[max_length:]

            out_data = cipher.encrypt(input_data)

            encrypt_result += out_data

        encrypt_result = base64.b64encode(encrypt_result)

        return encrypt_result

 

    # 加密 支付方私钥

    def encrypt_by_private_key(self, encrypt_message):

        """使用私钥加密.

            :param encrypt_message: 需要加密的内容.

            加密之后需要对接过进行base64转码

        """

        encrypt_result = b''

        max_length = self.get_max_length(self.company_private_key)

        cipher = PKCS1_v1_5_cipper.new(self.company_public_key)

        while encrypt_message:

            input_data = encrypt_message[:max_length]

            encrypt_message = encrypt_message[max_length:]

            out_data = cipher.encrypt(input_data)

            encrypt_result += out_data

        encrypt_result = base64.b64encode(encrypt_result)

        return encrypt_result

 

    def decrypt_by_public_key(self, decrypt_message):

        """使用公钥解密.

            :param decrypt_message: 需要解密的内容.

            解密之后的内容直接是字符串,不需要在进行转义

        """

        decrypt_result = b""

        max_length = self.get_max_length(self.company_public_key, False)

        decrypt_message = base64.b64decode(decrypt_message)

        cipher = PKCS1_v1_5_cipper.new(self.company_public_key)

        while decrypt_message:

            input_data = decrypt_message[:max_length]

            decrypt_message = decrypt_message[max_length:]

            out_data = cipher.decrypt(input_data, '')

            decrypt_result += out_data

        return decrypt_result

 

    def decrypt_by_private_key(self, decrypt_message):

        """使用私钥解密.

            :param decrypt_message: 需要解密的内容.

            解密之后的内容直接是字符串,不需要在进行转义

        """

        decrypt_result = b""

        max_length = self.get_max_length(self.company_private_key, False)

        decrypt_message = base64.b64decode(decrypt_message)

        cipher = PKCS1_v1_5_cipper.new(self.company_private_key)

        while decrypt_message:

            input_data = decrypt_message[:max_length]

            decrypt_message = decrypt_message[max_length:]

            out_data = cipher.decrypt(input_data, '')

            decrypt_result += out_data

        return decrypt_result

 

    # 签名 商户私钥 base64转码

    def sign_by_private_key(self, message):

        """私钥签名.

            :param message: 需要签名的内容.

            签名之后,需要转义后输出

        """

        cipher = PKCS1_v1_5.new(self.company_private_key)  # 用公钥签名,会报错 raise TypeError("No private key") 如下

        # if not self.has_private():

        #   raise TypeError("No private key")

        hs = SHA.new(message)

        signature = cipher.sign(hs)

        return base64.b64encode(signature)

 

    def verify_by_public_key(self, message, signature):

        """公钥验签.

            :param message: 验签的内容.

            :param signature: 对验签内容签名的值(签名之后,会进行b64encode转码,所以验签前也需转码).

        """

        signature = base64.b64decode(signature)

        cipher = PKCS1_v1_5.new(self.company_public_key)

        hs = SHA.new(message)

 

        # digest = hashlib.sha1(message).digest()  # 内容摘要的生成方法有很多种,只要签名和解签用的是一样的就可以

 

        return cipher.verify(hs, signature)

 

 

 

message = 'hell worldhell worldhell worldhell worldhell worldhell worldhell worldhell worldhell worldhell worldhell worldhell worldhell worldhell worldhell worldhell worldhell worldhell worldhell world'

print("明文内容:>>> ")

print(message)

rsaUtil = RsaUtil()

encrypy_result = rsaUtil.encrypt_by_public_key(message)

print("加密结果:>>> ")

print(encrypy_result)

decrypt_result = rsaUtil.decrypt_by_private_key(encrypy_result)

print("解密结果:>>> ")

print(decrypt_result)

sign = rsaUtil.sign_by_private_key(message)

print("签名结果:>>> ")

print(sign)

print("验签结果:>>> ")

print(rsaUtil.verify_by_public_key(message, sign))

 

#执行结果:

明文内容:>>>

hell worldhell worldhell worldhell worldhell worldhell worldhell worldhell worldhell worldhell worldhell worldhell worldhell worldhell worldhell worldhell worldhell worldhell worldhell world

加密结果:>>>

PC8/knkmszKby2pHtlKJa/Uv7EADImNhrFwZQK3YHpwPwDpt5A4bFTxsDu2o8U0yc+X50+M3Bi53C0sOHjiOCStG/Bp1nfowHQBgUFCETp4G3fpLAl7eWynqqu6gInjHQeNMbBz1wvRhSiXoMB2lJm8b9fLuzDuQQRFZPqD356kgTKnBM+lju4HE4zMjAT8jMam5Z4EnmaRfX7kYDGzga+PgbkkGon354i3CRhuRWtpvQeXnmjZq8MpfDC6//L7I/vvw4/LMJhiQJkXUbGEgSok8yg6jZzGx+bllc+qn7DH5nkNZKkOnqaeJHbEktgdhua/QXJcRR/5Lm0Y8ovs54A==

解密结果:>>>

hell worldhell worldhell worldhell worldhell worldhell worldhell worldhell worldhell worldhell worldhell worldhell worldhell worldhell worldhell worldhell worldhell worldhell worldhell world

签名结果:>>>

VinHhT+iJfDvIgseJ0ZsmJcLk+yDdx0323B6vMKMUHDlUF2HDWqQhEEoqmSstjsSfR/T+4829t5DhtaJ5w1O7K7ZyP/+yu/lupc8apmfYSIziozi3vPy20p/CYNaXAy0LLGOwrtVNn3jTaq7Gb0yI4/Zhin2jNmTk09g8Qx9rGI=

验签结果:>>>

True

  

知识点

  • Crypto计算密钥长度的方法是 Crypto.Util.number.size(rsa_key.n) / 8(一个字节8位)
  • Crypto导入密钥的方法是同一个 RSA.importKey(self, externKey, passphrase=None),externKey为密钥内容
  • Crypto加密方法:Crypto.Cipher.PKCS1_v1_5.new(key).encrypt(self, message)
  • Crypto解密方法:Crypto.Cipher.PKCS1_v1_5.new(key).decrypt(self, message)
  • Crypto签名方法:Crypto.Signature.PKCS1_v1_5.new(key).sign(self, mhash)
  • Crypto验签方法:Crypto.Signature.PKCS1_v1_5_cipper.new(key).verifyverify(self, mhash, S)
  • Crypto公钥、私钥都可以互相加解密
  • Crypto只能私钥签名,公钥验签,签名传入公钥会报错(底层有key.has_private()判断)
  • Crypto私钥签名时,需要传入的是消息的摘要内容,所以摘要可以由不同的实现方式只要验签时摘要算法一致即可。
  • Crypto验签之后成功返回结果True(不知道会不会与其他的)

M2Crypto

示例代码

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

38

39

40

41

42

43

44

45

46

47

48

49

50

51

52

53

54

55

56

57

58

59

60

61

62

63

64

65

66

67

68

69

70

71

72

73

74

75

76

77

78

79

80

81

82

83

84

85

86

87

88

89

90

91

92

93

94

95

96

97

98

99

100

101

102

103

104

105

106

107

108

109

110

111

112

113

114

115

116

117

118

119

120

121

122

123

124

125

126

127

128

129

130

131

132

133

134

135

136

137

138

139

140

141

142

143

144

145

146

147

148

149

150

151

152

# -*- coding: UTF-8 -*-

# ! /usr/bin/env python

import base64

import M2Crypto

from M2Crypto import EVP

 

 

# 使用 M2Crypto库进行RSA签名和加解密

class RsaUtil(object):

    PUBLIC_KEY_PATH = '/Users/anonyper/Desktop/key/company_rsa_public_key.pem'  # 公钥

    PRIVATE_KEY_PATH = '/Users/anonyper/Desktop/key/company_rsa_private_key.pem'  # 私钥

 

    # 初始化key

    def __init__(self,

                 company_pub_file=PUBLIC_KEY_PATH,

                 company_pri_file=PRIVATE_KEY_PATH):

 

        if company_pub_file:

            self.company_public_key = M2Crypto.RSA.load_pub_key(company_pub_file)

        if company_pri_file:

            self.company_private_key = M2Crypto.RSA.load_key(company_pri_file)

 

    def get_max_length(self, rsa_key, encrypt=True):

        """加密内容过长时 需要分段加密 换算每一段的长度.

            :param rsa_key: 钥匙.

            :param encrypt: 是否是加密.

        """

        blocksize = rsa_key.__len__() / 8

        reserve_size = 11  #

        if not encrypt:

            reserve_size = 0

        maxlength = blocksize - reserve_size

        return maxlength

 

    # 加密 支付方公钥

    def encrypt_by_public_key(self, encrypt_message):

        """使用公钥加密.

            :param encrypt_message: 需要加密的内容.

            加密之后需要对接过进行base64转码

        """

        encrypt_result = b''

        max_length = self.get_max_length(self.company_public_key)

        print(max_length)

        while encrypt_message:

            input_data = encrypt_message[:max_length]

            encrypt_message = encrypt_message[max_length:]

            out_data = self.company_public_key.public_encrypt(input_data, M2Crypto.RSA.pkcs1_padding)

            encrypt_result += out_data

        encrypt_result = base64.b64encode(encrypt_result)

        return encrypt_result

 

    # 加密 支付方私钥

    def encrypt_by_private_key(self, encrypt_message):

        """使用私钥加密.

            :param encrypt_message: 需要加密的内容.

            加密之后需要对接过进行base64转码

        """

        encrypt_result = b''

        max_length = self.get_max_length(self.company_private_key)

        while encrypt_message:

            input_data = encrypt_message[:max_length]

            encrypt_message = encrypt_message[max_length:]

            out_data = self.company_private_key.private_encrypt(input_data, M2Crypto.RSA.pkcs1_padding)

            encrypt_result += out_data

        encrypt_result = base64.b64encode(encrypt_result)

        return encrypt_result

 

    def decrypt_by_public_key(self, decrypt_message):

        """使用公钥解密.

            :param decrypt_message: 需要解密的内容.

            解密之后的内容直接是字符串,不需要在进行转义

        """

        decrypt_result = b""

        max_length = self.get_max_length(self.company_private_key, False)

        decrypt_message = base64.b64decode(decrypt_message)

        while decrypt_message:

            input_data = decrypt_message[:max_length]

            decrypt_message = decrypt_message[max_length:]

            out_data = self.company_public_key.public_encrypt(input_data, M2Crypto.RSA.pkcs1_padding)

            decrypt_result += out_data

        return decrypt_result

 

    def decrypt_by_private_key(self, decrypt_message):

        """使用私钥解密.

            :param decrypt_message: 需要解密的内容.

            解密之后的内容直接是字符串,不需要在进行转义

        """

        decrypt_result = b""

        max_length = self.get_max_length(self.company_private_key, False)

        decrypt_message = base64.b64decode(decrypt_message)

        while decrypt_message:

            input_data = decrypt_message[:max_length]

            decrypt_message = decrypt_message[max_length:]

            out_data = self.company_private_key.private_decrypt(input_data, M2Crypto.RSA.pkcs1_padding)

            decrypt_result += out_data

        return decrypt_result

 

    # 签名 商户私钥 base64转码

    def sign_by_private_key(self, message):

        """私钥签名.

            :param message: 需要签名的内容.

            签名之后,需要转义后输出

        """

        hs = EVP.MessageDigest('sha1')

        hs.update(message)

        digest = hs.final()

        # digest = hashlib.sha1(message).digest() # 内容摘要的生成方法有很多种,只要签名和解签用的是一样的就可以

        signature = self.company_private_key.sign(digest)

        # self.company_public_key.sign(digest)  # 用公钥签名IDE会崩

        return base64.b64encode(signature)

 

    def verify_by_public_key(self, message, signature):

        """公钥验签.

            :param message: 验签的内容.

            :param signature: 对验签内容签名的值(签名之后,会进行b64encode转码,所以验签前也需转码).

        """

        hs = EVP.MessageDigest('sha1')

        hs.update(message)

        digest = hs.final()

        # digest = hashlib.sha1(message).digest()  # 内容摘要的生成方法有很多种,只要签名和解签用的是一样的就可以

        signature = base64.b64decode(signature)

        return self.company_public_key.verify(digest, signature)

 

 

message = 'hell worldhell worldhell worldhell worldhell worldhell worldhell worldhell worldhell worldhell worldhell worldhell worldhell worldhell worldhell worldhell worldhell worldhell worldhell world'

print("明文内容:>>> ")

print(message)

rsaUtil = RsaUtil()

encrypy_result = rsaUtil.encrypt_by_public_key(message)

print("加密结果:>>> ")

print(encrypy_result)

decrypt_result = rsaUtil.decrypt_by_private_key(encrypy_result)

print("解密结果:>>> ")

print(decrypt_result)

sign = rsaUtil.sign_by_private_key(message)

print("签名结果:>>> ")

print(sign)

print("验签结果:>>> ")

print(rsaUtil.verify_by_public_key(message, sign))

 

 

#执行结果

明文内容:>>>

hell worldhell worldhell worldhell worldhell worldhell worldhell worldhell worldhell worldhell worldhell worldhell worldhell worldhell worldhell worldhell worldhell worldhell worldhell world

加密结果:>>>

fu4RgyOaokEcLmA5k0otMirZoiFBDBkEgycgehEajtPU+xP7Wf5rN05kwbsDNI7/kUR5wOvS0XE8jD1nYmKv4uBWfR5Z28BHdK20uue/8zTnPgdsAmRdzA6Lb2EIk/g38o2EtRZ4jILNOdikpW0kYpYRdaJgoHTWTOlE/RL9zcVKzYELFPpWui2jZ8EVMe+6ZiPkRKCKL571f/OTb1qOdg4GTiowZCNMIknTxXawvZl9Funz7TNz0WsNDejL+r3tM8erwhE0ygIMtemOiVy8yBVsHpHPzfdlNRoXXgtgupFEgVgEOODUp9y4LzX6UDf0+i8uI7/SpyQoa9jSpcsIjA==

解密结果:>>>

hell worldhell worldhell worldhell worldhell worldhell worldhell worldhell worldhell worldhell worldhell worldhell worldhell worldhell worldhell worldhell worldhell worldhell worldhell world

签名结果:>>>

VinHhT+iJfDvIgseJ0ZsmJcLk+yDdx0323B6vMKMUHDlUF2HDWqQhEEoqmSstjsSfR/T+4829t5DhtaJ5w1O7K7ZyP/+yu/lupc8apmfYSIziozi3vPy20p/CYNaXAy0LLGOwrtVNn3jTaq7Gb0yI4/Zhin2jNmTk09g8Qx9rGI=

验签结果:>>>

1

  

知识点

  • M2Crypto计算密钥长度的方法是 rsa_key.len() / 8(一个字节8位)
  • M2Crypto导入密钥的方法是不同 M2Crypto.RSA.load_pub_key(file),M2Crypto.RSA.load_key(file)//还有其他的,不列举了,使用load_key(file)传入公钥地址会报错。
  • M2Crypto加密解密代码:(RSA class下)

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

def public_encrypt(self, data, padding):

    # type: (bytes, int) -> bytes

    assert self.check_key(), 'key is not initialised'

    return m2.rsa_public_encrypt(self.rsa, data, padding)

 

def public_decrypt(self, data, padding):

    # type: (bytes, int) -> bytes

    assert self.check_key(), 'key is not initialised'

    return m2.rsa_public_decrypt(self.rsa, data, padding)

 

def private_encrypt(self, data, padding):

    # type: (bytes, int) -> bytes

    assert self.check_key(), 'key is not initialised'

    return m2.rsa_private_encrypt(self.rsa, data, padding)

 

def private_decrypt(self, data, padding):

    # type: (bytes, int) -> bytes

    assert self.check_key(), 'key is not initialised'

    return m2.rsa_private_decrypt(self.rsa, data, padding)

  

  • 公钥和私钥具体实现RSA的代码:

1

2

3

4

5

6

7

8

9

10

11

12

13

class RSA_pub(RSA):

 

    """

    Object interface to an RSA public key.

    """

    #公钥调用下面方法直接报错

    def private_encrypt(self*argv):

        # type: (*Any) -> None

        raise RSAError('RSA_pub object has no private key')

    #公钥调用下面方法直接报错

    def private_decrypt(self*argv):

        # type: (*Any) -> None

        raise RSAError('RSA_pub object has no private key')

  

  • M2Crypto签名和验签 sign(self, digest, algo='sha1'):/verify(self, data, signature, algo='sha1'):
  • M2Crypto公钥、私钥都可以互相加解密
  • M2Crypto只能私钥签名,公钥验签,签名传入公钥会报错(公钥可以调用签名方法,但是IDE崩溃了)
  • M2Crypto私钥签名时,需要传入的是消息的摘要内容,所以摘要可以由不同的实现方式只要验签时摘要算法一致即可。
  • M2Crypto验签之后成功返回结果1(不知道会不会与其他的)

其他注意事项

  • base64位encode和decode时,可以传入编码集,UTF-8会将+转化为u,将/转化为t
  • 在和服务器交互时,‘+’、‘=’、‘/’ 等特殊字符可能会被转义,造成客户端和服务器内容细微的不一致而导致验签失败,尤其是两边使用的语言不通,所以要协商好转义方案。
  • 更多资讯或疑问内容添加小编微信, 回复 “Python” ,领取更多资料哦

        

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/547688.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

php7 有参数类型,PHP7中的可空返回类型

小编典典PHP 7.1现在支持可为空的返回类型。我链接到的第一个RFC是他们使用的RFC:function nullOrString(int $foo) : ?string{return $foo%2 ? "odd" : null;}旧答案:由于我的评论实际上是对该问题的答案:PHP7尚不支持可空的返回…

DataGridview动态添加列

1.获取数据源&#xff08;select * from table名称&#xff09; 2.动态绑定数据源 1 private void GetTableInfo(DataTable dt)2 {3 listBh new List<BH_DICTInfo>();4 foreach (DataRow dr in dt.Rows)5 {6 …

C# 控制台应用程序输出颜色字体[更正版]

首先感谢院子里的“yanxinchen”&#xff0c;之前的方法是通过c#调用系统api实现的&#xff0c;相比之下我的有点画蛇添足了&#xff0c;哈哈。 最佳解决方案的代码&#xff1a; static void Main(string[] args){ Console.ForegroundColor ConsoleColor.Green; Consol…

MXNet结合kubeflow进行分布式训练

GPU集群配置MXNetCUDA 为方便控制集群&#xff0c;写了脚本cmd2all.sh #!/bin/bash if [ $# -lt 3 ]; thenecho "usage: $0 [type cmds hosts]"echo "for example: ./cmd2all.sh \"cmds\" \"touch t1.txt\" \"gpu1 gpu2\""…

php新建文件在指定目录下,PHP在获取指定目录下的目录,在获取的目录下面再创建文件,多平台...

代码如下://取得指定文件夹的目录名称function get_dir_name($dir_path,$file){$dirpath $dir_path;$dir scandir($dirpath);foreach ($dir as $key>$value){if (is_dir($dirpath./.$value) && $value ! . && $value ! ..){//echo $dirpath./.$value./.$f…

性能测试流程

一个项目如果有性能需求&#xff0c;那恭喜你&#xff0c;你接到活了&#xff0c;于是你开始着手开始性能测试。 首先第一步&#xff0c;你会先去了解业务&#xff0c;与此同时&#xff0c;产品或者项目经理也会给出他们的一些性能需求&#xff0c;和相关的指标要求&#xff0c…

基于Opencv的水位识别,液面识别、高度识别

Update 代码已经上传到github上了&#xff0c;可以点这里 Cutting 一直说这要整理一下Computer Vision课程的大作业&#xff0c;拖了好久。这两天忙着写一个订单处理的第三方库&#xff0c;陷入了僵局&#xff0c;所以换个口味&#xff0c;把大作业整理一下。 Requirement W…

php最新版本的安装,centos安装新PHP版本

方法一&#xff1a;yum 安装默认的版本太低了&#xff0c;手动安装有一些麻烦&#xff0c;想采用Yum安装的可以使用下面的方案&#xff1a;1.检查当前安装的PHP包yum list installed | grep php如果有安装的PHP包&#xff0c;先删除他们yum remove php.x86_64 php-cli.x86_64 p…

Openshift3.9部署手册

说明&#xff1a;本文主要介绍通过Ansible来部署Openshift 3.9 一、准备 系统准备 节点类型说明Masters 物理主机或者虚拟机 系统&#xff1a;Fedora 21, CentOS 7.3, 7.4或者7.5 最少4vCPU 最少16GB内存 /var/最少40GB空间 /usr/local/bin最少1GB空间 容器临时目录最少1GB空…

php 获取 table,php – 获取表对象(App_Model_TableName)作为获取结果(Zend Framework)

现在,我在我的模型中写了一个函数&#xff1a;public function getRowsByZipCode($zip){// SQL to get all the rows with the given zip code$stmt $this -> getAdapter()-> query( "SELECT *FROMtable_nameWHEREtable_name.status 1 ANDtable_name.zip{$zip}&qu…

Solr入门——安装

为什么80%的码农都做不了架构师&#xff1f;>>> Solr网址http://lucene.apache.org/solr/ OSC地址&#xff1a;http://www.oschina.net/p/solr 下载地址&#xff1a;http://www.apache.org/dyn/closer.cgi/lucene/solr/4.3.1 解压 1、拷贝 solr-4.3.1/dist/…

Kubernetes 部署 Ingress 控制器 Traefik v2.1

目录[-] . 一、Traefik 简介. 二、Kubernetes 部署 Traefik. 1、创建 CRD 资源. 2、创建 RBAC 权限. 3、创建 Traefik 配置文件. 4、节点设置 Label 标签. 5、Kubernetes 部署 Traefik. 三、Traefik 路由规则配置. 1、配置 HTTP 路由规则 &#xff08;Traefik Dashboard 为例&…

java调用小冰,Java利用微软小冰API测颜值

【需求背景】七月入职&#xff0c;做了一个交友mini项目&#xff0c;有涉及一个给人脸颜值评分的需求。经过网上搜索&#xff0c;发现微软小冰可以很好解决这个需求。【说明】根据mini项目&#xff0c;用Spring-boot框架实现了一个demo&#xff0c;在html页面&#xff0c;上传个…

svn完整搭建

安装软件 # yum install httpd mod_dav_svn subversion mod_ssl 查看是否安装成功#svn --version 如果出现版本号如则说明svn安装成功查看httpd配置文件/etc/httpd/conf/httpd.conf如果找到这说明apache模块安装正确配置1.创建版本库# mkdir -pv /svn/date --创建主目录# svn…

where in的sql语句按照指定ID进行排序的解决方法

做网站的时候需要一个需求&#xff0c;需要按照指定的ID获取数据库中的数据&#xff0c;返回数据的顺序要和指定ID的顺序相同&#xff0c;数据库是SQL Server的&#xff0c;下面的代码是在网上找来的&#xff0c;SQL server的已经测试过&#xff0c;可以满足要求。 Access:sele…

Kubernetes 部署 Ingress 控制器 Traefik v1.7.4

标签: kubernetes ingress traefik nginx haproxy kong 介绍TraefikIngress 对象 上节课我们学习了在Kubernetes集群内部使用kube-dns实现服务发现的功能&#xff0c;那么我们部署在Kubernetes集群中的应用如何暴露给外部的用户使用呢&#xff1f;我们知道前面我们…

php iis redis,iis windows phpstudy安装redis扩展

说明,我的服务器是2008 64位 php5.4.33首先下载符合条件的redis扩展,是否符合条件可以参考https://pecl.php.net/package/redis,进入之后,点击"DLL"可以看到红圈里面的就是适合iis的non thread safe就是非安全线程下面那个thread safe适合apache下面两个就是下载所需…

几种常见SQL分页方式效率比较

转载地址&#xff1a;http://www.cnblogs.com/iamowen/archive/2011/11/03/2235068.html 分页很重要&#xff0c;面试会遇到。不妨再回顾总结一下。 1.创建测试环境&#xff0c;(插入100万条数据大概耗时5分钟)。 create database DBTestuse DBTest--创建测试表create table…

在Eclipse中,用XFire发布web服务

配置及相关说明见http://www.cnblogs.com/xshy3412/archive/2007/09/29/910848.html 仅确定发布xfire需要的最基本的jar activation-1.1.jar commons-logging-1.0.4.jar jdom-1.0.jar jsr173_api-1.0.jar spring-1.2.6.jar stax-utils-20040917.jar wsdl4j-1.6.1.jar wstx-asl-…

BinderHub 使用简介

使用 Binder 將公開的 GitHub Repository 轉換為可互動、可執行程式碼並能在瀏覽器上一鍵啟動的 JupyterHub 伺服器&#xff0c;讓我們可以快速地建造出方便分享的教學環境。 Python 3.6 JupyterLabPython 3.7 Jupyter NotebookR 3.6 JupyterHubR 3.6 RStudio 使用 Binder 與 …