当前位置:   article > 正文

[python] bin转dfu 脚本 RSA2048 签名 解密 公钥 私钥_rsa2048生成的公钥私钥多长

rsa2048生成的公钥私钥多长

一、简介

RSA算法密钥长度的选择

RSA算法密钥长度的选取直接关系到加解密、签名验签的安全强度和运算速度。密钥的长度实际上是指公钥模N的长度(以Bit为单位),理论上来讲N越大,安全强度越高,算法运算速度越慢。因此,RSA算法密钥长度要结合项目的实际情况来选取,以求在安全性和运算性能之间取得平衡点。例如:有些产品的应用场景要求RSA加解密必须具有很高的实时性,比依托于强大CPU性能,不需要过多考虑RSA运算速度,还有些终端产品如公交刷卡机。如果RSA运算时间过长会导致刷卡交易整体时间延长,用户刷卡体验变差,上下车客流速度变慢,因此这种应用场景不适合选取过高的公钥模长。有些PC端产品,虽然MCU运算性能偏弱,但是增加了一颗带有协处理器的加密芯片来协助MCU完成运算,这样就能很好的实现运算加速,因此不需要过多担心速度问题,可以选取较高的公钥模长来提升系统安全强度。总体来说,现在市场上RSA公钥长度应用较多的是1024位和2048位,简称RSA1204算法和RSA2048算法。

RSA几个特性如下:

(1)密钥长度增长一倍,公钥操作所需时间增加约4倍,私钥操作所需时间增加约8倍,公私钥生成时间约增长16倍。

(2) 一次能加密的密文长度与公钥长度成正比,如RSA1024,一次能加密的内容长度为 1024/8 = 128byte(包含填充字节)。所以非对称加密一般都用于加密对称加密算法的密钥,而不是直接加密内容。

(3) 加密后密文的长度为公钥的长度,例如公钥长度为1024Bit(128Byte),最后生成的密文固定为 1024Bit(128Byte)。

二、使用方法

使用帮助:
-h 查看帮助
-s bin文件路径 例: E:\123.bin
-o dfu文件输出路径 例: D:
-v 版本号 例: 0.0.1.0
-t 类型 例: factory或user或engineer
-k 查看秘钥 例:
-c 创建秘钥 例:
完整例子: xxx.exe -s E:\folk.bin -o D:\ -v 0.0.1.0 -t factory

钥匙路径:.\xBin2Dfu\key
(生成的钥匙目录里面会含有keys.h文件,请放置指定地点使用。例:/utils/rsa/)

两种使用方式:
第一种,脚本运行。(需要python环境并安装第三方RSA库)。
路径:xBox/Makefile
使用方式:
IMAGE_DFU: $(IMAGE_BIN)
@python $(PWD)/tools/xBin2Dfu/xBin2Dfu.py -s ( K B U I L D O U T P U T ) / (KBUILD_OUTPUT)/ (KBUILDOUTPUT)/(T).bin -o $(KBUILD_OUTPUT) -v $(REVISION_INFO_S) -t $(REVISION_TYPE_S)

第二种,exe运行(无需环境)。
路径:xBox/Makefile
IMAGE_DFU: ( I M A G E B I N ) @ (IMAGE_BIN) @ (IMAGEBIN)@(PWD)/tools/xBin2Dfu/xBin2Dfu.exe -s ( K B U I L D O U T P U T ) / (KBUILD_OUTPUT)/ (KBUILDOUTPUT)/(T).bin -o $(KBUILD_OUTPUT) -v $(REVISION_INFO_S) -t $(REVISION_TYPE_S)

三、笔记

使用脚本时,需要安装第三方库
环境: python 3.6.8
编译: .\make.bat main.py
安装命令: pip install xxx
依赖:rsa, 其余根据提示安装。

四、示例代码

import hashlib
import os
import sys
import time
from datetime import datetime

import rsa


class my_sign():

    pubkey = ""
    privkey = ""

    def __init__(self, path):
        self.py_path = path
        self.pubkey_path = self.py_path + '\\key\\public.pem'
        self.privkey_path = self.py_path + '\\key\\private.pem'
        self.keys_path = self.py_path + '\\key\\keys.h'
        self.read_key()
        rsa.key.find_p_q = self.find_p_q  # 替换库函数

    # 重写RSA库,使得秘钥长度为256或512
    def find_p_q(self, nbits, getprime_func, accurate):
        total_bits = nbits * 2
        shift = 0  # 取消偏移,使长度为256
        pbits = nbits + shift
        qbits = nbits - shift
        # Choose the two initial primes
        p = getprime_func(pbits)
        q = getprime_func(qbits)

        def is_acceptable(p: int, q: int):
            if p == q:
                return False

            if not accurate:
                return True

            # Make sure we have just the right amount of bits
            found_size = rsa.common.bit_size(p * q)
            return total_bits == found_size

        # Keep choosing other primes until they match our requirements.
        change_p = False
        while not is_acceptable(p, q):
            # Change p on one iteration and q on the other
            if change_p:
                p = getprime_func(pbits)
            else:
                q = getprime_func(qbits)

            change_p = not change_p

        # We want p > q as described on
        return max(p, q), min(p, q)

    def get_data(self, path):
        data = []
        if(path.find(".bin") > -1):
            with open(path, 'rb') as f:
                data = f.read()
                f.close()
        return data

    def hex_output(self, bytes_s):
        i = 0
        s = ""
        for data in bytes_s:
            if(i >= 16):
                i = 0
                s = s[:-1] + "\n"
            i = i + 1
            s = s + '0x' + ('%02X' % data) + ", "
        return s[:-2]

    def buff_output(self, input_s, buf_head):
        input_s = input_s.replace("\n", "\n    ")
        input_s = "    " + input_s
        input_s = "const static unsigned char " + \
            buf_head + "[] = {\n" + input_s + "};"

        return input_s

    def get_out_path(self, src_path, out_path):
        if out_path is not None:
            file_path = out_path
            # print("file_path", file_path)
            if((file_path.endswith('\\') is not True) and file_path.find('\\') > 0):
                file_path = file_path + '\\'
            if((file_path.endswith('/') is not True) and file_path.find('/') > 0):
                file_path = file_path + '/'
            filename = file_path + os.path.split(src_path)[1]
        else:
            filename = src_path
        filename = filename.replace(".bin", ".dfu")
        return filename

    def get_head_info(self, md5_val, file_size, version, type):
        hrad_info = []
        file_size = file_size.to_bytes(4, byteorder='big', signed=False)
        # print(file_size)
        version = version.split(".")
        version = list(map(int, version))
        version = bytes(version)
        if(type == "factory"):
            type = bytes([0])
        elif(type == "engineer"):
            type = bytes([1])
        elif(type == "user"):
            type = bytes([2])
        else:
            type = bytes([255])
        # print(type, 16 - len(file_size + version) - 1)
        null_bytes = bytes(16 - len(file_size + version) - 1)
        # print(null_bytes)

        # 读取RSA钥匙
        if(self.privkey or self.privkey):
            self.read_key()

        # 用RSA2048签名MD5(私钥签名)
        crypto = self.privkey_sign(md5_val)
        if(len(crypto) < 1):
            print("私钥签名失败")
        hrad_info = crypto + file_size + version + type + null_bytes
        return hrad_info

    # md5采用加盐方式签名
    def md5_opt(self, data, salt):
        obj = hashlib.md5(salt.encode('utf-8'))
        obj.update(data)
        print("MD5:", obj.digest().hex())
        return obj.digest()

    # md5常规签名
    def md5_opt1(self, data):
        data_sha = hashlib.md5(data).digest()
        print("MD5:", data_sha.hex())
        return data_sha

    # 创建一个新RSA钥匙
    def create_key(self):
        start = datetime.now()
        try:
            try:
                # 备份当前秘钥
                if os.path.exists(self.pubkey_path) == True:
                    os.rename(self.pubkey_path, self.pubkey_path + '.' +
                              str(int(time.time())) + ".bak")

                if os.path.exists(self.privkey_path) == True:
                    os.rename(self.privkey_path, self.privkey_path + '.' +
                              str(int(time.time())) + ".bak")

                if os.path.exists(self.keys_path) == True:
                    os.rename(self.keys_path, self.keys_path + '.' +
                              str(int(time.time())) + ".bak")
            except Exception:
                print("备份秘钥失败!")
                print(self.pubkey_path)
                print(self.privkey_path)
                print(self.keys_path)
            try:
                # 生成密钥
                (self.pubkey, self.privkey) = rsa.newkeys(2048)
            except Exception:
                print("生成秘钥失败!")

            # 保存密钥
            with open(self.pubkey_path, 'wb') as f:
                f.write(self.pubkey.save_pkcs1())
                f.close()

            with open(self.privkey_path, 'wb') as f:
                f.write(self.privkey.save_pkcs1())
                f.close()
            try:
                self.generateh_h_file()
            except Exception:
                print("生成H文件秘钥失败!")

        except Exception:
            print("秘钥创建失败!")
        print("创建秘钥用时:" + str((datetime.now() - start)))

    # 读取RSA钥匙
    def read_key(self):
        try:
            with open(self.pubkey_path, 'rb') as f:
                self.pubkey = rsa.PublicKey.load_pkcs1(f.read())
                f.close()
        except Exception:
            print("公钥秘钥读取错误,可能不存在。")
        try:
            with open(self.privkey_path, 'rb') as f:
                self.privkey = rsa.PrivateKey.load_pkcs1(f.read())
                f.close()
        except Exception:
            print("私钥秘钥读取错误,可能不存在。")

    # 查看 RSA钥匙
    def show_key(self):
        try:
            # 读取RSA钥匙
            if(self.privkey or self.privkey):
                self.read_key()
            print("公钥:", self.pubkey.hex())
            print("私钥:", self.privkey.hex())
        except Exception:
            print("秘钥读取错误,可能不存在。")

    # 生成秘钥H文件
    def generateh_h_file(self):
        out_s = "#ifndef __KEY_RAS_H__\n"
        out_s = out_s + "#define __KEY_RAS_H__\r\n"
        # n --> modulus rsa.
        out_buff = self.hex_output(rsa.transform.int2bytes(self.privkey.n))
        out_s = out_s + self.buff_output(out_buff, "key_m")
        out_s = out_s + "\r\n"
        # e --> public Exponent
        out_buff = self.hex_output(rsa.transform.int2bytes(self.privkey.e))
        out_s = out_s + self.buff_output(out_buff, "key_e")

        out_s = out_s + "\r\n"
        # d --> private Exponent
        out_buff = self.hex_output(rsa.transform.int2bytes(self.privkey.d))
        out_s = out_s + self.buff_output(out_buff, "key_ex")

        out_s = out_s + "\r\n"
        # p --> prime1
        out_buff = self.hex_output(rsa.transform.int2bytes(self.privkey.p))
        out_s = out_s + self.buff_output(out_buff, "key_p1")

        out_s = out_s + "\r\n"
        # q --> prime2
        out_buff = self.hex_output(rsa.transform.int2bytes(self.privkey.q))
        out_s = out_s + self.buff_output(out_buff, "key_p2")

        out_s = out_s + "\r\n"
        # exp1 --> exponent1
        out_buff = self.hex_output(rsa.transform.int2bytes(self.privkey.exp1))
        out_s = out_s + self.buff_output(out_buff, "key_e1")

        out_s = out_s + "\r\n"
        # exp2 --> exponent2
        out_buff = self.hex_output(rsa.transform.int2bytes(self.privkey.exp2))
        out_s = out_s + self.buff_output(out_buff, "key_e2")

        out_s = out_s + "\r\n"
        # coef --> coefficient
        out_buff = self.hex_output(rsa.transform.int2bytes(self.privkey.coef))
        out_s = out_s + self.buff_output(out_buff, "key_c")

        out_s = out_s + "\r\n#endif\n"
        with open(self.keys_path, 'w') as f:
            f.write(out_s)
            f.close()

    # RSA使用私钥签名
    def privkey_sign(self, data):
        keylength = rsa.common.byte_size(self.privkey.n)
        padded = rsa.pkcs1._pad_for_signing(data, keylength)
        payload = rsa.transform.bytes2int(padded)
        encrypted = self.privkey.blinded_encrypt(payload)
        block = rsa.transform.int2bytes(encrypted, keylength)
        return block

    # RSA使用公钥解签
    def pubkey_decrypt(self, data):
        keylength = rsa.common.byte_size(self.pubkey.n)
        encrypted = rsa.transform.bytes2int(data)
        decrypted = rsa.core.decrypt_int(
                    encrypted, self.pubkey.e, self.pubkey.n)
        text = rsa.transform.int2bytes(decrypted, keylength)
        try:
            if len(text) > 0:
                if(text[0] == 0 and text[1] == 1):
                    text = text[2:]
                    for i in range(0, len(text)):
                        if(text[i] != 255):
                            return text[i+1:]
            return 0
        except Exception:
            print("公钥解签失败!")

    # RSA使用公钥签名
    def pubkey_sign(self, data):
        crypto = rsa.encrypt(data, self.pubkey)
        return crypto

    # RSA使用私钥钥解签
    def privkey_decrypt(self, data):
        message = rsa.decrypt(data, self.privkey)
        return message

  • 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
  • 162
  • 163
  • 164
  • 165
  • 166
  • 167
  • 168
  • 169
  • 170
  • 171
  • 172
  • 173
  • 174
  • 175
  • 176
  • 177
  • 178
  • 179
  • 180
  • 181
  • 182
  • 183
  • 184
  • 185
  • 186
  • 187
  • 188
  • 189
  • 190
  • 191
  • 192
  • 193
  • 194
  • 195
  • 196
  • 197
  • 198
  • 199
  • 200
  • 201
  • 202
  • 203
  • 204
  • 205
  • 206
  • 207
  • 208
  • 209
  • 210
  • 211
  • 212
  • 213
  • 214
  • 215
  • 216
  • 217
  • 218
  • 219
  • 220
  • 221
  • 222
  • 223
  • 224
  • 225
  • 226
  • 227
  • 228
  • 229
  • 230
  • 231
  • 232
  • 233
  • 234
  • 235
  • 236
  • 237
  • 238
  • 239
  • 240
  • 241
  • 242
  • 243
  • 244
  • 245
  • 246
  • 247
  • 248
  • 249
  • 250
  • 251
  • 252
  • 253
  • 254
  • 255
  • 256
  • 257
  • 258
  • 259
  • 260
  • 261
  • 262
  • 263
  • 264
  • 265
  • 266
  • 267
  • 268
  • 269
  • 270
  • 271
  • 272
  • 273
  • 274
  • 275
  • 276
  • 277
  • 278
  • 279
  • 280
  • 281
  • 282
  • 283
  • 284
  • 285
  • 286
  • 287
  • 288
  • 289
  • 290
  • 291
  • 292
  • 293
  • 294
  • 295
  • 296

主程序:

import getopt
import os
import sys

from lib.mysign import my_sign


def show_help():
    print("-h                       查看帮助")
    print("-s <path>                bin文件路径         例: E:\\123.bin")
    print("-o <path>                dfu文件输出路径     例: D:\\")
    print("-v <version num>         版本号              例: 0.0.1.0")
    print("-t <type>                类型                例: factory或user或engineer")
    print("-k                       查看秘钥            例: ")
    print("-c                       创建秘钥            例: ")
    print("完整例子: xxx.exe -s E:\\123.bin -o D:\\ -v 0.0.1.0 -t factory")


if __name__ == "__main__":
    # print(sys.argv)
    py_path = os.path.dirname(sys.argv[0])

    mysign = my_sign(py_path)

    sour_path = None
    out_path = None
    pack_version = None
    pack_type = None

    try:
        opts, args = getopt.getopt(sys.argv[1:], '-h-s:-o:-v:-t:-k-c',
                                   ['help', 'source=', 'out=', 'version=', 'type=', 'key', 'newkey'])
    except Exception:
        print("参数错误!")
        sys.exit()

    for opt_name, opt_value in opts:
        if opt_name in ('-h', '--help'):
            show_help()
            sys.exit()
        elif(opt_name in ('-c', '--newkey')):
            mysign.create_key()
        elif(opt_name in ('-s', '--source')):
            sour_path = opt_value
        elif(opt_name in ('-o', '--out')):
            out_path = opt_value
        elif(opt_name in ('-v', '--version')):
            pack_version = opt_value
        elif(opt_name in ('-t', '--type')):
            pack_type = opt_value
        elif(opt_name in ('-k', '--key')):
            mysign.show_key()
            sys.exit()

    # print(sour_path)
    if sour_path is not None:
        data = mysign.get_data(sour_path)
    else:
        sys.exit()
    # print("sour_path:", sour_path)

    if len(data) != 0:
        size = os.path.getsize(sour_path)
        md5_val = mysign.md5_opt1(data)
        # 得到输出路径
        out_path = mysign.get_out_path(sour_path, out_path)
        print("out path:", out_path)
        # 得到头信息
        head_info = mysign.get_head_info(
            md5_val, size, pack_version, pack_type)
        # 写出dfu文件
        with open(out_path, 'wb') as f:
            f.write(head_info + data)
            f.close()

    else:
        print("err: Invalid parameter")

  • 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
声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/AllinToyou/article/detail/308253
推荐阅读
相关标签
  

闽ICP备14008679号