1.1 Ucryptolib 模块API手册#

前言#

概述#

本文档主要介绍 CanMV 项目中加解密算法库-ucryptolib。

读者对象#

本文档(本指南)主要适用于以下人员:

  • 技术支持工程师

  • 软件开发工程师

缩略词定义#

简称

说明

AES

Advanced Encryption Standard

GCM

Galois/Counter Mode

修订记录#

文档版本号

修改说明

修改者

日期

V1.0

初版

杨帆

2023-09-15

V1.1

修改示例程序,新增使用指南

杨帆

2023-10-10

V1.2

增加 AES-ECB/CBC/CTR 软件源生实现

杨帆

2023-10-13

1. 概述#

Ucryptolib 库提供了 AES-ECB/CBC/CTR、AES-GCM、SM4 加解密功能。其中,AES-ECB/CBC/CTR 三种模式是由 micropython 的软件源生实现,AES-GCM 和 SM4 由底层硬件加速器进行加速。

注意:本文档不会介绍 AES-ECB/CBC/CTR 三种模式的加解密详细步骤,具体请参考 micropython cryptolib官方文档

2. API描述#

Ucryptolib 库提供了两个类,分别是 aes 和 sm4,它们分别实现了两个函数,加密 encrypt() 和解密 decrypt()。

2.1 类 aes#

【描述】

类 aes 用于初始化一个 AES-GCM 国际加解密对象,从而完成加密/解密操作。同时,在 AES-GCM 加解密算法中,初始化时必须输入 key、mode、IV 和 AAD。

注意:初始化后,加解密对象只能用于加密或解密操作,不允许创建一个密码对象同时用于加密、解密操作

【语法】

ucryptolib.aes((key, mode, IV, AAD))

【参数】

参数名称

描述

输入/输出

key

加解密密钥,支持的密钥长度为 256 bits

输入

mode

加解密模式,支持的加解密模式为 AES-GCM,这里设置 mode=0 即可

输入

IV

初始化向量,支持的 IV 长度为 12 bytes

输入

AAD

附加数据

输入

【返回值】

返回值

描述

0

成功

非 0

失败

【注意】

【举例】

/**********encrypt************/
key = b'\x24\x50\x1a\xd3\x84\xe4\x73\x96\x3d\x47\x6e\xdc\xfe\x08\x20\x52\x37\xac\xfd\x49\xb5\xb8\xf3\x38\x57\xf8\x11\x4e\x86\x3f\xec\x7f'
iv = b'\x9f\xf1\x85\x63\xb9\x78\xec\x28\x1b\x3f\x27\x94'
aad = b'\xad\xb5\xec\x72\x0c\xcf\x98\x98\x50\x00\x28\xbf\x34\xaf\xcc\xbc\xac\xa1\x26\xef'
pt = b'\x27'

crypto = ucryptolib.aes(key, 0, iv, aad)
inbuf = pt
outbuf = bytearray(17)
crypto.encrypt(inbuf, outbuf)

/**********decrypt************/
ct = b'\xeb'
tag = b'\x63\x35\xe1\xd4\x9e\x89\x88\xea\xc4\x8e\x42\x19\x4e\x5f\x56\xdb'
crypto = ucryptolib.aes(key, 0, iv, aad)
inbuf = ct + tag
outbuf = bytearray(1)
crypto.decrypt(inbuf, outbuf)

【相关主题】

2.1.1 加密函数 encrypt()#

【描述】

对输入数据进行加密运算。输入数据存放在 inbuf 中,加密结果将存储到输出缓冲区 outbuf 中,如果:

  1. 没有给定 outbuf,加密函数 encrypt() 将返回一个 bytes 类型的对象;

  2. 如果给定 outbuf 且 outbuf = inbuf,数据将被就地加密。

【语法】

crypto.encrypt(inbuf[, outbuf])

【参数】

参数名称

描述

输入/输出

inbuf

输入缓冲区,存放待加密的明文数据

输入

outbuf(可选)

输出缓冲区,存放加密完成的密文数据

输入

【返回值】

返回值

描述

0

成功

非 0

失败

【注意】

加密后返回的数据(密文数据)格式为:密文 + TAG,TAG 长度固定为 16 bytes。

【举例】

【相关主题】

2.1.2 解密函数 decrypt()#

【描述】

对输入数据进行解密运算。输入数据存放在 inbuf 中,解密结果将存储到输出缓冲区 outbuf 中,如果:

  1. 没有给定 outbuf,解密函数 decrypt() 将返回一个 bytes 类型的对象;

  2. 如果给定 outbuf 且 outbuf = inbuf,数据将被就地解密。

【语法】

crypto.decrypt(inbuf[, outbuf])

【参数】

参数名称

描述

输入/输出

inbuf

输入缓冲区,存放待解密的密文数据

输入

outbuf(可选)

输出缓冲区,存放解密完成的明文数据

输入

【返回值】

返回值

描述

0

成功

非 0

失败

【注意】

解密后返回的数据(明文数据)格式为:明文。

【举例】

【相关主题】

2.2 类 sm4#

【描述】

类 sm4 用于初始化一个国密加解密对象,从而完成加密/解密操作。

注意:初始化后,加解密对象只能用于加密或解密操作,不允许创建一个密码对象同时用于加密、解密操作

【语法】

ucryptolib.sm4((key, mode[, IV]))

【参数】

参数名称

描述

输入/输出

key

加解密密钥,支持的密钥长度为 128 bits

输入

mode

加解密模式,支持的模式有 ecb/cbc/cfb/ofb/ctr,mode 分别为 1/2/3/5/6

输入

IV(可选)

初始化向量,支持的 IV 长度为 20 bytes

输入

【返回值】

返回值

描述

0

成功

非 0

失败

【注意】

【举例】

/**********encrypt************/
key = b'\x01\x23\x45\x67\x89\xab\xcd\xef\xfe\xdc\xba\x98\x76\x54\x32\x10'
iv = b'\x00\x01\x02\x03\x04\x05\x06\x07\x08\x09\x0a\x0b\x0c\x0d\x0e\x0f'
pt = b'\xaa\xaa\xaa\xaa\xbb\xbb\xbb\xbb\xcc\xcc\xcc\xcc\xdd\xdd\xdd\xdd\xee\xee\xee\xee\xff\xff\xff\xff\xaa\xaa\xaa\xaa\xbb\xbb\xbb\xbb'
crypto = ucryptolib.sm4(key, 2, iv)
inbuf = pt
outbuf = bytearray(32)
crypto.encrypt(inbuf, outbuf)

/**********decrypt************/
ct = b'\x78\xeb\xb1\x1c\xc4\x0b\x0a\x48\x31\x2a\xae\xb2\x04\x02\x44\xcb\x4c\xb7\x01\x69\x51\x90\x92\x26\x97\x9b\x0d\x15\xdc\x6a\x8f\x6d'
crypto = ucryptolib.sm4(key, 2, iv)
inbuf = ct
outbuf = bytearray(32)
crypto.decrypt(inbuf, outbuf)

【相关主题】

2.2.1 加密函数 encrypt()#

【描述】

对输入数据进行加密运算。输入数据存放在 inbuf 中,加密结果将存储到输出缓冲区 outbuf 中,如果:

  1. 没有给定 outbuf,加密函数 encrypt() 将返回一个 bytes 类型的对象;

  2. 如果给定 outbuf 且 outbuf = inbuf,数据将被就地加密。

【语法】

crypto.encrypt(inbuf[, outbuf])

【参数】

参数名称

描述

输入/输出

inbuf

输入缓冲区,存放待加密的明文数据

输入

outbuf(可选)

输出缓冲区,存放加密完成的密文数据

输入

【返回值】

返回值

描述

0

成功

非 0

失败

【注意】

【举例】

【相关主题】

2.2.2 解密函数 decrypt()#

【描述】

对输入数据进行解密运算。输入数据存放在 inbuf 中,解密结果将存储到输出缓冲区 outbuf 中,如果:

  1. 没有给定 outbuf,解密函数 decrypt() 将返回一个 bytes 类型的对象;

  2. 如果给定 outbuf 且 outbuf = inbuf,数据将被就地解密。

【语法】

crypto.decrypt(inbuf[, outbuf])

【参数】

参数名称

描述

输入/输出

inbuf

输入缓冲区,存放待解密的密文数据

输入

outbuf(可选)

输出缓冲区,存放解密完成的明文数据

输入

【返回值】

返回值

描述

0

成功

非 0

失败

【注意】

【举例】

【相关主题】

3. 示例程序#

3.1 aes 加解密#

/********** AES-GCM encrypt ************/
import ucryptolib

# key(256 bytes)
key = b'\x24\x50\x1a\xd3\x84\xe4\x73\x96\x3d\x47\x6e\xdc\xfe\x08\x20\x52\x37\xac\xfd\x49\xb5\xb8\xf3\x38\x57\xf8\x11\x4e\x86\x3f\xec\x7f'
# iv(12 bytes)
iv = b'\x9f\xf1\x85\x63\xb9\x78\xec\x28\x1b\x3f\x27\x94'
# aad(20 bytes)
aad = b'\xad\xb5\xec\x72\x0c\xcf\x98\x98\x50\x00\x28\xbf\x34\xaf\xcc\xbc\xac\xa1\x26\xef'
# plaintext(51 bytes)
pt = b'\x27\xf3\x48\xf9\xcd\xc0\xc5\xbd\x5e\x66\xb1\xcc\xb6\x3a\xd9\x20\xff\x22\x19\xd1\x4e\x8d\x63\x1b\x38\x72\x26\x5c\xf1\x17\xee\x86\x75\x7a\xcc\xb1\x58\xbd\x9a\xbb\x38\x68\xfd\xc0\xd0\xb0\x74\xb5\xf0\x1b\x2c'
ct = b'\xeb\x7c\xb7\x54\xc8\x24\xe8\xd9\x6f\x7c\x6d\x9b\x76\xc7\xd2\x6f\xb8\x74\xff\xbf\x1d\x65\xc6\xf6\x4a\x69\x8d\x83\x9b\x0b\x06\x14\x5d\xae\x82\x05\x7a\xd5\x59\x94\xcf\x59\xad\x7f\x67\xc0\xfa\x5e\x85\xfa\xb8'
tag = b'\xbc\x95\xc5\x32\xfe\xcc\x59\x4c\x36\xd1\x55\x02\x86\xa7\xa3\xf0'
# init cipher object(aes-gcm)
crypto = ucryptolib.aes(key, 0, iv, aad)
inbuf = pt
# outbuf = ciphertext + tag
outbuf = bytearray(67)
crypto.encrypt(inbuf, outbuf).hex(' ')

/********** AES-GCM decrypt ************/
crypto = ucryptolib.aes(key, 0, iv, aad)
# ciphertext + tag
inbuf = ct + tag
outbuf = bytearray(51)
crypto.decrypt(inbuf, outbuf).hex(' ')

3.2 sm4 加解密#

import ucryptolib

/********** SM4-ECB encrypt ************/
# key(128 bits)
key = b'\x01\x23\x45\x67\x89\xab\xcd\xef\xfe\xdc\xba\x98\x76\x54\x32\x10'
iv = b'\x00\x01\x02\x03\x04\x05\x06\x07\x08\x09\x0a\x0b\x0c\x0d\x0e\x0f'
# plaintext(32 bytes)
pt = b'\xaa\xaa\xaa\xaa\xbb\xbb\xbb\xbb\xcc\xcc\xcc\xcc\xdd\xdd\xdd\xdd\xee\xee\xee\xee\xff\xff\xff\xff\xaa\xaa\xaa\xaa\xbb\xbb\xbb\xbb'
ct = b'\x5e\xc8\x14\x3d\xe5\x09\xcf\xf7\xb5\x17\x9f\x8f\x47\x4b\x86\x19\x2f\x1d\x30\x5a\x7f\xb1\x7d\xf9\x85\xf8\x1c\x84\x82\x19\x23\x04'
# init cipher object(sm4-ebc)
crypto = ucryptolib.sm4(key, 1)
inbuf = pt
outbuf = bytearray(32)
crypto.encrypt(inbuf, outbuf).hex(' ')

/********** SM4-EBC decrypt ************/
# init cipher object(aes-ebc)
crypto = ucryptolib.sm4(key, 1)
inbuf = ct
outbuf = bytearray(32)
crypto.decrypt(inbuf, outbuf).hex(' ')

4. 使用指南#

截止到当前版本,ucryptolib 库已经测试了下列 case。测试程序参考 ./tests/cipher/cipher.py,启动 canmv 开发板,进入 REPL 之后,通过命令 import sdcard.app.tests.cipher.cipher 可直接运行测试 demo。

方法

测试 case

测试结果

aes-gcm

encrypt / decrypt

ivlen=12, ptlen=0, aadlen=0

pass

ivlen=12, ptlen=1, aadlen=20

pass

ivlen=12, ptlen=51, aadlen=0

pass

ivlen=12, ptlen=51, aadlen=20

pass

sm4-ecb

encrypt / decrypt

keybits=128, ptlen=32

pass

sm4-cbc

encrypt / decrypt

keybits=128, ivlen=16, ptlen=32

pass

sm4-cfb

encrypt / decrypt

keybits=128, ivlen=16, ptlen=32

pass

sm4-ofb

encrypt / decrypt

keybits=128, ivlen=16, ptlen=32

pass

sm4-ctr

encrypt / decrypt

keybits=128, ivlen=16, ptlen=64

pass