def __init__( self, credentials: Dict, url: str, conn_type: Type[ClientConnection], client_type: Type[Client], ) -> None: # Use Server metadata # to build client route self.conn = conn_type(url=url) # type: ignore self.client_type = client_type if credentials: metadata, _user_key = self.conn.login(credentials=credentials) # type: ignore _user_key = SigningKey(_user_key.encode("utf-8"), encoder=HexEncoder) else: metadata = self.conn._get_metadata() # type: ignore if not user_key: _user_key = SigningKey.generate() else: _user_key = user_key ( spec_location, name, client_id, ) = self.client_type.deserialize_client_metadata_from_node( metadata=metadata ) # Create a new Solo Route using the selected connection type route = SoloRoute(destination=spec_location, connection=self.conn) location_args = self.__route_client_location( client_type=self.client_type, location=spec_location ) self.proxy_address: Optional[Address] = None # Create a new client using the selected client type super().__init__( network=location_args[NetworkClient], domain=location_args[DomainClient], device=location_args[DeviceClient], vm=location_args[VirtualMachineClient], name=name, routes=[route], signing_key=_user_key, ) self.groups = GroupRequestAPI(send=self.__perform_grid_request) self.users = UserRequestAPI(send=self.__perform_grid_request) self.roles = RoleRequestAPI(send=self.__perform_grid_request) self.workers = WorkerRequestAPI( send=self.__perform_grid_request, domain_client=self ) self.association_requests = AssociationRequestAPI( send=self.__perform_grid_request )
class Account: def __init__(self, private_key, address=None, sequence_number=0): self._signing_key = SigningKey(private_key) self._verify_key = self._signing_key.verify_key shazer = new_sha3_256() shazer.update(self._verify_key.encode()) if address is None: self.address = shazer.digest() else: self.address = Address.normalize_to_bytes(address) self.sequence_number = sequence_number self.status = AccountStatus.Local def json_print_fields(self): return ["address", "private_key", "public_key"] @classmethod def faucet_account(cls, private_key): return cls(private_key, AccountConfig.association_address()) @classmethod def gen_faucet_account(cls, faucet_account_file): if faucet_account_file is None: faucet_account_file = cls.faucet_file_path() with open(faucet_account_file, 'rb') as f: data = f.read() assert len(data) == 80 assert b' \x00\x00\x00\x00\x00\x00\x00' == data[0:8] assert b' \x00\x00\x00\x00\x00\x00\x00' == data[40:48] private_key = data[8:40] public_key = data[48:] return cls.faucet_account(private_key) @classmethod def faucet_file_path(cls): curdir = os.path.dirname(libra.__file__) return os.path.abspath((os.path.join(curdir, "faucet_key_for_test"))) def sign(self, message): return self._signing_key.sign(message) @property def address_hex(self): return self.address.hex() @property def public_key(self): return self._verify_key.encode() @property def private_key(self): return self._signing_key.encode() @property def public_key_hex(self): return self.public_key.hex() @property def private_key_hex(self): return self.private_key.hex()
class Account: def __init__(self, private_key, sequence_number=0): self._signing_key = SigningKey(private_key) self._verify_key = self._signing_key.verify_key shazer = new_sha3_256() shazer.update(self._verify_key.encode()) self.address = shazer.digest() self.sequence_number = sequence_number self.status = AccountStatus.Local def sign(self, message): return self._signing_key.sign(message) @property def address_hex(self): return self.address.hex() @property def public_key(self): return self._verify_key.encode() @property def private_key(self): return self._signing_key.encode() @property def public_key_hex(self): return self.public_key.hex() @property def private_key_hex(self): return self.private_key.hex()
def save_signing_key(self, signing_key: SigningKey): # Save the signing key file = open( os.path.join( self.location, signing_key.verify_key.encode(Base32Encoder).decode("utf-8")), 'wb') file.write(signing_key.encode()) file.close()
def blinded_ed25519_signature(message_parts, s: SigningKey, d: bytes, D: bytes): H_rh = sha512(s.encode()).digest()[32:] r = sodium.crypto_core_ed25519_scalar_reduce( sha512_multipart(H_rh, D, message_parts)) sig_R = sodium.crypto_scalarmult_ed25519_base_noclamp(r) HRAM = sodium.crypto_core_ed25519_scalar_reduce( sha512_multipart(sig_R, D, message_parts)) sig_s = sodium.crypto_core_ed25519_scalar_add( r, sodium.crypto_core_ed25519_scalar_mul(HRAM, d)) return sig_R + sig_s
class Account(object): def __init__(self, private_key): self._signing_key = SigningKey(bytes.fromhex(private_key)) self._verify_key = self._signing_key.verify_key shazer = sha3_256() shazer.update(self._verify_key.encode()) self.address = shazer.digest().hex() def sign(self, message): return self._signing_key.sign(message) @property def public_key(self): return self._verify_key.encode().hex() @property def private_key(self): return self._signing_key.encode().hex()
class Account: def __init__(self, private_key): self._signing_key = SigningKey(bytes.fromhex(private_key)) self._verify_key = self._signing_key.verify_key m = create_hasher() m.update(self._verify_key.encode()) self.address = m.digest().hex() def sign(self, message): return self._signing_key.sign(message) @property def public_key(self): return self._verify_key.encode().hex() @property def private_key(self): return self._signing_key.encode().hex()
def maybe_generate_key(log, cbdir, privkey_path=u'key.priv', pubkey_path=u'key.pub'): if not HAS_NACL: log.warn("Skipping node key generation - NaCl package not installed!") return from nacl.signing import SigningKey from nacl.encoding import HexEncoder privkey = None pubkey = None privkey_path = os.path.join(cbdir, privkey_path) pubkey_path = os.path.join(cbdir, pubkey_path) if os.path.exists(privkey_path): # node private key seems to exist already .. check! tags = _parse_keyfile(privkey_path, private=True) if u'private-key-ed25519' not in tags: raise Exception("Node private key file lacks a 'private-key-ed25519' tag!") privkey = tags[u'private-key-ed25519'] # recreate a signing key from the base64 encoding privkey_obj = SigningKey(privkey, encoder=HexEncoder) pubkey = privkey_obj.verify_key.encode(encoder=HexEncoder).decode('ascii') # confirm we have the public key in the file, and that it is # correct if u'public-key-ed25519' in tags: if tags[u'public-key-ed25519'] != pubkey: raise Exception( ("Inconsistent key file '{}': 'public-key-ed25519' doesn't" " correspond to private-key-ed25519").format(privkey_path) ) log.debug("Node key already exists (public key: {})".format(pubkey)) if os.path.exists(pubkey_path): pubtags = _parse_keyfile(pubkey_path, private=False) if u'public-key-ed25519' not in pubtags: raise Exception( ("Pubkey file '{}' exists but lacks 'public-key-ed25519'" " tag").format(pubkey_path) ) if pubtags[u'public-key-ed25519'] != pubkey: raise Exception( ("Inconsistent key file '{}': 'public-key-ed25519' doesn't" " correspond to private-key-ed25519").format(pubkey_path) ) else: log.info("'{}' not found; re-creating from '{}'".format(pubkey_path, privkey_path)) tags = OrderedDict([ (u'creator', _creator()), (u'created-at', utcnow()), (u'machine-id', _machine_id()), (u'public-key-ed25519', pubkey), ]) msg = u'Crossbar.io public key for node authentication\n\n' _write_node_key(pubkey_path, tags, msg) else: # node private key does NOT yet exist: generate one privkey_obj = SigningKey.generate() privkey = privkey_obj.encode(encoder=HexEncoder).decode('ascii') pubkey = privkey_obj.verify_key.encode(encoder=HexEncoder).decode('ascii') # first, write the public file tags = OrderedDict([ (u'creator', _creator()), (u'created-at', utcnow()), (u'machine-id', _machine_id()), (u'public-key-ed25519', pubkey), ]) msg = u'Crossbar.io public key for node authentication\n\n' _write_node_key(pubkey_path, tags, msg) # now, add the private key and write the private file tags[u'private-key-ed25519'] = privkey msg = u'Crossbar.io private key for node authentication - KEEP THIS SAFE!\n\n' _write_node_key(privkey_path, tags, msg) log.info("New node key generated!") return pubkey
def maybe_generate_key(self, cbdir, privkey_path=u'key.priv', pubkey_path=u'key.pub'): privkey_path = os.path.join(cbdir, privkey_path) pubkey_path = os.path.join(cbdir, pubkey_path) if os.path.exists(privkey_path): # node private key seems to exist already .. check! priv_tags = _parse_keyfile(privkey_path, private=True) for tag in [ u'creator', u'created-at', u'machine-id', u'public-key-ed25519', u'private-key-ed25519' ]: if tag not in priv_tags: raise Exception( "Corrupt node private key file {} - {} tag not found". format(privkey_path, tag)) privkey_hex = priv_tags[u'private-key-ed25519'] privkey = SigningKey(privkey_hex, encoder=HexEncoder) pubkey = privkey.verify_key pubkey_hex = pubkey.encode(encoder=HexEncoder).decode('ascii') if priv_tags[u'public-key-ed25519'] != pubkey_hex: raise Exception(( "Inconsistent node private key file {} - public-key-ed25519 doesn't" " correspond to private-key-ed25519").format(pubkey_path)) if os.path.exists(pubkey_path): pub_tags = _parse_keyfile(pubkey_path, private=False) for tag in [ u'creator', u'created-at', u'machine-id', u'public-key-ed25519' ]: if tag not in pub_tags: raise Exception( "Corrupt node public key file {} - {} tag not found" .format(pubkey_path, tag)) if pub_tags[u'public-key-ed25519'] != pubkey_hex: raise Exception(( "Inconsistent node public key file {} - public-key-ed25519 doesn't" " correspond to private-key-ed25519" ).format(pubkey_path)) else: self.log.info( "Node public key file {pub_path} not found - re-creating from node private key file {priv_path}", pub_path=pubkey_path, priv_path=privkey_path, ) pub_tags = OrderedDict([ (u'creator', priv_tags[u'creator']), (u'created-at', priv_tags[u'created-at']), (u'machine-id', priv_tags[u'machine-id']), (u'public-key-ed25519', pubkey_hex), ]) msg = u'Crossbar.io node public key\n\n' _write_node_key(pubkey_path, pub_tags, msg) self.log.debug("Node key already exists (public key: {hex})", hex=pubkey_hex) else: # node private key does not yet exist: generate one privkey = SigningKey.generate() privkey_hex = privkey.encode(encoder=HexEncoder).decode('ascii') pubkey = privkey.verify_key pubkey_hex = pubkey.encode(encoder=HexEncoder).decode('ascii') # first, write the public file tags = OrderedDict([ (u'creator', _creator()), (u'created-at', utcnow()), (u'machine-id', _machine_id()), (u'public-key-ed25519', pubkey_hex), ]) msg = u'Crossbar.io node public key\n\n' _write_node_key(pubkey_path, tags, msg) # now, add the private key and write the private file tags[u'private-key-ed25519'] = privkey_hex msg = u'Crossbar.io node private key - KEEP THIS SAFE!\n\n' _write_node_key(privkey_path, tags, msg) self.log.info("New node key pair generated!") # fix file permissions on node public/private key files # note: we use decimals instead of octals as octal literals have changed between Py2/3 # if os.stat(pubkey_path ).st_mode & 511 != 420: # 420 (decimal) == 0644 (octal) os.chmod(pubkey_path, 420) self.log.info("File permissions on node public key fixed!") if os.stat(privkey_path ).st_mode & 511 != 384: # 384 (decimal) == 0600 (octal) os.chmod(privkey_path, 384) self.log.info("File permissions on node private key fixed!") self._node_key = cryptosign.SigningKey(privkey) return pubkey_hex
def set_sk_from_encoded_seed(context, sk_enc): seed = base64.b64decode(sk_enc) key = SigningKey(seed) private_key = base64.b64encode(key.encode() + key.verify_key.encode()).decode() context.sk = private_key
def maybe_generate_key(self, cbdir, privkey_path=u'key.priv', pubkey_path=u'key.pub'): privkey_path = os.path.join(cbdir, privkey_path) pubkey_path = os.path.join(cbdir, pubkey_path) if os.path.exists(privkey_path): # node private key seems to exist already .. check! priv_tags = _parse_keyfile(privkey_path, private=True) for tag in [u'creator', u'created-at', u'machine-id', u'public-key-ed25519', u'private-key-ed25519']: if tag not in priv_tags: raise Exception("Corrupt node private key file {} - {} tag not found".format(privkey_path, tag)) privkey_hex = priv_tags[u'private-key-ed25519'] privkey = SigningKey(privkey_hex, encoder=HexEncoder) pubkey = privkey.verify_key pubkey_hex = pubkey.encode(encoder=HexEncoder).decode('ascii') if priv_tags[u'public-key-ed25519'] != pubkey_hex: raise Exception( ("Inconsistent node private key file {} - public-key-ed25519 doesn't" " correspond to private-key-ed25519").format(pubkey_path) ) if os.path.exists(pubkey_path): pub_tags = _parse_keyfile(pubkey_path, private=False) for tag in [u'creator', u'created-at', u'machine-id', u'public-key-ed25519']: if tag not in pub_tags: raise Exception("Corrupt node public key file {} - {} tag not found".format(pubkey_path, tag)) if pub_tags[u'public-key-ed25519'] != pubkey_hex: raise Exception( ("Inconsistent node public key file {} - public-key-ed25519 doesn't" " correspond to private-key-ed25519").format(pubkey_path) ) else: self.log.info( "Node public key file {pub_path} not found - re-creating from node private key file {priv_path}", pub_path=pubkey_path, priv_path=privkey_path, ) pub_tags = OrderedDict([ (u'creator', priv_tags[u'creator']), (u'created-at', priv_tags[u'created-at']), (u'machine-id', priv_tags[u'machine-id']), (u'public-key-ed25519', pubkey_hex), ]) msg = u'Crossbar.io node public key\n\n' _write_node_key(pubkey_path, pub_tags, msg) self.log.debug("Node key already exists (public key: {hex})", hex=pubkey_hex) else: # node private key does not yet exist: generate one privkey = SigningKey.generate() privkey_hex = privkey.encode(encoder=HexEncoder).decode('ascii') pubkey = privkey.verify_key pubkey_hex = pubkey.encode(encoder=HexEncoder).decode('ascii') # first, write the public file tags = OrderedDict([ (u'creator', _creator()), (u'created-at', utcnow()), (u'machine-id', _machine_id()), (u'public-key-ed25519', pubkey_hex), ]) msg = u'Crossbar.io node public key\n\n' _write_node_key(pubkey_path, tags, msg) # now, add the private key and write the private file tags[u'private-key-ed25519'] = privkey_hex msg = u'Crossbar.io node private key - KEEP THIS SAFE!\n\n' _write_node_key(privkey_path, tags, msg) self.log.info("New node key pair generated!") # fix file permissions on node public/private key files # note: we use decimals instead of octals as octal literals have changed between Py2/3 # if os.stat(pubkey_path).st_mode & 511 != 420: # 420 (decimal) == 0644 (octal) os.chmod(pubkey_path, 420) self.log.info("File permissions on node public key fixed!") if os.stat(privkey_path).st_mode & 511 != 384: # 384 (decimal) == 0600 (octal) os.chmod(privkey_path, 384) self.log.info("File permissions on node private key fixed!") self._node_key = cryptosign.SigningKey(privkey) return pubkey_hex
def maybe_generate_key(log, cbdir, privkey_path=u'node.key'): if not HAS_NACL: log.warn("Skipping node key generation - NaCl package not installed!") return from nacl.signing import SigningKey from nacl.encoding import HexEncoder privkey = None privkey_path = os.path.join(cbdir, privkey_path) if os.path.exists(privkey_path): # node private key seems to exist already .. check! if os.path.isfile(privkey_path): with open(privkey_path, 'r') as privkey_file: privkey = None # parse key file lines, looking for tag "ed25519-privkey" got_blankline = False for line in privkey_file.read().splitlines(): if line.strip() == '': got_blankline = True elif got_blankline: tag, value = line.split(':', 1) tag = tag.strip().lower() value = value.strip() if tag not in [ u'private-key-ed25519', u'public-key-ed25519', u'machine-id', u'created-at', u'creator' ]: raise Exception( "Invalid tag '{}' in node private key file {}". format(tag, privkey_path)) if tag == u'private-key-ed25519': privkey = value break if not privkey: raise Exception( "Node private key file lacks a 'ed25519-privkey' tag!") # recreate a signing key from the base64 encoding privkey_obj = SigningKey(privkey, encoder=HexEncoder) pubkey = privkey_obj.verify_key.encode( encoder=HexEncoder).decode('ascii') log.debug( "Node key already exists (public key: {})".format(pubkey)) else: raise Exception( "Node private key path '{}' exists, but isn't a file".format( privkey_path)) else: # node private key does NOT yet exist: generate one privkey_obj = SigningKey.generate() privkey = privkey_obj.encode(encoder=HexEncoder).decode('ascii') privkey_created_at = utcnow() pubkey = privkey_obj.verify_key.encode( encoder=HexEncoder).decode('ascii') # for informational purposes, try to get a machine unique id thing .. machine_id = None try: # why this? see: http://0pointer.de/blog/projects/ids.html with open('/var/lib/dbus/machine-id', 'r') as f: machine_id = f.read().strip() except: pass # for informational purposes, try to identify the creator (user@hostname) creator = None try: creator = u'{}@{}'.format(getpass.getuser(), socket.gethostname()) except: pass # write out the private key file with open(privkey_path, 'w') as privkey_file: privkey_file.write( u'Crossbar.io private key for node authentication - KEEP THIS SAFE!\n\n' ) if creator: privkey_file.write(u'creator: {}\n'.format(creator)) privkey_file.write(u'created-at: {}\n'.format(privkey_created_at)) if machine_id: privkey_file.write(u'machine-id: {}\n'.format(machine_id)) privkey_file.write(u'public-key-ed25519: {}\n'.format(pubkey)) privkey_file.write(u'private-key-ed25519: {}\n'.format(privkey)) # set file mode to read only for owner # 384 (decimal) == 0600 (octal) - we use that for Py2/3 reasons os.chmod(privkey_path, 384) log.info("New node key generated!") return pubkey
def _prepare_node_keys(self): from nacl.signing import SigningKey from nacl.encoding import HexEncoder # make sure CBDIR/.cdc exists # cdc_dir = os.path.join(self._cbdir, '.cdc') if os.path.isdir(cdc_dir): pass elif os.path.exists(cdc_dir): raise Exception(".cdc exists, but isn't a directory") else: os.mkdir(cdc_dir) self.log.info("CDC directory created") # load node ID, either from .cdc/node.id or from CDC_NODE_ID # def split_nid(nid_s): nid_c = nid_s.strip().split('@') if len(nid_c) != 2: raise Exception( "illegal node principal '{}' - must follow the form <node id>@<management realm>" .format(nid_s)) node_id, realm = nid_c # FIXME: regex check node_id and realm return node_id, realm nid_file = os.path.join(cdc_dir, 'node.id') node_id, realm = None, None if os.path.isfile(nid_file): with open(nid_file, 'r') as f: node_id, realm = split_nid(f.read()) elif os.path.exists(nid_file): raise Exception("{} exists, but isn't a file".format(nid_file)) else: if 'CDC_NODE_ID' in os.environ: node_id, realm = split_nid(os.environ['CDC_NODE_ID']) else: raise Exception( "Neither node ID file {} exists nor CDC_NODE_ID environment variable set" .format(nid_file)) # Load the node key, either from .cdc/node.key or from CDC_NODE_KEY. # The node key is a Ed25519 key in either raw format (32 bytes) or in # hex-encoded form (64 characters). # # Actually, what's loaded is not the secret Ed25519 key, but the _seed_ # for that key. Private keys are derived from this 32-byte (256-bit) # random seed value. It is thus the seed value which is sensitive and # must be protected. # skey_file = os.path.join(cdc_dir, 'node.key') skey = None if os.path.isfile(skey_file): # FIXME: check file permissions are 0600! # This value is read in here. skey_len = os.path.getsize(skey_file) if skey_len in (32, 64): with open(skey_file, 'r') as f: skey_seed = f.read() encoder = None if skey_len == 64: encoder = HexEncoder skey = SigningKey(skey_seed, encoder=encoder) self.log.info("Existing CDC node key loaded from {skey_file}.", skey_file=skey_file) else: raise Exception( "invalid node key length {} (key must either be 32 raw bytes or hex encoded 32 bytes, hence 64 byte char length)" ) elif os.path.exists(skey_file): raise Exception("{} exists, but isn't a file".format(skey_file)) else: skey = SigningKey.generate() skey_seed = skey.encode(encoder=HexEncoder) with open(skey_file, 'w') as f: f.write(skey_seed) # set file mode to read only for owner # 384 (decimal) == 0600 (octal) - we use that for Py2/3 reasons os.chmod(skey_file, 384) self.log.info("New CDC node key {skey_file} generated.", skey_file=skey_file) return realm, node_id, skey
def maybe_generate_key(log, cbdir, privkey_path=u'key.priv', pubkey_path=u'key.pub'): if not HAS_NACL: log.warn("Skipping node key generation - NaCl package not installed!") return from nacl.signing import SigningKey from nacl.encoding import HexEncoder privkey = None pubkey = None privkey_path = os.path.join(cbdir, privkey_path) pubkey_path = os.path.join(cbdir, pubkey_path) if os.path.exists(privkey_path): # node private key seems to exist already .. check! tags = _parse_keyfile(privkey_path, private=True) if u'private-key-ed25519' not in tags: raise Exception( "Node private key file lacks a 'private-key-ed25519' tag!") privkey = tags[u'private-key-ed25519'] # recreate a signing key from the base64 encoding privkey_obj = SigningKey(privkey, encoder=HexEncoder) pubkey = privkey_obj.verify_key.encode( encoder=HexEncoder).decode('ascii') # confirm we have the public key in the file, and that it is # correct if u'public-key-ed25519' in tags: if tags[u'public-key-ed25519'] != pubkey: raise Exception(( "Inconsistent key file '{}': 'public-key-ed25519' doesn't" " correspond to private-key-ed25519").format(privkey_path)) log.debug("Node key already exists (public key: {})".format(pubkey)) if os.path.exists(pubkey_path): pubtags = _parse_keyfile(pubkey_path, private=False) if u'public-key-ed25519' not in pubtags: raise Exception( ("Pubkey file '{}' exists but lacks 'public-key-ed25519'" " tag").format(pubkey_path)) if pubtags[u'public-key-ed25519'] != pubkey: raise Exception( ("Inconsistent key file '{}': 'public-key-ed25519' doesn't" " correspond to private-key-ed25519").format(pubkey_path)) else: log.info("'{}' not found; re-creating from '{}'".format( pubkey_path, privkey_path)) tags = OrderedDict([ (u'creator', _creator()), (u'created-at', utcnow()), (u'machine-id', _machine_id()), (u'public-key-ed25519', pubkey), ]) msg = u'Crossbar.io public key for node authentication\n\n' _write_node_key(pubkey_path, tags, msg) else: # node private key does NOT yet exist: generate one privkey_obj = SigningKey.generate() privkey = privkey_obj.encode(encoder=HexEncoder).decode('ascii') pubkey = privkey_obj.verify_key.encode( encoder=HexEncoder).decode('ascii') # first, write the public file tags = OrderedDict([ (u'creator', _creator()), (u'created-at', utcnow()), (u'machine-id', _machine_id()), (u'public-key-ed25519', pubkey), ]) msg = u'Crossbar.io public key for node authentication\n\n' _write_node_key(pubkey_path, tags, msg) # now, add the private key and write the private file tags[u'private-key-ed25519'] = privkey msg = u'Crossbar.io private key for node authentication - KEEP THIS SAFE!\n\n' _write_node_key(privkey_path, tags, msg) log.info("New node key generated!") return pubkey
format(sys.argv[0])) sys.exit(1) key_filename = sys.argv[1] input_filename = sys.argv[2] output_filename = sys.argv[3] # Open the private key file and read in the signing key bytes with open(key_filename, 'rb') as key_file: keydata_bytes = key_file.read() # Reconstruct the SigningKey instance from the serialized form signing_key = SigningKey(keydata_bytes, encoder=RawEncoder) # Print out the private Signing key signing_hex = signing_key.encode(encoder=HexEncoder) print(Fore.LIGHTBLUE_EX + 'the private key is {}'.format(signing_hex)) # Open the input file and read its data in as a message that we wish to sign with open(input_filename, 'rb') as msg_file: msg = msg_file.read() # Sign a message with the signing key - this also containes the original message at the end sig = signing_key.sign(msg) # Save the signature to an output file with open(output_filename, 'wb') as sig_file: sig_file.write(sig) print(Fore.GREEN + 'Saved signature to {!r} for message file {!r}'.format( output_filename, input_filename))
def _prepare_node_keys(self): from nacl.signing import SigningKey from nacl.encoding import HexEncoder # make sure CBDIR/.cdc exists # cdc_dir = os.path.join(self._cbdir, '.cdc') if os.path.isdir(cdc_dir): pass elif os.path.exists(cdc_dir): raise Exception(".cdc exists, but isn't a directory") else: os.mkdir(cdc_dir) self.log.info("CDC directory created") # load node ID, either from .cdc/node.id or from CDC_NODE_ID # def split_nid(nid_s): nid_c = nid_s.strip().split('@') if len(nid_c) != 2: raise Exception("illegal node principal '{}' - must follow the form <node id>@<management realm>".format(nid_s)) node_id, realm = nid_c # FIXME: regex check node_id and realm return node_id, realm nid_file = os.path.join(cdc_dir, 'node.id') node_id, realm = None, None if os.path.isfile(nid_file): with open(nid_file, 'r') as f: node_id, realm = split_nid(f.read()) elif os.path.exists(nid_file): raise Exception("{} exists, but isn't a file".format(nid_file)) else: if 'CDC_NODE_ID' in os.environ: node_id, realm = split_nid(os.environ['CDC_NODE_ID']) else: raise Exception("Neither node ID file {} exists nor CDC_NODE_ID environment variable set".format(nid_file)) # Load the node key, either from .cdc/node.key or from CDC_NODE_KEY. # The node key is a Ed25519 key in either raw format (32 bytes) or in # hex-encoded form (64 characters). # # Actually, what's loaded is not the secret Ed25519 key, but the _seed_ # for that key. Private keys are derived from this 32-byte (256-bit) # random seed value. It is thus the seed value which is sensitive and # must be protected. # skey_file = os.path.join(cdc_dir, 'node.key') skey = None if os.path.isfile(skey_file): # FIXME: check file permissions are 0600! # This value is read in here. skey_len = os.path.getsize(skey_file) if skey_len in (32, 64): with open(skey_file, 'r') as f: skey_seed = f.read() encoder = None if skey_len == 64: encoder = HexEncoder skey = SigningKey(skey_seed, encoder=encoder) self.log.info("Existing CDC node key loaded from {skey_file}.", skey_file=skey_file) else: raise Exception("invalid node key length {} (key must either be 32 raw bytes or hex encoded 32 bytes, hence 64 byte char length)") elif os.path.exists(skey_file): raise Exception("{} exists, but isn't a file".format(skey_file)) else: skey = SigningKey.generate() skey_seed = skey.encode(encoder=HexEncoder) with open(skey_file, 'w') as f: f.write(skey_seed) # set file mode to read only for owner # 384 (decimal) == 0600 (octal) - we use that for Py2/3 reasons os.chmod(skey_file, 384) self.log.info("New CDC node key {skey_file} generated.", skey_file=skey_file) return realm, node_id, skey
def _load_and_maybe_generate(self, privkey_path, pubkey_path, yes_to_all=False): if os.path.exists(privkey_path): # node private key seems to exist already .. check! priv_tags = _parse_keyfile(privkey_path, private=True) for tag in [ u'creator', u'created-at', u'user-id', u'public-key-ed25519', u'private-key-ed25519' ]: if tag not in priv_tags: raise Exception( "Corrupt user private key file {} - {} tag not found". format(privkey_path, tag)) creator = priv_tags[u'creator'] created_at = priv_tags[u'created-at'] user_id = priv_tags[u'user-id'] privkey_hex = priv_tags[u'private-key-ed25519'] privkey = SigningKey(privkey_hex, encoder=HexEncoder) pubkey = privkey.verify_key pubkey_hex = pubkey.encode(encoder=HexEncoder).decode('ascii') if priv_tags[u'public-key-ed25519'] != pubkey_hex: raise Exception(( "Inconsistent user private key file {} - public-key-ed25519 doesn't" " correspond to private-key-ed25519").format(pubkey_path)) if os.path.exists(pubkey_path): pub_tags = _parse_keyfile(pubkey_path, private=False) for tag in [ u'creator', u'created-at', u'user-id', u'public-key-ed25519' ]: if tag not in pub_tags: raise Exception( "Corrupt user public key file {} - {} tag not found" .format(pubkey_path, tag)) if pub_tags[u'public-key-ed25519'] != pubkey_hex: raise Exception(( "Inconsistent user public key file {} - public-key-ed25519 doesn't" " correspond to private-key-ed25519" ).format(pubkey_path)) else: # public key is missing! recreate it pub_tags = OrderedDict([ (u'creator', priv_tags[u'creator']), (u'created-at', priv_tags[u'created-at']), (u'user-id', priv_tags[u'user-id']), (u'public-key-ed25519', pubkey_hex), ]) msg = u'Crossbar.io user public key\n\n' _write_node_key(pubkey_path, pub_tags, msg) click.echo( 'Re-created user public key from private key: {}'.format( style_ok(pubkey_path))) # click.echo('User public key loaded: {}'.format(style_ok(pubkey_path))) # click.echo('User private key loaded: {}'.format(style_ok(privkey_path))) else: # user private key does not yet exist: generate one creator = _creator(yes_to_all) created_at = utcnow() user_id = _user_id(yes_to_all) privkey = SigningKey.generate() privkey_hex = privkey.encode(encoder=HexEncoder).decode('ascii') pubkey = privkey.verify_key pubkey_hex = pubkey.encode(encoder=HexEncoder).decode('ascii') # first, write the public file tags = OrderedDict([ (u'creator', creator), (u'created-at', created_at), (u'user-id', user_id), (u'public-key-ed25519', pubkey_hex), ]) msg = u'Crossbar.io FX user public key\n\n' _write_node_key(pubkey_path, tags, msg) os.chmod(pubkey_path, 420) # now, add the private key and write the private file tags[u'private-key-ed25519'] = privkey_hex msg = u'Crossbar.io FX user private key - KEEP THIS SAFE!\n\n' _write_node_key(privkey_path, tags, msg) os.chmod(privkey_path, 384) click.echo('New user public key generated: {}'.format( style_ok(pubkey_path))) click.echo('New user private key generated ({}): {}'.format( style_error('keep this safe!'), style_ok(privkey_path))) # fix file permissions on node public/private key files # note: we use decimals instead of octals as octal literals have changed between Py2/3 if os.stat(pubkey_path ).st_mode & 511 != 420: # 420 (decimal) == 0644 (octal) os.chmod(pubkey_path, 420) click.echo( style_error('File permissions on user public key fixed!')) if os.stat(privkey_path ).st_mode & 511 != 384: # 384 (decimal) == 0600 (octal) os.chmod(privkey_path, 384) click.echo( style_error('File permissions on user private key fixed!')) # load keys into object self._creator = creator self._created_at = created_at self.user_id = user_id self._privkey = privkey self._privkey_hex = privkey_hex self._pubkey = pubkey self._pubkey_hex = pubkey_hex self.key = cryptosign.SigningKey(privkey)
def maybe_generate_key(log, cbdir, privkey_path=u'node.key'): if not HAS_NACL: log.warn("Skipping node key generation - NaCl package not installed!") return from nacl.signing import SigningKey from nacl.encoding import HexEncoder privkey = None privkey_path = os.path.join(cbdir, privkey_path) if os.path.exists(privkey_path): # node private key seems to exist already .. check! if os.path.isfile(privkey_path): with open(privkey_path, 'r') as privkey_file: privkey = None # parse key file lines, looking for tag "ed25519-privkey" got_blankline = False for line in privkey_file.read().splitlines(): if line.strip() == '': got_blankline = True elif got_blankline: tag, value = line.split(':', 1) tag = tag.strip().lower() value = value.strip() if tag not in [u'private-key-ed25519', u'public-key-ed25519', u'machine-id', u'created-at', u'creator']: raise Exception("Invalid tag '{}' in node private key file {}".format(tag, privkey_path)) if tag == u'private-key-ed25519': privkey = value break if not privkey: raise Exception("Node private key file lacks a 'ed25519-privkey' tag!") # recreate a signing key from the base64 encoding privkey_obj = SigningKey(privkey, encoder=HexEncoder) pubkey = privkey_obj.verify_key.encode(encoder=HexEncoder).decode('ascii') log.debug("Node key already exists (public key: {})".format(pubkey)) else: raise Exception("Node private key path '{}' exists, but isn't a file".format(privkey_path)) else: # node private key does NOT yet exist: generate one privkey_obj = SigningKey.generate() privkey = privkey_obj.encode(encoder=HexEncoder).decode('ascii') privkey_created_at = utcnow() pubkey = privkey_obj.verify_key.encode(encoder=HexEncoder).decode('ascii') # for informational purposes, try to get a machine unique id thing .. machine_id = None try: # why this? see: http://0pointer.de/blog/projects/ids.html with open('/var/lib/dbus/machine-id', 'r') as f: machine_id = f.read().strip() except: pass # for informational purposes, try to identify the creator (user@hostname) creator = None try: creator = u'{}@{}'.format(getpass.getuser(), socket.gethostname()) except: pass # write out the private key file with open(privkey_path, 'w') as privkey_file: privkey_file.write(u'Crossbar.io private key for node authentication - KEEP THIS SAFE!\n\n') if creator: privkey_file.write(u'creator: {}\n'.format(creator)) privkey_file.write(u'created-at: {}\n'.format(privkey_created_at)) if machine_id: privkey_file.write(u'machine-id: {}\n'.format(machine_id)) privkey_file.write(u'public-key-ed25519: {}\n'.format(pubkey)) privkey_file.write(u'private-key-ed25519: {}\n'.format(privkey)) # set file mode to read only for owner # 384 (decimal) == 0600 (octal) - we use that for Py2/3 reasons os.chmod(privkey_path, 384) log.info("New node key generated!") return pubkey
class PrivateKeyProvider(object): """ Decrypts private keys. """ def __init__(self, key, passphrase: bytes): self.key = key # Secure! self.passphrase = passphrase self.sign = None self.encrypt = None def __enter__(self) -> typing.Tuple[PrivateKey, PrivateKey]: """ Provides a pair of private keys. """ # Derive the key from the passphrase. derived = util.derive_passphrase(self.passphrase) sign_box = SecretBox(derived) enc_box = SecretBox(derived) # Decrypt, using the two nonces. s_d = sign_box.decrypt(self.key._private_signing_seed, self.key._private_signing_nonce) e_d = enc_box.decrypt(self.key._private_key_raw, self.key._private_nonce) # Generate a SigningKey out of the seed. self.sign = SigningKey(s_d) self.encrypt = PrivateKey(e_d) # Update the key's public keys. if self.key._public_key is None: self.key._public_key = self.encrypt.public_key if self.key._public_signing_key is None: self.key._public_signing_key = self.sign.verify_key return self.encrypt, self.sign def __exit__(self, exc_type, exc_val, exc_tb): """ Re-encrypt. """ # Derive the key from the passphrase. derived = util.derive_passphrase(self.passphrase) # Generate two random nonces. nonce1 = random(SecretBox.NONCE_SIZE) nonce2 = random(SecretBox.NONCE_SIZE) sign_box = SecretBox(derived) enc_box = SecretBox(derived) s_p = self.sign.encode() e_p = self.encrypt.encode() s_e = sign_box.encrypt(s_p, nonce1) e_e = enc_box.encrypt(e_p, nonce2) # Update `self.key`. self.key._private_key_raw = e_e.ciphertext self.key._private_signing_key_raw = s_e.ciphertext # Bit of a mixed up name. self.key._private_nonce = e_e.nonce self.key._private_signing_nonce = s_e.nonce if exc_type is not None: raise exc_type(exc_val)