🧑‍🏫
liualexiang
  • Introduction
  • Azure
    • AKS Basic
    • AKS Spark
    • AZ ACR SYNC
    • Azure CMI SDWAN
    • Azure LB DeepDive
      • Azure LB DeepDive
    • Azure Service Principal Basic
    • Azure Internal VM Network Connectivity
      • Azure Internal VM Network Connectivity
    • Azure Cli Build
    • Azure Vm Memory Monitor
  • Blockchain
    • BTC
  • CRISPR
    • 使用Parallel_Cluster提升CRISPA效率
  • OpenSource
    • ElasticSearch
      • ES Get Started
      • ES Search Query
      • Kibana 可视化
      • Logstash配置
    • Ansible 基础
    • Infra As Code
      • Pulumi Get Started
      • Terraform Basic
    • ZooKeeper 基础
    • RPC与REST
    • 使用Python申请大量内存测试
    • 使用TPC_DS产生压测数据
    • Superset
      • Superset部署手册
    • 代码扫描
    • Git
      • Git Basic
      • Github Action Basic
      • Gitlab与AzureAD集成
      • Gitbook 基础教程
    • K8S
      • enter_node
      • K8s X509 Client Cert
      • K8s Basic
      • K8s Oidc
      • Docker 基础
      • helm基础
      • K8S_Secrets管理
      • 深入了解K8S
      • 混沌工程
      • Istio
      • 生态
      • CRD开发
      • k8s网络
    • Cloud_Custodian
    • Jenkins Basic
    • Nginx
    • ETCD
    • 正则
    • VictoriaMetrics
    • Kafka
  • MySQL
    • MySQL 调优
  • Linux
    • SSH Tunnel 上网
    • 内存管理
    • 在Linux系统中通过LUKS加密磁盘
    • 量子计算 Basic
    • IO多路复用
    • Iptables
    • tmux和screen
    • Systemd
    • OS 基础
    • jq基础
    • yum
    • neovim
  • Web
    • Html Css
    • Web部署
    • 缓存
  • Programming
    • 算法
      • 返回list中最大生序子序列长度
    • Python技巧
      • Python的语法糖
      • Python常用装饰器
      • AsyncIO基础
      • 自动化测试pytest
      • python中的下划线
      • 面向对象
      • Python的坑
      • Python配置文件管理
      • HTTP Stream Response
      • Python项目管理
    • 设计模式
      • 设计模式
      • 面向对象的思想
      • 编程概念
    • Go
      • Go 基础
      • Go常用功能
      • 结构体入门
    • 前端
    • Vue
    • NodeJS
  • Math
    • 多项式插值法
  • Security
    • HTTP常见攻击
    • 加密与签名
    • RSA
    • ECDSA
  • Solidity
    • Solidity基础
    • Blockchain Testnet Faucet
  • Tools
    • 视频处理ffmpeg
    • IDE配置
    • iTerm2美化
    • 密码管理
    • FRP配置
    • 工具集
由 GitBook 提供支持
在本页
  • 简介
  • 区块链的曲线和算法
  • ECDSA
  • EDDSA
  • 有关椭圆曲线
  • 签名
  • 加密解密
  • 有关 PKCS#1 与 PKCS#8
  • 以太坊私钥创建,以及地址验证
  • AWS KMS 基础
  • 对称式密钥
  1. Security

加密与签名

简介

加密一般是用公钥进行加密,然后使用私钥进行解密(注意一般不会反向操作)。签名一般指的是,通过私钥对数据的摘要(hash值)进行签名,摘要保证了数据的完整性,签名后的数据,可以用公钥进行验证。

一般加密使用 RSA(RSA也可以用做签名),签名可以使用 ECDSA(ECDSA不具备加密能力)。

RSA 是基于质因数分解,椭圆曲线算法是依赖于椭圆曲线离散对数问题的困难性。从安全性角度看,椭圆曲线离散对数问题比整数质因数分解更困难。RSA需要更长的密钥(2048位以上)来保证安全强度,ECDSA可以使用更短的密钥。256位的 ECDSA密钥与3072位的RSA密钥强度相当。ECDSA的实现比较复杂,需要找到合适的椭圆曲线,RSA比较简单。

区块链的曲线和算法

主要的算法有:

ECDSA

secp256k1

ECDSA算法在区块链应用里,多数币种用的是 secp256k1 ,比如ETH,BTC等。该曲线和算法,第一版代码是中本聪写的,当时并没有这个算法和曲线库的开源实现。 y2=X3+7y^2 = X^3 +7y2=X3+7

secp256r1 (aka: NIST P-256)

这个是比较老牌的曲线了,TLS用的就是这条曲线。ECDSA算法用这条secp256r1曲线的币种有:NEO和 ONT (Ontology)。其中b是一个常数,具体值比较大,这里就不写了

y2=x3−3x+by^2 = x^3 -3x + by2=x3−3x+b

EDDSA

ED25519

在 ed25519曲线上,用 EDDSA算法的币种有: Monero(XMR), Cardano(ADA), Algorand(ALGO), Stellar(XLM), Tezos(XTZ), Zcash(ZEC), HBAR 等

Pallas

mina 这个币种,签名和密钥生成,用的曲线是 pallas,算法是 EDDSA。

有关椭圆曲线

ECC、ECDSA、EDDSA、ECDH、ECDHE都是基于椭圆曲线 cryptography (ECC) 的算法,它们之间的区别如下:

  • ECC 是椭圆曲线加密算法的总称,提供了基于椭圆曲线数学原理的公钥密码学框架。

  • ECDSA 是基于ECC的数字签名算法,用于生成签名和验证签名。

  • EDDSA 是新一代的ECC签名算法,相比ECDSA有各种改进。

  • ECDH 是基于ECC的密钥交换/协商算法,用于在双方生成共享密钥。

  • ECDHE 是使用ECDHE执行密钥交换的协议,常用在TLS等加密通信中。

总结一下:

  • ECC是基础框架。

  • ECDSA用于数字签名。

  • EDDSA是改进版本签名算法。

  • ECDH进行密钥协商。

  • ECDHE应用于密钥交换协议。

签名

示例一: 直接对原始字符串进行加密

## ecdsa              0.18.0
import ecdsa.util
from ecdsa import SigningKey, SECP256k1

# 生成签名秘钥
sk = SigningKey.generate(curve=SECP256k1)

# 待签名信息
message = "abc"
message_bytes = message.encode()

# 计算签名
signature = sk.sign(message_bytes)
r, s = ecdsa.util.sigdecode_string(signature, order=SECP256k1.generator.order())
print(r,s)

# 验证签名
vk = sk.verifying_key
print(vk.verify(signature, message_bytes)) # True

示例二:在签名的时候,可以指定签名 encode的格式


import ecdsa
import hashlib

# 生成签名秘钥
sk = ecdsa.SigningKey.generate(curve=ecdsa.SECP256k1)

# 消息
message = b"abc"

# 签名,下面sign的时候,也可以指定 entropy 为任意正整数,这个代表了椭圆曲线算法的 k,默认用的是 os.urandom()
sig = sk.sign(message, hashfunc= hashlib.sha256, sigencode=ecdsa.util.sigencode_der)


from ecdsa.util import sigdecode_der

curve = ecdsa.SECP256k1
order = curve.generator.order()
r, s = sigdecode_der(sig,order)
print(r, s)

# 验证签名
vk = sk.verifying_key
print(vk.verify(sig, message, hashfunc=hashlib.sha256, sigdecode=sigdecode_der))

示例三,对数据摘要进行签名

## ecdsa              0.18.0
import ecdsa.util
from ecdsa import SigningKey, SECP256k1
import hashlib

# 生成签名秘钥
sk = SigningKey.generate(curve=SECP256k1)

# 待签名信息,获取其摘要
message = "abc"
message_bytes = message.encode()

hash_func = hashlib.sha256()
hash_func.update(message_bytes)
msg_digest = hash_func.digest()

# 计算签名
signature = sk.sign(msg_digest)
r, s = ecdsa.util.sigdecode_string(signature, order=SECP256k1.generator.order())
print(r,s)

# 可选步骤:将签名转为16进制字符串
import codecs
signature_hex = codecs.encode(signature, 'hex')
print(signature_hex)


# 验证签名
vk = sk.verifying_key
print(vk.verify(signature, msg_digest)) # True

加密解密

使用 rsa 算法进行加密或解密

# 默认使用  PKCS#1v1.5进行RSA填充,也可以指定使用TLS填充
import rsa

# 生成RSA密钥对
(pubkey, privkey) = rsa.newkeys(1024)

# 待加密信息
message = 'hello world'

# RSA加密
crypto = rsa.encrypt(message.encode(), pubkey)

# RSA解密
message = rsa.decrypt(crypto, privkey).decode()

print(message)

有关 PKCS#1 与 PKCS#8

如果是 openssl 1.x,默认创建的rsa 的私钥格式,是pkcs#1的(以-BEGIN RSA PRIVATE KEY开头),但openssl 3.x,默认创建的是pkcs#8(以BEGIN PRIVATE KEY开头)

# openssl 1.x
 openssl genrsa -out private-key.pem
 openssl rsa  -pubout -in private-key.pem -out public-key.pem
 
# openssl 3.x
openssl genrsa -traditional -out private-key.pem
openssl rsa -traditional -pubout -in private-key.pem -out public-key.pem  

以太坊私钥创建,以及地址验证

创建ECDSA的私钥(该私钥可以作为以太坊的私钥,直接导入metamask钱包)

openssl ecparam -name secp256k1 -genkey -noout -out ec-secp256k1-priv-key.pem

#获得公钥和私钥,保存到key文件
cat ec-secp256k1-priv-key.pem | openssl ec -text -noout > key

# 私钥
cat key | grep priv -A 3 | tail -n +2 | tr -d '\n[:space:]:' | sed 's/^00//' > priv

# 公钥
cat key | grep pub -A 5 | tail -n +2 | tr -d '\n[:space:]:' | sed 's/^04//' > pub

上述得到公钥之后,可以使用下面的python代码,获取其地址(同时将key放到metamask里,对比下,将发现地址是一致的)

from ethereum import utils

def generate_ethereum_address(public_key):
    address = utils.sha3(public_key)[-20:]
    return '0x' + address.hex()

# Example public key (replace this with an actual public key)
public_key = bytes.fromhex("74f96b6971d2cdc996e1ac4886cb45ed7c995b3bbba513da1b8822d3162da2b262909754c0b5c98f1dd26943672b6e1f319e7220aa39fef220a2900423b573b8")

ethereum_address = generate_ethereum_address(public_key)
print("Ethereum Address:", ethereum_address)

上述操作完整的python代码

from ecdsa import SigningKey, SECP256k1
sk = SigningKey.generate(curve=SECP256k1)

prv_key_hex = sk.to_string().hex()
print(prv_key_hex)

pub_key = sk.get_verifying_key()
pub_key_hex = pub_key.to_string().hex()
print(pub_key_hex)

# 也可以将上述信息,保存到文件中
#生成私钥pem文件
# with open("private.pem", "wb") as f:
#     f.write(sk.to_pem())
#
#
# # 从私钥pem文件中,读取pk信息
# with open("private.pem", "r") as f:
#     private_key_pem = f.read()
# sk = SigningKey.from_pem(private_key_pem)
#
#
# prv_key_hex = sk.to_string().hex()
# print(prv_key_hex)
#
# pub_key = sk.get_verifying_key()
# pub_key_hex = pub_key.to_string().hex()
# print(pub_key_hex)

## 获得以太坊地址
from ethereum import utils
def generate_ethereum_address(public_key):
    address = utils.sha3(public_key)[-20:]
    return '0x' + address.hex()
public_key = bytes.fromhex(pub_key_hex)

ethereum_address = generate_ethereum_address(public_key)
print("Ethereum Address:", ethereum_address)

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 编码过的。

export KEY_ID=$AWS_KEY_ID

# 获得明文的datakey,并将其保存到文件中
aws kms generate-data-key --key-id $KEY_ID --key-spec AES_256 --query Plaintext --output text | base64 -d > plaintext_datakey

# 使用上述产生的datakey,对 my_secret_message.txt 文件进行加密,并将加密后的数据保存成一个 .enc 的新文件
openssl enc -e -aes256 -kfile plaintext_datakey \
-in my_secret_message.txt \
-out my_secret_message.enc

# 解密,获得新的文件
openssl enc -d -aes256 -kfile plaintext_datakey \
-in my_secret_message.enc \
-out new_plaintext_message.txt

如果是产生的 DataKeyWithoutPlaintext,那么需要先通过 aws kms decrypt --ciphertext-blob 接口解密,获得其明文的datakey,之后使用方法和上述一样

aws kms generate-data-key-without-plaintext --key-id $KEY_ID --key-spec AES_256 --query CiphertextBlob --output text | xargs -I {} aws kms decrypt --ciphertext-blob {} --query Plaintext --output text | base64 -d > plaintext_datakey

使用 openssl 产生 AES密钥

上述使用 kms 产生的 datakey,如果是想使用 openssl本地产生,可以使用下面的命令,之后使用方法和上述一样

# AES 256密钥:该命令其实是生成32字节的随机数,每个字节8位,因此是256位,生成的密钥保存在 aes256key.bin文件中
openssl rand -out aes256key.bin 32
# 生成 AES 128
openssl rand -out aes256key.bin 16
# 生成 AES 192
openssl rand -out aes192key.bin 24
上一页HTTP常见攻击下一页RSA

最后更新于7个月前