def do_sign(g, pubkey, digest_algo, digest): g.send_command('SIGKEY %s\n' % hexlify(pubkey.compute_keygrip())) if digest_algo == DIGEST_SHA256: g.send_command('SETHASH --hash=sha256 %s\n' % hexlify(digest)) else: raise ('Unknown digest algorithm', digest_algo) g.send_command('PKSIGN\n') sig_result_str = g.get_response() sig_sexp = sexp(sig_result_str) # [ "sig-val" [ "rsa" [ "s" "xxx" ] ] ] return sig_sexp[1][1][1]
def do_sign(g, pubkey, digest_algo, digest): g.send_command('SIGKEY %s\n' % hexlify(pubkey.compute_keygrip())) if digest_algo == DIGEST_SHA256: g.send_command('SETHASH --hash=sha256 %s\n' % hexlify(digest)) else: raise('Unknown digest algorithm', digest_algo) g.send_command('PKSIGN\n') sig_result_str = g.get_response() sig_sexp = sexp(sig_result_str) # [ "sig-val" [ "rsa" [ "s" "xxx" ] ] ] return sig_sexp[1][1][1]
def build_rsakey_from_ssh_key_under_gpg_agent(g, timestamp=None): # (1) Get the list of available key specifying '--with-ssh' g.send_command("KEYINFO --list --with-ssh --data\n") kl_str = g.get_response() kl_str = kl_str[0:-1] kl = kl_str.split('\n') # (2) Select SSH key(s) kl_ssh = [kg for kg in kl if re.search("S$", kg)] # Select SSH key # (3) Use the first entry of the list (in future, use all???) print("KEYINFO: %s" % kl_ssh[0]) # KG: The keygrip of key in question kg = kl_ssh[0].split(' ')[0] # By READKEY command, get the public key information of KG g.send_command("READKEY %s\n" % kg) pubkey_info_str = g.get_response() # The information is in SEXP format, extract N and E s = sexp(pubkey_info_str) if s[0] != 'public-key': print s exit(1) rsa = s[1] if rsa[0] != 'rsa': print rsa exit(1) n_x = rsa[1] if n_x[0] != 'n': print n_x exit(1) n_byte_str = n_x[1] while n_byte_str[0] == '\x00': n_byte_str = n_byte_str[1:] n = n_byte_str e_x = rsa[2] if e_x[0] != 'e': print e_x exit(1) e = e_x[1] if not timestamp: timestamp = int(time()) # Compose our RSA_KEY by TIMESTAMP, N, and E return rsa_key(timestamp, n, e)
def build_rsakey_from_ssh_key_under_gpg_agent(g, timestamp=None): # (1) Get the list of available key specifying '--with-ssh' g.send_command("KEYINFO --list --with-ssh --data\n") kl_str = g.get_response() kl_str = kl_str[0:-1] kl = kl_str.split('\n') # (2) Select SSH key(s) kl_ssh = [kg for kg in kl if re.search("S$", kg)] # Select SSH key # (3) Use the first entry of the list (in future, use all???) print("KEYINFO: %s" % kl_ssh[0]) # KG: The keygrip of key in question kg = kl_ssh[0].split(' ')[0] # By READKEY command, get the public key information of KG g.send_command("READKEY %s\n" % kg) pubkey_info_str = g.get_response() # The information is in SEXP format, extract N and E s = sexp(pubkey_info_str) if s[0] != 'public-key': print s exit(1) rsa = s[1] if rsa[0] != 'rsa': print rsa exit(1) n_x = rsa[1] if n_x[0] != 'n': print n_x exit(1) n_byte_str = n_x[1] while n_byte_str[0] == '\x00': n_byte_str = n_byte_str[1:] n = n_byte_str e_x = rsa[2] if e_x[0] != 'e': print e_x exit(1) e = e_x[1] if not timestamp: timestamp = int(time()) # Compose our RSA_KEY by TIMESTAMP, N, and E return rsa_key(timestamp,n,e)
def OnCopyData(self, hwnd, msg, wparam, lparam): debug("WM_COPYDATA message") debug(" window=%08x" % hwnd) debug(" msg =%08x" % msg) debug(" wparam=%08x" % wparam) pCDS = ctypes.cast(lparam, P_COPYDATA) debug(" dwData=%08x" % (pCDS.contents.dwData & 0xffffffff)) debug(" len=%d" % pCDS.contents.cbData) mapname = ctypes.string_at(pCDS.contents.lpData) debug(" mapname='%s'" % ctypes.string_at(pCDS.contents.lpData)) hMapObject = ctypes.windll.kernel32.OpenFileMappingA( FILE_MAP_ALL_ACCESS, 0, mapname) if hMapObject == 0: debug("error on OpenFileMapping") return 0 pBuf = ctypes.windll.kernel32.MapViewOfFile(hMapObject, FILE_MAP_ALL_ACCESS, 0, 0, 0) if pBuf == 0: ctypes.windll.kernel32.CloseHandle(hMapObject) debug("error on MapViewOfFile") return 0 pSshMsg = ctypes.cast(pBuf, P_SSH_MSG_HEAD) debug(" ssh_msg_len: %d" % pSshMsg.contents.msg_len) debug(" ssh_msg_type: %d" % pSshMsg.contents.msg_type) if pSshMsg.contents.msg_type == 11: # SSH2_AGENT_REQUEST_IDENTITIES blob_len = len(ssh_rsa_public_blob) cmnt_len = len(ssh_key_comment) pAns = ctypes.cast(pBuf, P_SSH_MSG_ID_ANSWER) pAns.contents.msg_len = 1 + 4 + 4 + blob_len + 4 + cmnt_len pAns.contents.msg_type = 12 # SSH2_AGENT_IDENTITIES_ANSWER pAns.contents.keys = 1 ctypes.memmove(pBuf + 4 + 1 + 4, pack('>I', blob_len), 4) ctypes.memmove(pBuf + 4 + 1 + 4 + 4, ssh_rsa_public_blob, blob_len) ctypes.memmove(pBuf + 4 + 1 + 4 + 4 + blob_len, pack('>I', cmnt_len), 4) ctypes.memmove(pBuf + 4 + 1 + 4 + 4 + blob_len + 4, ssh_key_comment, cmnt_len) debug("answer is:") debug(" ssh_msg_len: %d" % pSshMsg.contents.msg_len) debug(" ssh_msg_type: %d" % pSshMsg.contents.msg_type) elif pSshMsg.contents.msg_type == 13: # SSH2_AGENT_SIGN_REQUEST req_blob_len = unpack(">I", ctypes.string_at(pBuf + 5, 4))[0] req_blob = ctypes.string_at(pBuf + 5 + 4, req_blob_len) req_data_len = unpack( ">I", ctypes.string_at(pBuf + 5 + 4 + req_blob_len, 4))[0] req_data = ctypes.string_at(pBuf + 5 + 4 + req_blob_len + 4, req_data_len) debug(" blob_len=%d" % req_blob_len) debug(" data_len=%d" % req_data_len) hash = hashlib.sha1(req_data).hexdigest() debug(" hash=%s" % hash) g.send_command('SIGKEY %s\n' % keygrip) g.send_command('SETHASH --hash=sha1 %s\n' % hash) g.send_command('PKSIGN\n') sig = sexp(g.get_response()) # [ "sig-val" [ "rsa" [ "s" "xxx" ] ] ] sig = sig[1][1][1] sig = "\x00\x00\x00\x07" + "ssh-rsa" + "\x00\x00\x01\x00" + sig # FIXME: should support different key size siglen = len(sig) debug("sig_len=%d" % siglen) debug("sig=%s" % binascii.hexlify(sig)) pRes = ctypes.cast(pBuf, P_SSH_MSG_SIGN_RESPONSE) pRes.contents.msg_len = 1 + 4 + siglen pRes.contents.msg_type = 14 # SSH2_AGENT_SIGN_RESPONSE pRes.contents.sig_len = siglen ctypes.memmove(pBuf + 4 + 1 + 4, sig, siglen) debug("answer is:") debug(" ssh_msg_len: %d" % pSshMsg.contents.msg_len) debug(" ssh_msg_type: %d" % pSshMsg.contents.msg_type) else: exit(0) ctypes.windll.kernel32.UnmapViewOfFile(pBuf) ctypes.windll.kernel32.CloseHandle(hMapObject) debug(" ssh_msg: done") return 1
# Connect GPG-Agent, and get list of KEYGRIPs. g = gpg_agent() g.read_line() # Greeting message g.send_command('KEYINFO --list --data\n') keyinfo_result = g.get_response() keygrip_list = get_keygrip_list(keyinfo_result) debug(keygrip_list) keylist = [] # For each KEYGRIP, get its PUBLIC-KEY. for kg in keygrip_list: g.send_command('READKEY %s\n' % kg) key = sexp(g.get_response()) # [ "public-key" [ "rsa" [ "n" MODULUS ] [ "e" EXPONENT] ] ] n = key[1][1][1] e = key[1][2][1] debug(binascii.hexlify(n)) debug(binascii.hexlify(e)) keylist.append([n, e, kg]) # FIXME: should handle all keys, not only a single key # FIXME: should support different key size n = keylist[0][0] e = keylist[0][1] keygrip = keylist[0][2] ssh_rsa_public_blob = "\x00\x00\x00\x07ssh-rsa" + \ "\x00\x00\x00\x03" + e + "\x00\x00\x01\x01" + n
def OnCopyData(self, hwnd, msg, wparam, lparam): debug("WM_COPYDATA message") debug(" window=%08x" % hwnd) debug(" msg =%08x" % msg) debug(" wparam=%08x" % wparam) pCDS = ctypes.cast(lparam, P_COPYDATA) debug(" dwData=%08x" % (pCDS.contents.dwData & 0xffffffff)) debug(" len=%d" % pCDS.contents.cbData) mapname = ctypes.string_at(pCDS.contents.lpData) debug(" mapname='%s'" % ctypes.string_at(pCDS.contents.lpData)) hMapObject = ctypes.windll.kernel32.OpenFileMappingA(FILE_MAP_ALL_ACCESS, 0, mapname) if hMapObject == 0: debug("error on OpenFileMapping") return 0 pBuf = ctypes.windll.kernel32.MapViewOfFile(hMapObject, FILE_MAP_ALL_ACCESS, 0, 0, 0) if pBuf == 0: ctypes.windll.kernel32.CloseHandle(hMapObject) debug("error on MapViewOfFile") return 0 pSshMsg = ctypes.cast(pBuf, P_SSH_MSG_HEAD) debug(" ssh_msg_len: %d" % pSshMsg.contents.msg_len) debug(" ssh_msg_type: %d" % pSshMsg.contents.msg_type) if pSshMsg.contents.msg_type == 11: # SSH2_AGENT_REQUEST_IDENTITIES blob_len = len(ssh_rsa_public_blob) cmnt_len = len(ssh_key_comment) pAns = ctypes.cast(pBuf, P_SSH_MSG_ID_ANSWER) pAns.contents.msg_len = 1+4+4+blob_len+4+cmnt_len pAns.contents.msg_type = 12 # SSH2_AGENT_IDENTITIES_ANSWER pAns.contents.keys = 1 ctypes.memmove(pBuf+4+1+4, pack('>I', blob_len), 4) ctypes.memmove(pBuf+4+1+4+4, ssh_rsa_public_blob, blob_len) ctypes.memmove(pBuf+4+1+4+4+blob_len, pack('>I', cmnt_len), 4) ctypes.memmove(pBuf+4+1+4+4+blob_len+4, ssh_key_comment, cmnt_len) debug("answer is:") debug(" ssh_msg_len: %d" % pSshMsg.contents.msg_len) debug(" ssh_msg_type: %d" % pSshMsg.contents.msg_type) elif pSshMsg.contents.msg_type == 13: # SSH2_AGENT_SIGN_REQUEST req_blob_len = unpack(">I", ctypes.string_at(pBuf+5, 4))[0] req_blob = ctypes.string_at(pBuf+5+4, req_blob_len) req_data_len = unpack(">I", ctypes.string_at(pBuf+5+4+req_blob_len,4))[0] req_data = ctypes.string_at(pBuf+5+4+req_blob_len+4,req_data_len) debug(" blob_len=%d" % req_blob_len) debug(" data_len=%d" % req_data_len) hash = hashlib.sha1(req_data).hexdigest() debug(" hash=%s" % hash) g.send_command('SIGKEY %s\n' % keygrip) g.send_command('SETHASH --hash=sha1 %s\n' % hash) g.send_command('PKSIGN\n') sig = sexp(g.get_response()) # [ "sig-val" [ "rsa" [ "s" "xxx" ] ] ] sig = sig[1][1][1] sig = "\x00\x00\x00\x07" + "ssh-rsa" + "\x00\x00\x01\x00" + sig # FIXME: should support different key size siglen = len(sig) debug("sig_len=%d" % siglen) debug("sig=%s" % binascii.hexlify(sig)) pRes = ctypes.cast(pBuf, P_SSH_MSG_SIGN_RESPONSE) pRes.contents.msg_len = 1+4+siglen pRes.contents.msg_type = 14 # SSH2_AGENT_SIGN_RESPONSE pRes.contents.sig_len = siglen ctypes.memmove(pBuf+4+1+4, sig, siglen) debug("answer is:") debug(" ssh_msg_len: %d" % pSshMsg.contents.msg_len) debug(" ssh_msg_type: %d" % pSshMsg.contents.msg_type) else: exit(0) ctypes.windll.kernel32.UnmapViewOfFile(pBuf) ctypes.windll.kernel32.CloseHandle(hMapObject) debug(" ssh_msg: done") return 1