加密与签名
简介
加密一般是用公钥进行加密,然后使用私钥进行解密(注意一般不会反向操作)。签名一般指的是,通过私钥对数据的摘要(hash值)进行签名,摘要保证了数据的完整性,签名后的数据,可以用公钥进行验证。
一般加密使用 RSA(RSA也可以用做签名),签名可以使用 ECDSA(ECDSA不具备加密能力)。
RSA 是基于质因数分解,椭圆曲线算法是依赖于椭圆曲线离散对数问题的困难性。从安全性角度看,椭圆曲线离散对数问题比整数质因数分解更困难。RSA需要更长的密钥(2048位以上)来保证安全强度,ECDSA可以使用更短的密钥。256位的 ECDSA密钥与3072位的RSA密钥强度相当。ECDSA的实现比较复杂,需要找到合适的椭圆曲线,RSA比较简单。
区块链的曲线和算法
主要的算法有:
ECDSA
secp256k1
ECDSA算法在区块链应用里,多数币种用的是 secp256k1 ,比如ETH,BTC等。该曲线和算法,第一版代码是中本聪写的,当时并没有这个算法和曲线库的开源实现。
secp256r1 (aka: NIST P-256)
这个是比较老牌的曲线了,TLS用的就是这条曲线。ECDSA算法用这条secp256r1曲线的币种有:NEO和 ONT (Ontology)。其中b是一个常数,具体值比较大,这里就不写了
EDDSA
ED25519
在 ed25519曲线上,用 EDDSA算法的币种有: Monero(XMR), Cardano(ADA), Algorand(ALGO), Stellar(XLM), Tezos(XTZ), Zcash(ZEC), HBAR 等
Pallas
mina 这个币种,签名和密钥生成,用的曲线是 pallas,算法是 EDDSA。
ECDH
ECDH 的本质,就是通过两个公钥,算出一个共享秘密(AES key)。两个公钥相同,那么算出的共享秘密就相同。在浏览器TLS场景下,每次服务器和客户端都会临时生成一个 pub key,然后将pub key 发给对方,双方在自己的环境内,独立的算出 共享秘密 AES Key。ECDH 生成 AES key 的过程也叫 derive shared shared secret (和加密货币HD wallet的derive不一样)。可参考 AWS KMS Derive 的示例
HMAC
HMAC 和非对称式密钥的 Sign 有点像,都是对原始数据,产生一个 hmac 或签名,验证方拿原始的数据以及这个 hmac 和签名,做verify,看是否verify 通过,从而保证数据在传输的时候没有被人改过。 不同的是:HMAC 是对称式密钥的功能,Sign 是非对称密钥的功能。HMAC 由于双方都有AES key,所以双方都能创造 hmac 值和验证。而Sign 只有私钥拥有方才能签名,任何公钥持有者都能验证。HMAC性能要比Sign快一些(可能几十倍差距,并非数量级差别)
签名
示例一: 直接对原始字符串进行加密
示例二:在签名的时候,可以指定签名 encode的格式
示例三,对数据摘要进行签名
加密解密
使用 rsa 算法进行加密或解密
有关 PKCS#1 与 PKCS#8
如果是 openssl 1.x,默认创建的rsa 的私钥格式,是pkcs#1的(以-BEGIN RSA PRIVATE KEY开头),但openssl 3.x,默认创建的是pkcs#8(以BEGIN PRIVATE KEY开头)
以太坊私钥创建,以及地址验证
创建ECDSA的私钥(该私钥可以作为以太坊的私钥,直接导入metamask钱包)
上述得到公钥之后,可以使用下面的python代码,获取其地址(同时将key放到metamask里,对比下,将发现地址是一致的)
上述操作完整的python代码
AWS KMS 基础
对称式密钥
使用 AWS KMS创建的对称式密钥,如果直接使用 encrypt 或者 decrypt 接口对数据进行加密解密,那么加密的数据要求是4096字节以内,因此一般只适合加密数据库密码等数据,或者加密 data key(data key有时候也被称为 envelop key)。对于大量数据加密,一般是通过 GenerateDataKey的方式,产生一对对称式数据密钥,然后使用数据密钥对数据进行加密。也可以GenerateDataKeyPair 产生非对称式数据密钥,然后对数据做验签。
AWS KMS GenerateDataKey
只有对称式加密才能产生data key,非对称式加密无法产生data key。产生数据密钥的时候,会返回 Data Key 的 CiphertextBlob 以及 Plaintext,然后可以拿 Plaintext 直接进行加密。但如果此时只是想产生,并不需要立即使用,那么可以通过generate-data-key-without-plaintext 接口,只产生CiphertextBlob,不产生Plaintext。另外需要注意,无论是 CiphertextBlob 还是 Plaintext,都是 base64 编码过的。
如果是产生的 DataKeyWithoutPlaintext,那么需要先通过 aws kms decrypt --ciphertext-blob 接口解密,获得其明文的datakey,之后使用方法和上述一样
通过kms 算地址
注意,python里的 ethernum 包已经被弃用了,所以我们用 web3的这个包来算地址
然后我们可以做一笔签名,在签名里,还原回pub key,再次通过 pub key 算地址,看与之前是否一致 (我们也可以通过 cast 命令来生成一个待签名hash,做一笔真正的转账)
使用 openssl 产生 AES密钥
上述使用 kms 产生的 datakey,如果是想使用 openssl本地产生,可以使用下面的命令,之后使用方法和上述一样
Last updated