mirror of
https://github.com/trezor/trezor-firmware.git
synced 2024-11-14 03:30:02 +00:00
Tool for digitally signing the config for Trezor browser plugin
This commit is contained in:
parent
d18ad92fc1
commit
e410acad0a
29
protob/config.proto
Normal file
29
protob/config.proto
Normal file
@ -0,0 +1,29 @@
|
||||
//
|
||||
// This file defines the configuration format for initializing the
|
||||
// Trezor browser plugin.
|
||||
//
|
||||
|
||||
import "google/protobuf/descriptor.proto";
|
||||
|
||||
message DeviceDescriptor {
|
||||
optional uint32 vendor_id = 1;
|
||||
optional uint32 product_id = 2;
|
||||
optional bytes serial_number = 3;
|
||||
optional bytes path = 4;
|
||||
}
|
||||
|
||||
message Configuration {
|
||||
// regexes of allowed/forbidden urls
|
||||
repeated bytes whitelist_urls = 1;
|
||||
repeated bytes blacklist_urls = 2;
|
||||
|
||||
// compiled specification of the wire protocol, serialized
|
||||
// FileDescriptorSet can be generated with `protoc -o`
|
||||
required google.protobuf.FileDescriptorSet wire_protocol = 3;
|
||||
|
||||
// descriptors of allowed devices
|
||||
repeated DeviceDescriptor known_devices = 4;
|
||||
|
||||
// timestamp of expiration
|
||||
optional int32 valid_until = 5;
|
||||
}
|
4
signer/.gitignore
vendored
Normal file
4
signer/.gitignore
vendored
Normal file
@ -0,0 +1,4 @@
|
||||
config_pb2.py
|
||||
config_pb2.pyc
|
||||
config_signed.bin
|
||||
*.pem
|
15
signer/config.json
Normal file
15
signer/config.json
Normal file
@ -0,0 +1,15 @@
|
||||
{
|
||||
"whitelist_urls": [
|
||||
".*",
|
||||
"file://.*",
|
||||
"https?://.*\\.mytrezor\\.com\\/.*",
|
||||
"https?://mytrezor\\.com\\/.*"
|
||||
],
|
||||
"blacklist_urls": [
|
||||
],
|
||||
"known_devices": [
|
||||
["0x534c", "0x0001", "Trezor"],
|
||||
["0x10c4", "0xea80", "Trezor Shield"]
|
||||
],
|
||||
"valid_days": 15
|
||||
}
|
6
signer/sample.key
Normal file
6
signer/sample.key
Normal file
@ -0,0 +1,6 @@
|
||||
-----BEGIN EC PRIVATE KEY-----
|
||||
MHQCAQEEIBKl1isjNeP4S5uP5S9LI3RZu6+hNQRxO10IGTd8JBq3oAcGBSuBBAAK
|
||||
oUQDQgAENEoHRLyHw1AM5jl0pbUNgXHFldzn1jWT/tGrlePY/vfKVVc2QM2pz0fb
|
||||
YUn4WEZC8DDfQ3XEhvKnsyOotsY7QQ==
|
||||
-----END EC PRIVATE KEY-----
|
||||
|
100
signer/sign.py
Executable file
100
signer/sign.py
Executable file
@ -0,0 +1,100 @@
|
||||
#!/usr/bin/python
|
||||
import subprocess
|
||||
import os
|
||||
import json
|
||||
import time
|
||||
import ecdsa
|
||||
import hashlib
|
||||
import binascii
|
||||
from google.protobuf.descriptor_pb2 import FileDescriptorSet
|
||||
|
||||
PROTOBUF_PROTO_DIR=os.environ.get('PROTOBUF_PROTO_DIR', '/usr/include/')
|
||||
TREZOR_PROTO_DIR=os.environ.get('TREZOR_PROTO_DIR', '../protob/')
|
||||
|
||||
def compile_config():
|
||||
cmd = "protoc --python_out=../signer/ -I" + PROTOBUF_PROTO_DIR + " -I./ config.proto"
|
||||
subprocess.check_call(cmd.split(), cwd=TREZOR_PROTO_DIR)
|
||||
|
||||
def parse_json():
|
||||
return json.loads(open('config.json', 'r').read())
|
||||
|
||||
|
||||
def get_compiled_proto():
|
||||
# Compile trezor.proto to binary format
|
||||
pdir = os.path.abspath(TREZOR_PROTO_DIR)
|
||||
pfile = os.path.join(pdir, "messages.proto")
|
||||
cmd = "protoc --include_imports -I" + PROTOBUF_PROTO_DIR + " -I" + pdir + " " + pfile + " -otrezor.bin"
|
||||
|
||||
subprocess.check_call(cmd.split())
|
||||
|
||||
# Load compiled protocol description to string
|
||||
proto = open('trezor.bin', 'r').read()
|
||||
os.unlink('trezor.bin')
|
||||
|
||||
# Parse it into FileDescriptorSet structure
|
||||
compiled = FileDescriptorSet()
|
||||
compiled.ParseFromString(proto)
|
||||
return compiled
|
||||
|
||||
def compose_message(json, proto):
|
||||
import config_pb2
|
||||
|
||||
cfg = config_pb2.Configuration()
|
||||
cfg.valid_until = int(time.time()) + json['valid_days'] * 3600 * 24
|
||||
cfg.wire_protocol.MergeFrom(proto)
|
||||
|
||||
for url in json['whitelist_urls']:
|
||||
cfg.whitelist_urls.append(str(url))
|
||||
|
||||
for url in json['blacklist_urls']:
|
||||
cfg.blacklist_urls.append(str(url))
|
||||
|
||||
for dev in json['known_devices']:
|
||||
desc = cfg.known_devices.add()
|
||||
desc.vendor_id = int(dev[0], 16)
|
||||
desc.product_id = int(dev[1], 16)
|
||||
|
||||
return cfg.SerializeToString()
|
||||
|
||||
def sign_message(data, key_pem):
|
||||
# curve = ecdsa.curves.SECP256k1
|
||||
# x = ecdsa.keys.SigningKey.generate(curve=curve)
|
||||
key = ecdsa.keys.SigningKey.from_pem(key_pem)
|
||||
|
||||
verify = key.get_verifying_key()
|
||||
print "Verifying key:"
|
||||
print verify.to_pem()
|
||||
|
||||
return key.sign_deterministic(data, hashfunc=hashlib.sha256)
|
||||
|
||||
def pack_datafile(filename, signature, data):
|
||||
if len(signature) != 64:
|
||||
raise Exception("Signature must be 64 bytes long")
|
||||
|
||||
fp = open(filename, 'w')
|
||||
fp.write(binascii.hexlify(signature))
|
||||
fp.write(binascii.hexlify(data))
|
||||
fp.close()
|
||||
|
||||
print "Signature and data stored to", filename
|
||||
|
||||
if __name__ == '__main__':
|
||||
key_pem = ''
|
||||
print "Paste ECDSA private key (in PEM format) and press Enter:"
|
||||
while True:
|
||||
inp = raw_input()
|
||||
if inp == '':
|
||||
break
|
||||
|
||||
key_pem += inp + "\n"
|
||||
|
||||
# key_pem = open('sample.key', 'r').read()
|
||||
|
||||
compile_config()
|
||||
json = parse_json()
|
||||
proto = get_compiled_proto()
|
||||
|
||||
data = compose_message(json, proto)
|
||||
signature = sign_message(data, key_pem)
|
||||
|
||||
pack_datafile('config_signed.bin', signature, data)
|
Loading…
Reference in New Issue
Block a user