PKCS1_EncryptionSchemes_OAEP

7. Encryption Schemes

简称RSAES。本部分介绍非对称加密RSA使用的加密填充/编码方案。

当RSA明文较短时,则会有选择密文攻击的风险。

选择密文攻击,Chosen Ciphertext Attack,CCA。

攻击者具备条件:解密流程可控,即选定密文,得到明文。

比如,e==3,m < n^(1/3),那只需要对密文求立方根就能解密。

有两个加解密方案:

  • OAEP,适用于新应用
  • PKCS1-v1_5,处理兼容性

应用:

  • key establishment protocol, eg, PKCS #7 [RFC2315]

源码参考PyCryptodome \Crypto\Cipher\PKCS1_OAEP.py

7.1. RSAES-OAEP

RSA Encryption Schemes-Optimal(最优) Asymmetric Encryption Padding

相关技术:

  • EME-OAEP encoding
  • Bellare and Rogaway’s Optimal Asymmetric Encryption scheme [OAEP]
  • Integer Factorization Encryption Scheme (IFES) defined in IEEE 1363 [IEEE1363]
  • encryption primitives, IFEP-RSA
  • decryption primitives, IFDP-RSA
  • plaintext awareness (PA94) == plaintext awareness (PA98)
  • The indifferent attack scenario (denoted CCA1) == the adaptive scenario (denoted CCA2)

可操作消息长度: k - 2hLen -2 octets

  • hLen is the length of the output from the underlying hash function
  • k is the length in octets of the recipient’s RSA modulus

7.1.1. Encryption Operation

def RSAES-OAEP-ENCRYPT ((n, e), M, L):...
	# (n, e) recipient’s RSA public key
    # M message to be encrypted, an octet string of length mLen, where mLen <= k - 2hLen - 2
    # L optional label, default empty string
    return C # ciphertext, an octet string of length k

Options:

  • Hash, hash function (hLen denotes the length in octets of the hash function output)
  • MGF, mask generation function (Appendix B.2)

steps:

  1. Length checking

# See 7.1.1 in RFC3447
modBits = Crypto.Util.number.size(self._key.n)	# 1024
k = ceil_div(modBits, 8) # 128 Convert from bits to bytes
hLen = self._hashObj.digest_size	# sha1 20
mLen = len(message)	# eg 19
# Step 1a
# length of L
# Step 1b
ps_len = k - mLen - 2 * hLen - 2	# 67 = 128-19-40-2
if ps_len < 0:
    raise ValueError("Plaintext is too long.")
  1. EME-OAEP encoding (see Figure 1 below)

# Step 2a
lHash = self._hashObj.new(self._label).digest()
# Step 2b padding string
ps = b'\x00' * ps_len
# Step 2c data block
# DB = lHash || PS || 0x01 || M
db = lHash + ps + b'\x01' + _copy_bytes(None, None, message)
# Step 2d
seed = self._randfunc(hLen)
# Step 2e
dbMask = self._mgf(seed, k-hLen-1)
# Step 2f
maskedDB = strxor(db, dbMask)
# Step 2g
seedMask = self._mgf(maskedDB, hLen)
# Step 2h
maskedSeed = strxor(ros, seedMask)
# Step 2i
# EM = 0x00 || maskedSeed || maskedDB
em = b'\x00' + maskedSeed + maskedDB
  1. RSA encryption:
# Step 3a (OS2IP)
em_int = bytes_to_long(em)
# Step 3b (RSAEP)
m_int = self._key._encrypt(em_int)
# Step 3c (I2OSP)
c = long_to_bytes(m_int, k)
return c
  1. Output the ciphertext C
Figure 1: EME-OAEP Encoding Operation
                        +----------+------+--+-------+
                DB =    | lHash    | PS   |01|   M   |
                        +----------+------+--+-------+
                                     |
            +----------+             |
            |   seed   |             |
            +----------+             |
                |                    |
                |-------> MGF --->  xor
                |                    |
        +--+    V                    |
        |00|    xor <----- MGF <-----|
        +--+    |                    |
          |     |                    |
          V     V                    V
        +--+----------+----------------------------+
 EM =   |00|maskedSeed|          maskedDB          |
        +--+----------+----------------------------+

EM长度填充为密钥长度。

BT为00,则PS==00,EM变成了小数,减小了计算量。

7.1.2. Decryption Operation

def RSAES-OAEP-DECRYPT (K, C, L):
    # K recipient’s RSA private key (k denotes the length inoctets of the RSA modulus n), where k >= 2hLen + 2
	# C ciphertext to be decrypted, an octet string of length k
 	# L optional label
    return M # message, an octet string of length mLen, where mLen <= k - 2hLen - 2

steps:

  1. Length checking
# See 7.1.2 in RFC3447
modBits = Crypto.Util.number.size(self._key.n)
k = ceil_div(modBits,8) # Convert from bits to bytes
hLen = self._hashObj.digest_size

# Step 1b and 1c
if len(ciphertext) != k or k<hLen+2:
    raise ValueError("Ciphertext with incorrect length.")
  1. RSA decryption
# Step 2a (O2SIP)
ct_int = bytes_to_long(ciphertext)
# Step 2b (RSADP)
m_int = self._key._decrypt(ct_int)
# Complete step 2c (I2OSP)
em = long_to_bytes(m_int, k)
  1. EME-OAEP decoding
  2. Output the message M
# Step 3a
lHash = self._hashObj.new(self._label).digest()
# Step 3b
# EM = Y || maskedSeed || maskedDB
y = em[0]
# y must be 0, but we MUST NOT check it here in order not to
# allow attacks like Manger's (http://dl.acm.org/citation.cfm?id=704143)
maskedSeed = em[1:hLen+1]
maskedDB = em[hLen+1:]	# length k - hLen - 1
# Step 3c
seedMask = self._mgf(maskedDB, hLen)
# Step 3d
seed = strxor(maskedSeed, seedMask)
# Step 3e
dbMask = self._mgf(seed, k-hLen-1)
# Step 3f
db = strxor(maskedDB, dbMask)
# Step 3g
# DB = lHash’ || PS || 0x01 || M
one_pos = hLen + db[hLen:].find(b'\x01')
lHash1 = db[:hLen]
invalid = bord(y) | int(one_pos < hLen)
hash_compare = strxor(lHash1, lHash)
for x in hash_compare:
    invalid |= bord(x)
for x in db[hLen:one_pos]:
    invalid |= bord(x)
if invalid != 0:
	raise ValueError("Incorrect decryption.")
# Step 4
return db[one_pos + 1:]

Appendix B. Supporting Techniques

B.2. Mask Generation Functions

MGF是一个依赖于hash函数的伪随机函数,应用于RSAES-OAEP和RSASSA-PSS。

PyCryptodome源码:\Crypto\Signature\pss.py

def MGF1(mgfSeed, maskLen, hash_gen):
    
    T = b""
    for counter in iter_range(ceil_div(maskLen, hash_gen.digest_size)):
        c = long_to_bytes(counter, 4)
        hobj = hash_gen.new()
        hobj.update(mgfSeed + c)
        T = T + hobj.digest()
    assert(len(T) >= maskLen)
    return T[:maskLen]

C实现:https://github.com/C0deStarr/CryptoImp/tree/main/common/util.h , MGF()

实现

https://github.com/C0deStarr/CryptoImp/tree/main/pubkey/rsa

  • pkcs1_oaep.c
  • pkcs1_oaep.h

参考资料

RFC 8017: PKCS #1: RSA Cryptography Specifications Version 2.2

Manger01.pdf (ethz.ch)

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值