def connect(self): """Enumerate and connect to the first USB HID interface.""" try: return comm.getDongle() except comm.CommException as e: raise interface.NotFoundError( '{} not connected: "{}"'.format(self, e))
def handleSignRequest(message, key, eddsa, path): logging.debug("Sign request") blobSize = struct.unpack(">I", message[0:4])[0] blob = message[4 : 4 + blobSize] if blob <> key: logging.debug("Client sent a different blob " + blob.encode('hex')) return chr(SSH_AGENT_FAILURE) challengeSize = struct.unpack(">I", message[4 + blobSize : 4 + blobSize + 4])[0] challenge = message[4 + blobSize + 4: 4 + blobSize + 4 + challengeSize] # Send the challenge in chunks dongle = getDongle(logging.getLogger().isEnabledFor(logging.DEBUG)) donglePath = parse_bip32_path(args.path) offset = 0 while offset <> len(challenge): data = "" if offset == 0: donglePath = parse_bip32_path(path) data = chr(len(donglePath) / 4) + donglePath if (len(challenge) - offset) > (255 - len(data)): chunkSize = (255 - len(data)) else: chunkSize = len(challenge) - offset data += challenge[offset : offset + chunkSize] if offset == 0: p1 = 0x00 else: p1 = 0x01 if eddsa: p2 = 0x02 else: p2 = 0x01 offset += chunkSize apdu = "8004".decode('hex') + chr(p1) + chr(p2) + chr(len(data)) + data signature = dongle.exchange(bytes(apdu)) dongle.close() # Parse r and s rLength = signature[3] r = signature[4 : 4 + rLength] sLength = signature[4 + rLength + 1] s = signature[4 + rLength + 2:] r = str(r) s = str(s) encodedSignatureValue = struct.pack(">I", len(r)) + r encodedSignatureValue += struct.pack(">I", len(s)) + s encodedSignature = struct.pack(">I", len(SIG_HEADER)) + SIG_HEADER encodedSignature += struct.pack(">I", len(encodedSignatureValue)) + encodedSignatureValue response = chr(SSH2_AGENT_SIGN_RESPONSE) response += struct.pack(">I", len(encodedSignature)) + encodedSignature return response
if args.path == None: args.path = "44'/535348'/0'/0/0" if args.ed25519: p2 = "02" keyHeader = KEY_HEADER_ED25519 else: p2 = "01" keyHeader = KEY_HEADER donglePath = parse_bip32_path(args.path) apdu = "800200" + p2 apdu = apdu.decode('hex') + chr(len(donglePath) + 1) + chr(len(donglePath) / 4) + donglePath dongle = getDongle(True) result = dongle.exchange(bytes(apdu)) key = str(result[1:]) blob = struct.pack(">I", len(KEY_HEADER)) + keyHeader if args.ed25519: keyX = bytearray(key[0:32]) keyY = bytearray(key[32:][::-1]) if ((keyX[31] & 1)<>0): keyY[31] |= 0x80 key = str(keyY) else: blob += struct.pack(">I", len(CURVE_NAME)) + CURVE_NAME blob += struct.pack(">I", len(key)) + key print keyHeader + " " + base64.b64encode(blob)
* * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. ******************************************************************************** """ from ledgerblue.comm import getDongle import argparse def auto_int(x): return int(x, 0) parser = argparse.ArgumentParser() parser.add_argument("--fileName", help="Set the file name to load") parser.add_argument("--apdu", help="Display APDU log", action='store_true') args = parser.parse_args() if args.fileName == None: raise Exception("Missing fileName") dongle = getDongle(args.apdu) file = open(args.fileName, "r") for data in file: data = data.rstrip('\r\n').decode('hex') dongle.exchange(bytearray(data))
import struct path = args.from_addr donglePath = b'' for pathElement in path.split('/'): element = pathElement.split('\'') if len(element) == 1: donglePath += struct.pack(">I", int(element[0])) else: donglePath += struct.pack(">I", 0x80000000 | int(element[0])) apdu = bytes.fromhex('e0020000') apdu += bytes([len(donglePath) + 1]) apdu += bytes([len(donglePath) // 4]) apdu += donglePath result = getDongle(True).exchange(apdu) offset = 1 + result[0] address = result[offset + 1 : offset + 1 + result[offset]] from_addr = "0x" + str(address.decode('ascii')).lower() if args.keytype == 'file': from_addr = args.from_addr # Check address validity if not web3.isAddress(from_addr): raise Exception('Invalid address %s' % from_addr) if not web3.isAddress(args.to_addr): raise Exception('Invalid address %s' % args.to_addr) # Fetch nonce from the blockchain if args.nonce < 0:
parser.add_argument("--apdu", help="Display APDU log", action='store_true') parser.add_argument("--perso", help="Personalization key reference to use") parser.add_argument("--firmware", help="Firmware reference to use") parser.add_argument("--firmwareKey", help="Firmware reference key to use") args = parser.parse_args() if args.url == None: raise Exception("No URL specified") if args.perso == None: raise Exception("No personalization specified") if args.firmware == None: raise Exception("No firmware specified") if args.firmwareKey == None: raise Exception("No firmware key specified") dongle = getDongle(args.apdu) # Identify targetid = bytearray(struct.pack('>I', 0x31000001)) apdu = bytearray([0xe0, 0x04, 0x00, 0x00]) + bytearray([len(targetid) ]) + targetid dongle.exchange(apdu) # Initialize chain dongle.exchange(bytearray.fromhex('E050000000')) # Get remote certificate request = Request()
def clear_online_seed(lang): print("Open device...") dongle = getDongle(False) print("Erase old key words...") dongle.exchange(pack('>6B', 0x00, 0x28, 0x02, 0x00, 0x01, 0x00))
try: # Send the APDU Payloads in (N)Chunks for i in range(chunkCount): if chunks[i] is not None: hasMoreChunks = chunks[i + 1] is not None p1 = p1_single if chunkCount == 1 \ else p1_first if i == 0 and hasMoreChunks \ else p1_more if hasMoreChunks else p1_last apdu = bytearray.fromhex(cla + operation + p1 + p2) if i == 0: apdu.append(pathLength + len(chunks[0])) apdu.append(pathLength // 4) apdu += donglePath + chunks[0] dongle = getDongle(True) else: apdu.append(len(chunks[i])) apdu += chunks[i] result = dongle.exchange(bytes(apdu)) if len(result) == 0: print("Sending next APDU Chunk..") else: print( "\nPayload:", binascii.hexlify(payload).decode("utf-8") ) print("\nApproved by user on Path:", args.path, "\n") print(
def exchange(apdu): dongle = getDongle(True) return dongle.exchange(apdu)
def __enter__(self): self.d = getDongle(debug=DEBUG) return self.d
def point_mul(P, n): R = None for i in range(N): if ((n >> i) & 1): R = point_add(R, P) P = point_add(P, P) return R textToSign = b'' while True: data = input('Enter text to sign, end with an empty line : ') if len(data) == 0: break textToSign += data.encode() + b'\n' dongle = getDongle(True) # True here means debug is on try: publicKey = dongle.exchange(bytes.fromhex('8004000000')) except: if comm.sw == 0x6804: raise RuntimeError('Invalid status from Ledger: %x. Is the device unlocked?' % comm.sw) print('publicKey ', publicKey.hex()) try: offset = 0 while offset != len(textToSign): if (len(textToSign) - offset) > 255: chunk = textToSign[offset : offset + 255] else: chunk = textToSign[offset:]
def get_dongle(): global dongle if dongle is None: dongle = getDongle(True) return dongle
from ledgerblue.comm import getDongle from tx_pb2 import Transaction import struct input_1 = Transaction.Input(input_tx_hash=bytes.fromhex( "ac3c7f1938e9bb4e04f296eb7b1d13758e904dcecf352bc5349eda43c84ebbc6"), input_index=0) output_0 = Transaction.Output(dest_addr=bytes.fromhex( "05c829a6b0ec3df93dac8c07d6b947ee99c4ff103d1b303894"), amount=79798) message = "https://bit.ly/32hI7ly" tx = Transaction(inputs=[input_1, input_1, input_1, input_1], outputs=[output_0, output_0, output_0, output_0, output_0], msg=message) # prefix buffer with its size request = struct.pack(">H", len( tx.SerializeToString())) + tx.SerializeToString() dongle = getDongle(debug=True) apdu = bytes.fromhex("e0020000") chunkSize = 200 for chunk in [ request[i:i + chunkSize] for i in range(0, len(request), chunkSize) ]: capdu = apdu + struct.pack('B', len(chunk)) + chunk response = dongle.exchange(bytes(capdu)) apdu = apdu[:2] + struct.pack('B', apdu[2] | 0x80) + apdu[3:]
import ed25519 import msgpack import base64 import sha512_256 import sys import os import struct import algomsgpack def checksummed(pk): sum = sha512_256.new(str(pk)).digest() return base64.b32encode(pk + sum[28:32]).replace("=", "") dongle = getDongle(debug=False) publicKey = dongle.exchange(bytes("8003000000".decode('hex'))) print "Ledger app address:", checksummed(publicKey) if len(sys.argv) != 3: print "Usage: %s infile outfile" % sys.argv[0] sys.exit(0) (_, infile, outfile) = sys.argv with open(infile) as f: buf = f.read() instx = msgpack.unpackb(buf, raw=False) intx = instx['txn']
def __init__(self): self.dongle = getDongle(debug=False)