keys 包
介绍
keys
包提供非对称加密算法
使用本包需要外部依赖 OpenSSL 3
的 crypto
动态库文件,故使用前需安装相关工具:
- 对于
Linux
操作系统,可参考以下方式:- 如果系统的包管理工具支持安装
OpenSSL 3
开发工具包,可通过这个方式安装,并确保系统安装目录下含有libcrypto.so
和libcrypto.so.3
这两个动态库文件,例如Ubuntu 22.04
系统上可使用sudo apt install libssl-dev
命令安装libssl-dev
工具包; - 如果无法通过上面的方式安装,可自行下载
OpenSSL 3.x.x
源码编译安装软件包,并确保安装目录下含有libcrypto.so
和libcrypto.so.3
这两个动态库文件,然后可选择下面任意一种方式来保证系统链接器可以找到这些文件:- 在系统未安装 OpenSSL 的场景,安装时选择直接安装到系统路径下;
- 安装在自定义目录的场景,将这些文件所在目录设置到环境变量
LD_LIBRARY_PATH
以及LIBRARY_PATH
中。
- 如果系统的包管理工具支持安装
- 对于
Windows
操作系统,可按照以下步骤:- 自行下载
OpenSSL 3.x.x
源码编译安装 x64 架构软件包或者自行下载安装第三方预编译的供开发人员使用的OpenSSL 3.x.x
软件包; - 确保安装目录下含有
libcrypto.dll.a
(或libcrypto.lib
)、libcrypto-3-x64.dll
这两个库文件; - 将
libcrypto.dll.a
(或libcrypto.lib
) 所在的目录路径设置到环境变量LIBRARY_PATH
中,将libcrypto-3-x64.dll
所在的目录路径设置到环境变量PATH
中。
- 自行下载
- 对于
macOS
操作系统,可参考以下方式:- 使用
brew install openssl@3
安装,并确保系统安装目录下含有libcrypto.dylib
和libcrypto.3.dylib
这两个动态库文件; - 如果无法通过上面的方式安装,可自行下载
OpenSSL 3.x.x
源码编译安装软件包,并确保安装目录下含有libcrypto.dylib
和libcrypto.3.dylib
这两个动态库文件,然后可选择下面任意一种方式来保证系统链接器可以找到这些文件:- 在系统未安装 OpenSSL 的场景,安装时选择直接安装到系统路径下;
- 安装在自定义目录的场景,将这些文件所在目录设置到环境变量
DYLD_LIBRARY_PATH
以及LIBRARY_PATH
中。
- 使用
如果未安装OpenSSL 3
软件包或者安装低版本的软件包,程序可能无法使用并抛出相关异常 CryptoException: Can not load openssl library or function xxx.
。
主要接口
class RSAPrivateKey
public class RSAPrivateKey <: PrivateKey{
public init(bits: Int32)
public init(bits: Int32, e: BigInt)
}
RSA 私钥类,提供生成 RSA 私钥能力,RSA 私钥支持签名和解密操作,支持 PEM 和 DER 格式的编码解码,符合 PKCS1 标准,详见 rfc8017。
init
public init(bits: Int32)
功能:init 初始化生成私钥, 公共指数默认值为 65537,业界推荐。
参数:
- bits:密钥长度,需要大于等于 512 位,并且小于等于 16384 位
异常:
- CryptoException - 密钥长度不符合要求或初始化失败,抛出异常
init
public init(bits: Int32, e: BigInt)
功能:init 初始化生成私钥,允许用户指定公共指数。
参数:
- bits:密钥长度,需要大于等于 512 位,并且小于等于 16384 位,推荐使用的密钥长度不小于 3072 位
- e:公钥公共指数,范围是 [3, 2^256-1] 的奇数
异常:
- CryptoException - 密钥长度不符合要求、公钥公共指数值不符合要求或初始化失败,抛出异常
func sign
public func sign(hash: Digest, digest: Array<Byte>, padType!: PadOption): Array<Byte>
功能:sign 对数据的摘要结果进行签名。
参数:
- hash:摘要方法,获取 digest 结果使用的摘要方法
- digest:数据的摘要结果
- padType:填充模式,可以选择 PKCS1 或 PSS 模式,不支持 OAEP 模式,在对安全场景要求较高的情况下,推荐使用 PSS 填充模式
返回值:签名后的数据
异常:
- CryptoException:设置摘要方法失败、设置填充模式失败或签名失败,抛出异常
func decrypt
public func decrypt(input: InputStream, output: OutputStream, padType!: PadOption): Unit
功能:decrypt 解密出原始数据。
参数:
- input:加密的数据
- digest:解密后的数据
- padType:填充模式,可以选择 PKCS1 或 OAEP 模式,不支持 PSS 模式,在对安全场景要求较高的情况下,推荐使用 OAEP 填充模式
异常:
- CryptoException - 设置填充模式失败或解密失败,抛出异常
func encodeToDer
public override func encodeToDer(): DerBlob
功能:将私钥编码为 DER 格式。
返回值:Derblob 对象
异常:
- CryptoException:编码失败,抛出异常
func encodeToDer
public func encodeToDer(password!: ?String): DerBlob
功能:使用 AES-256-CBC 加密私钥,将私钥编码为 DER 格式。
参数:
- password:加密私钥需要提供的密码,密码为 None 时则不加密
返回值:Derblob 对象
异常:
- CryptoException:编码失败、加密失败或者参数密码为空字符串,抛出异常
func encodeToPem
public override func encodeToPem(): PemEntry
功能:将私钥编码为 PEM 格式。
返回值:PemEntry
对象
异常:
- CryptoException:编码失败,抛出异常
func decodeDer
public static func decodeDer(blob: DerBlob): RSAPrivateKey
功能:将私钥从 DER 格式解码。
参数:
- password:二进制格式的私钥对象
返回值:解码出的 RSA 私钥
异常:
- CryptoException:解码失败,抛出异常
func decodeDer
public static func decodeDer(blob: DerBlob, password!: ?String): RSAPrivateKey
功能:将加密的私钥从 DER 格式解码。
参数:
- blob:二进制格式的私钥对象
- password:解密私钥需要提供的密码,密码为 None 时则不解密
返回值:解码出的 RSA 私钥
异常:
- CryptoException:解码失败、解密失败或者参数密码为空字符串,抛出异常
func decodeFromPem
public static func decodeFromPem(text: String): RSAPrivateKey
功能:将私钥从 PEM 格式解码。
参数:
- text:PEM 格式的私钥字符流
返回值:解码出的 RSA 私钥
异常:
- CryptoException:解码失败、解密失败、字符流不符合 PEM 格式或文件头不符合私钥头标准时,抛出异常
func decodeFromPem
public static func decodeFromPem(text: String, password!: ?String): RSAPrivateKey
功能:将私钥从 PEM 格式解码。
参数:
- text:PEM 格式的私钥字符流
- password:解密私钥需要提供的密码,密码为 None 时则不解密
返回值:解码出的 RSA 私钥
异常:
- CryptoException:解码失败、解密失败、参数密码为空字符串、字符流不符合 PEM 格式或文件头不符合私钥头标准时,抛出异常
func toString
public override func toString(): String
功能:输出私钥种类。
class RSAPublicKey
public class RSAPublicKey <: PublicKey {
public init(pri: RSAPrivateKey)
}
RSA 公钥类,提供生成 RSA 公钥能力,RSA 公钥支持验证签名和加密操作,支持 PEM 和 DER 格式的编码解码。
init
public init(pri: RSAPrivateKey)
功能:init 初始化公钥,从私钥中获取对应的公钥。
参数:
- pri:RSA私钥
异常:
- CryptoException:初始化失败,抛出异常
func verify
public func verify(hash: Digest, digest: Array<Byte>, sig: Array<Byte>, padType!: PadOption): Bool
功能:verify 验证签名结果。
参数:
- hash:摘要方法,获取 digest 结果使用的摘要方法
- digest:数据的摘要结果
- sig:数据的签名结果
- padType:填充模式,可以选择 PKCS1 或 PSS 模式,不支持 OAEP 模式,在对安全场景要求较高的情况下,推荐使用 PSS 填充模式
返回值:返回 true 表示验证成功,false 失败
异常:
- CryptoException:设置填充模式失败或验证失败,抛出异常
func encrypt
public func encrypt(input: InputStream, output: OutputStream, padType!: PadOption): Unit
功能:encrypt 给一段数据进行加密。
参数:
- input:需要加密的数据
- output:加密后的数据
- padType:填充模式,可以选择 PKCS1 或 OAEP 模式,不支持 PSS 模式,在对安全场景要求较高的情况下,推荐使用 OAEP 填充模式
异常:
- CryptoException:设置填充模式失败或加密失败,抛出异常
func encodeToDer
public override func encodeToDer(): DerBlob
功能:将公钥编码为 DER 格式。
返回值:返回 Derblob 对象
异常:
- CryptoException:编码失败,抛出异常
func encodeToPem
public override func encodeToPem(): PemEntry
功能:将公钥编码为 PEM 格式。
返回值:返回 PemEntry 对象
异常:
- CryptoException:编码失败,抛出异常
func decodeDer
public static func decodeDer(blob: DerBlob): RSAPublicKey
功能:将公钥从 DER 格式解码。
参数:
- blob:二进制格式的公钥对象
返回值:解码出的 RSA 公钥
异常:
- CryptoException:解码失败,抛出异常
func decodeFromPem
public static func decodeFromPem(text: String): RSAPublicKey
功能:将公钥从PEM 格式解码。
参数:
- text:PEM 格式的公钥字符流
返回值:解码出的 RSA 公钥
异常:
- CryptoException:解码失败、字符流不符合 PEM 格式或文件头不符合公钥头标准时,抛出异常
func toString
public override func toString(): String
功能:输出公钥种类
enum PadOption
public enum PadOption {
| OAEP(OAEPOption) | PSS(PSSOption) | PKCS1
}
枚举类型 PadOption 用于设置 RSA 的填充模式,RSA 有三种常用的填充模式,OAEP 为最优非对称加密填充,只能用于加密解密;PSS 为概率签名方案, 只能用于签名和验证,PKCS1 是一种普通的填充模式,用于填充数据长度,可以用于加密、解密、签名和验证。RSA 的 PKCS1 填充模式是在早期的 PKCS #1 v1.5 规范中定义的填充模式,当前对使用 PKCS1 填充模式的攻击较为成熟,容易被攻击者解密或伪造签名,建议采用 PKCS #1 v2 版本中更加安全的 PSS 或 OAEP 填充模式。
OAEP
OAEP(OAEPOption)
功能:使用最优非对称加密初始化 PadOption
实例。
PSS
PSS(PSSOption)
功能:使用概率签名方案初始化 PadOption
实例。
PKCS1
PKCS1
功能:使用 PKCS #1 公钥密码学标准初始化 PadOption
实例。
struct OAEPOption
public struct OAEPOption {
public init(hash: Digest, mgfHash: Digest, label!: String = "")
}
此结构体为 OAEP
填充模式需要设置的参数。
init
public init(hash: Digest, mgfHash: Digest, label!: String = "")
功能:初始化 OAEP 填充参数。
参数:
hash
:摘要方法,用于对 label 进行摘要mgfHash
:摘要方法,用于设置 MGF1 函数中的摘要方法label
: 摘要方法,label 是可选参数,默认为空字符串,可以通过设置 lable 来区分不同的加密操作
init
public init(hash: Digest, mgfHash: Digest, label!: String = "")
功能:初始化 OAEP 填充参数。
参数:
hash
:摘要方法,用于对 label 进行摘要mgfHash
:摘要方法,用于设置 MGF1 函数中的摘要方法label
:label 是可选参数,默认为空字符串,可以通过设置 lable 来区分不同的加密操作
struct PSSOption
public struct PSSOption {
public init(saltLen: Int32)
}
此结构体为 PSS
填充模式需要设置的参数。
init
public init(saltLen: Int32)
功能:初始化 PSS 填充参数。
参数:
- saltLen:随机盐长度,长度应大于等于 0,小于等于(RSA 长度 - 摘要长度 - 2),长度单位为字节,长度过长会导致签名失败
异常:
- CryptoException:随机盐长度小于 0,抛出异常
enum Curve
public enum Curve {
| P224 | P256 | P384 | P521 | BP256 | BP320 | BP384 | BP512
}
枚举类型 Curve 用于选择生成 ECDSA 密钥时使用的椭圆曲线类型,支持 NIST P-224,NIST P-256,NIST P-384,NIST P-521,Brainpool P-256,Brainpool P-320,Brainpool P-384,Brainpool P-512 八种椭圆曲线。
P224
P224
功能:使用 NIST P-224 椭圆曲线初始化 Curve
实例。
P256
P256
功能:使用 NIST P-256 椭圆曲线初始化 Curve
实例。
P384
P384
功能:使用 NIST P-384 椭圆曲线初始化 Curve
实例。
P521
P521
功能:使用 NIST P-521 椭圆曲线初始化 Curve
实例。
BP256
BP256
功能:使用 Brainpool P-256 椭圆曲线初始化 Curve
实例。
BP320
BP320
功能:使用 Brainpool P-320 椭圆曲线初始化 Curve
实例。
BP384
BP384
功能:使用 Brainpool P-384 椭圆曲线初始化 Curve
实例。
BP512
BP512
功能:使用 Brainpool P-512 椭圆曲线初始化 Curve
实例。
class ECDSAPrivateKey
public class ECDSAPrivateKey <: PrivateKey {
public init(curve: Curve)
}
ECDSA 私钥类,提供生成 ECDSA 私钥能力,ECDSA 的私钥支持签名操作,同时支持 PEM 和 DER 格式的编码解码,详见 FIPS 186-4。
init
public init(curve: Curve)
功能:init 初始化生成私钥。
参数:
- curve:椭圆曲线类型
异常:
- CryptoException:初始化失败,抛出异常
func sign
public func sign(digest: Array<Byte>): Array<Byte>
功能:sign 对数据的摘要结果进行签名。
参数:
- digest:数据的摘要结果
返回值:签名后的数据
异常:
- CryptoException:签名失败,抛出异常
func encodeToDer
public override func encodeToDer(): DerBlob
功能:将私钥编码为 DER 格式。
返回值:返回 Derblob 对象
异常:
- CryptoException:编码失败,抛出异常
func encodeToDer
public func encodeToDer(password!: ?String): DerBlob
功能:使用 AES-256-CBC 加密私钥,将私钥编码为 DER 格式。
参数:
- password:加密私钥需要提供的密码,密码为 None 时则不加密
返回值:Derblob 对象
异常:
- CryptoException:编码失败、加密失败或者参数密码为空字符串,抛出异常
func encodeToPem
public override func encodeToPem(): PemEntry
功能:将私钥编码为 PEM 格式。
返回值:PemEntry
对象
异常:
- CryptoException:编码失败,抛出异常
func decodeDer
public static func decodeDer(blob: DerBlob): ECDSAPrivateKey
功能:将私钥从 DER 格式解码。
参数:
- blob:二进制格式的私钥对象
返回值:解码出的 ECDSA 私钥
异常:
- CryptoException:解码失败,抛出异常
func decodeDer
public static func decodeDer(blob: DerBlob, password!: ?String): ECDSAPrivateKey
功能:将加密的私钥从 DER 格式解码。
参数:
- blob:二进制格式的私钥对象
- password:解密私钥需要提供的密码,密码为 None 时则不解密
返回值:解码出的 ECDSA 私钥
异常:
- CryptoException:解码失败、解密失败或者参数密码为空字符串,抛出异常
func decodeFromPem
public static func decodeFromPem(text: String): ECDSAPrivateKey
功能:将私钥从 PEM 格式解码。
参数:
- text:PEM 格式的私钥字符流
返回值:解码出的 ECDSA 私钥
异常:
- CryptoException:解码失败、字符流不符合 PEM 格式或文件头不符合私钥头标准时,抛出异常
func decodeFromPem
public static func decodeFromPem(text: String, password!: ?String): ECDSAPrivateKey
功能:将私钥从PEM 格式解码。
参数:
- text:PEM 格式的私钥字符流
- password:解密私钥需要提供的密码,密码为 None 时则不解密
返回值:解码出的 ECDSA 私钥
异常:
- CryptoException:解码失败、解密失败、参数密码为空字符串、字符流不符合 PEM 格式或文件头不符合私钥头标准时,抛出异常
func toString
public override func toString(): String
功能:输出私钥种类。
class ECDSAPublicKey
public class ECDSAPublicKey <: PublicKey {
public init(pri: ECDSAPrivateKey)
}
ECDSA 公钥类,提供生成 ECDSA 公钥能力,ECDSA 公钥支持验证签名操作,支持 PEM 和 DER 格式的编码解码。
init
public init(pri: ECDSAPrivateKey)
功能:init 初始化公钥,从私钥中获取对应的公钥。
参数:
- pri:ECDSA 私钥
异常:
- CryptoException:初始化失败,抛出异常
func verify
public func verify(digest: Array<Byte>, sig: Array<Byte>): Bool
功能:verify 验证签名结果。
参数:
- digest:数据的摘要结果
- sig:数据的签名结果
返回值:返回 true 表示验证成功,false 失败
func encodeToDer
public override func encodeToDer(): DerBlob
功能:将公钥编码为 DER 格式。
返回值:返回 Derblob 对象
异常:
- CryptoException:编码失败,抛出异常
func encodeToPem
public override func encodeToPem(): PemEntry
功能:将公钥编码为 PEM 格式。
返回值:PemEntry 对象
异常:
- CryptoException:编码失败,抛出异常
func decodeDer
public static func decodeDer(blob: DerBlob): ECDSAPublicKey
功能:将公钥从 DER 格式解码。
参数:
- blob:二进制格式的公钥对象
返回值:解码出的 ECDSA 公钥
异常:
- CryptoException:编码失败,抛出异常
func decodeFromPem
public static func decodeFromPem(text: String): ECDSAPublicKey
功能:将公钥从 PEM 格式解码。
参数:
- text:PEM 格式的公钥字符流
返回值:解码出的 ECDSA 公钥
异常:
- CryptoException:解码失败、字符流不符合 PEM 格式或文件头不符合公钥头标准时,抛出异常
func toString
public override func toString(): String
功能:输出公钥种类。
示例
RSA 密钥示例
使用 RSA 密钥使用示例。
生成 rsa 公钥及私钥,并使用公钥的 OAEP 填充模式加密,用私钥的 OAEP 填充模式解密。
from crypto import keys.*
from crypto import digest.*
from std import io.*
from std import crypto.digest.*
main() {
var rsaPri = RSAPrivateKey(2048)
var rsaPub = RSAPublicKey(rsaPri)
var str: String = "hello world, hello cangjie"
var bas1 = ByteArrayStream()
var bas2 = ByteArrayStream()
var bas3 = ByteArrayStream()
bas1.write(str.toArray())
var encOpt = OAEPOption(SHA1(), SHA256())
rsaPub.encrypt(bas1, bas2, padType: OAEP(encOpt))
var encOpt2 = OAEPOption(SHA1(), SHA256())
rsaPri.decrypt(bas2, bas3, padType: OAEP(encOpt2))
var buf = Array<Byte>(str.size, item:0)
bas3.read(buf)
if (str.toArray() == buf){
println("success")
} else {
println("fail")
}
}
从文件中读取 rsa 公钥和私钥,并使用私钥的 PKCS1 填充模式签名,用公钥的 PKCS1 填充模式验证签名结果。
from crypto import keys.*
from crypto import digest.*
from std import crypto.digest.*
from std import fs.*
main() {
var pemPri = String.fromUtf8(File("./files/rsaPri.pem", OpenOption.Open(true, false)).readToEnd())
var rsaPri = RSAPrivateKey.decodeFromPem(pemPri)
var pemPub = String.fromUtf8(File("./files/rsaPub.pem", OpenOption.Open(true, false)).readToEnd())
var rsaPub = RSAPublicKey.decodeFromPem(pemPub)
var str: String = "helloworld"
var sha512Instance = SHA512()
var md: Array<Byte> = digest(sha512Instance, str)
var sig = rsaPri.sign(sha512Instance, md, padType: PKCS1)
if (rsaPub.verify(sha512Instance, md, sig, padType: PKCS1)){
println("verify successful")
}
}
ECDSA 密钥示例
使用 ECDSA 密钥使用示例。
生成 ECDSA 公钥及私钥,并使用私钥签名,公钥验证签名结果。
from crypto import keys.*
from crypto import digest.*
from std import convert.*
from std import crypto.digest.*
main() {
var ecPri = ECDSAPrivateKey(P224)
var ecPub = ECDSAPublicKey(ecPri)
var str: String = "helloworld"
var sha512Instance = SHA512()
var md: Array<Byte> = digest(sha512Instance, str)
var sig = ecPri.sign(md)
println(sig)
if (ecPub.verify(md, sig)){
println("verify successful")
}
}