gpg: support RSA decode and verify

This commit is contained in:
Roman Zeyde
2016-04-30 10:56:15 +03:00
parent 5d007260e1
commit 9ed9781496
2 changed files with 46 additions and 12 deletions

View File

@@ -86,7 +86,15 @@ def _parse_ecdsa_sig(sig):
util.bytes2num(sig_s))
def sign(sock, keygrip, digest):
def _parse_rsa_sig(sig):
data, (algo, (s, sig_s)) = sig
assert data == 'sig-val'
assert algo == 'rsa'
assert s == 's'
return (util.bytes2num(sig_s),)
def sign(sock, keygrip, digest, algo='ecdsa'):
"""Sign a digest using specified key using GPG agent."""
hash_algo = 8 # SHA256
assert len(digest) == 32
@@ -115,7 +123,7 @@ def sign(sock, keygrip, digest):
sig, leftover = _parse(sig)
assert not leftover
return _parse_ecdsa_sig(sig)
return {'ecdsa': _parse_ecdsa_sig, 'rsa': _parse_rsa_sig}[algo](sig)
def get_keygrip(user_id):

View File

@@ -68,11 +68,27 @@ def _parse_ed25519_verifier(mpi):
return _ed25519_verify, vk
def _create_rsa_verifier(n, e):
def verifier(signature, digest):
s, = signature
size = n.bit_length()
result = pow(s, e, n) % (2 ** 256)
digest = util.bytes2num(digest)
if result == digest:
log.debug('RSA-%d signature is OK', size)
return True
else:
raise ValueError('invalid RSA signature')
return verifier
SUPPORTED_CURVES = {
b'\x2A\x86\x48\xCE\x3D\x03\x01\x07': _parse_nist256p1_verifier,
b'\x2B\x06\x01\x04\x01\xDA\x47\x0F\x01': _parse_ed25519_verifier,
}
ECDSA_ALGO_IDS = (19, 22) # (nist256, ed25519)
def _parse_literal(stream):
"""See https://tools.ietf.org/html/rfc4880#section-5.9 for details."""
@@ -119,7 +135,11 @@ def _parse_signature(stream):
p['embedded'] = embedded
p['hash_prefix'] = stream.readfmt('2s')
p['sig'] = (parse_mpi(stream), parse_mpi(stream))
if p['pubkey_alg'] in ECDSA_ALGO_IDS:
p['sig'] = (parse_mpi(stream), parse_mpi(stream))
else: # RSA
p['sig'] = (parse_mpi(stream),)
assert not stream.read()
return p
@@ -132,16 +152,23 @@ def _parse_pubkey(stream):
p['version'] = stream.readfmt('B')
p['created'] = stream.readfmt('>L')
p['algo'] = stream.readfmt('B')
if p['algo'] in ECDSA_ALGO_IDS:
# https://tools.ietf.org/html/rfc6637#section-11
oid_size = stream.readfmt('B')
oid = stream.read(oid_size)
assert oid in SUPPORTED_CURVES, util.hexlify(oid)
parser = SUPPORTED_CURVES[oid]
# https://tools.ietf.org/html/rfc6637#section-11
oid_size = stream.readfmt('B')
oid = stream.read(oid_size)
assert oid in SUPPORTED_CURVES
parser = SUPPORTED_CURVES[oid]
mpi = parse_mpi(stream)
log.debug('mpi: %x (%d bits)', mpi, mpi.bit_length())
p['verifier'], p['verifying_key'] = parser(mpi)
else: # RSA
n = parse_mpi(stream)
e = parse_mpi(stream)
log.debug('n: %x (%d bits)', n, n.bit_length())
log.debug('e: %x (%d bits)', e, e.bit_length())
p['verifier'] = _create_rsa_verifier(n, e)
mpi = parse_mpi(stream)
log.debug('mpi: %x (%d bits)', mpi, mpi.bit_length())
p['verifier'], p['verifying_key'] = parser(mpi)
assert not stream.read()
# https://tools.ietf.org/html/rfc4880#section-12.2
@@ -252,7 +279,6 @@ def load_public_key(stream):
subkey = subsig = None
if len(packets) == 5:
pubkey, userid, signature, subkey, subsig = packets
# TODO: refactor this out!
log.debug('subkey: %s', subkey)
log.debug('subsig: %s', subsig)
else: