def import_pubkey(key, rsa): (magic, key) = gale_pack.pop_data(key, len(PRIVATE_MAGIC3)) (namelen, key) = gale_pack.pop_int(key) (pubkeyname, key) = gale_pack.pop_string(key, namelen, chars=1) fraglist = gale_pack.group_to_FragList(key, 1) rsa.n = openssl.bn.bin2bn(fraglist.get_binary_first('rsa.modulus')) rsa.e = openssl.bn.bin2bn(fraglist.get_binary_first('rsa.exponent')) rsa.d = openssl.bn.bin2bn(fraglist.get_binary_first('rsa.private.exponent')) prime_data = fraglist.get_binary_first('rsa.private.prime') rsa.p = openssl.bn.bin2bn(prime_data[:GALE_RSA_PRIME_LEN]) rsa.q = openssl.bn.bin2bn(prime_data[GALE_RSA_PRIME_LEN:]) prime_data = fraglist.get_binary_first('rsa.private.prime.exponent') rsa.dmp1 = openssl.bn.bin2bn(prime_data[:GALE_RSA_PRIME_LEN]) rsa.dmq1 = openssl.bn.bin2bn(prime_data[GALE_RSA_PRIME_LEN:]) rsa.iqmp = openssl.bn.bin2bn(fraglist.get_binary_first('rsa.private.coefficient'))
def import_pubkey(keyobj, callback, trust=0): if DEBUG > 2: print '--> Starting import_pubkey' keydata = keyobj.data() # _ga_import_pub # Back up the key to verify its signature, later save = keydata (magic, keydata) = gale_pack.pop_data(keydata, len(KEY_MAGIC)) if KEY_MAGIC == magic: version = 1 elif KEY_MAGIC2 == magic: version = 2 elif KEY_MAGIC3 == magic: (subversion, keydata) = gale_pack.pop_data(keydata, len(SUBVERSION)) if SUBVERSION == subversion: version = 3 else: pygale.call_error_handler('Unsupported version 3 key format') keyobj.setpublic(None) keyobj.set_verified(0) callback(keyobj) return else: pygale.call_error_handler('Unsupported public key (bad magic)') keyobj.setpublic(None) keyobj.set_verified(0) callback(keyobj) return # version must be <= 3 at this point if DEBUG >= 3: print 'Public key version:', version if version > 1: (namelen, keydata) = gale_pack.pop_int(keydata) (pubkeyname, keydata) = gale_pack.pop_string(keydata, namelen, chars=1) else: # version == 1 (pubkeyname, keydata) = gale_pack.pop_nulltermstr(keydata) pubkeyname = flip_local_key_part(pubkeyname) if DEBUG > 2: print 'Unpacking public key named:', pubkeyname keyobj.setname(pubkeyname) if DEBUG > 2: print 'Setting name in %s to %s' % (`keyobj`, pubkeyname) keyobj.settrusted(trust) if len(keydata) == 0: if DEBUG: print 'Found stub key for', pubkeyname keyobj.setpublic(None) callback(keyobj) return # Otherwise, deal with a non-stub key # Special-case for different version keys. Version 3 is the key with # fragments in it, which Dan introduced in 0.91b. if version == 3: fraglist = gale_pack.group_to_FragList(keydata, DAN_IS_STOOPID=1) # Verify key if it's signed if fraglist.has_key('security/signature'): # deal with only the first security/signature fragment sig = fraglist.get_binary_first('security/signature') (sig_len, sig) = gale_pack.pop_int(sig) (signature, sig) = gale_pack.pop_data(sig, sig_len) msg_data = sig new_fragments = gale_pack.group_to_FragList(sig) fraglist.update(new_fragments) else: signature = '' # TODO # This hacky setting of msg_data is to fix the bug later on # where we try to call decode_sig with msg_data. I need to # dig into key formats more to find the right thing to do. msg_data = '' # TODO dangermouse # Redirects should not be handled here since the field contains # a *location* and not a key name if fraglist.get_text('key.redirect'): # Handle a key redirection: the field contains a *location* keyobj.set_redirect(fraglist.get_text_first('key.redirect')) # Use only the first instance of each fragment if it exists comment = fraglist.get_text_first('key.owner', 'Unspecified owner') time_sign = fraglist.get_time_first('key.signed', 0) time_expire = fraglist.get_time_first('key.expires', 0) rsa_keybits = fraglist.get_int_first('rsa.bits', 0) rsa_modulus = fraglist.get_binary_first('rsa.modulus', '') rsa_exponent = fraglist.get_binary_first('rsa.exponent', '') # Set the list of key members but do not look them up at this # point if fraglist.has_key('key.member'): keyobj.set_members(fraglist.get_text('key.member')) # Done unpacking version 3 key # Version 1 or 2 keys are packed binary data. elif version == 1 or version == 2: if version == 2: (comment, keydata) = gale_pack.pop_lenstr(keydata, chars=1) else: (comment, keydata) = gale_pack.pop_nulltermstr(keydata) if DEBUG > 2: print 'Found comment:', comment (rsa_keybits, keydata) = gale_pack.pop_int(keydata) (rsa_modulus, keydata) = gale_pack.pop_rle(keydata, GALE_RSA_MODULUS_LEN) (rsa_exponent, keydata) = gale_pack.pop_rle(keydata, GALE_RSA_MODULUS_LEN) if rsa_keybits > GALE_RSA_MODULUS_BITS: pygale.call_error_handler( 'bad public key bit size %i' % rsa_keybits) keyobj.setpublic(None) keyobj.set_verified(0) callback(keyobj) return if version > 1 and keydata: (time_sign, keydata) = gale_pack.pop_time(keydata) (time_expire, keydata) = gale_pack.pop_time(keydata) if DEBUG > 2: print 'Key signed at:', time_sign.ctime() if DEBUG > 2: print 'Key expires at:', time_expire.ctime() # if time_expire <= time.time(): # pygale.call_error_handler('found expired key for %s' % # pubkeyname) # callback(None) # return else: # no key timestamp checking in version 1 pass signature = keydata # Done unpacking version 1 or version 2 key else: # unsupported version pygale.call_error_handler('unsupported key version: %i' % version) keyobj.setpublic(None) keyobj.set_verified(0) callback(keyobj) return # TODO: check for expired keys keyobj.setcomment(comment) if rsa_keybits: pubkey = openssl.evp.PKEY() pubkey.assign_RSA(openssl.rsa.RSA()) pubkey.pkey.rsa.n = openssl.bn.bin2bn(rsa_modulus) pubkey.pkey.rsa.e = openssl.bn.bin2bn(rsa_exponent) keyobj.setpublic(pubkey) else: # No public key bits in this key keyobj.setpublic(None) # Import and validate the signature on this public key if not keyobj.trusted(): if DEBUG > 2: print 'import_pubkey: Verifying sig' if version < 3: msg_data = save[:-len(keydata)] if not signature or not msg_data: pygale.call_error_handler('unsigned key %s' % keyobj.name()) keyobj.setpublic(None) keyobj.set_verified(0) callback(keyobj) return decode_sig(signature, msg_data, lambda k, u=keyobj, c=callback: decode_done(k, u, c)) else: if DEBUG: print 'Key is trusted; not verifying' keyobj.set_verified(1) callback(keyobj) return