def test_boxnm(self): msg = b'Are you suggesting coconuts migrate?' # run 1 nonce1 = libnacl.utils.rand_nonce() pk1, sk1 = libnacl.crypto_box_keypair() pk2, sk2 = libnacl.crypto_box_keypair() k1 = libnacl.crypto_box_beforenm(pk2, sk1) k2 = libnacl.crypto_box_beforenm(pk1, sk2) enc_msg = libnacl.crypto_box_afternm(msg, nonce1, k1) self.assertNotEqual(msg, enc_msg) clear_msg = libnacl.crypto_box_open_afternm(enc_msg, nonce1, k2) self.assertEqual(clear_msg, msg)
def confirm(request, addr, publicKey, password): her_public = b64decode(request['pk'][0]) response = { 'credentials': { ('%s:%s' % addr): { 'publicKey': publicKey, 'password': password } } } response = json.dumps(response) my_public, my_private = libnacl.crypto_box_keypair() nonce = libnacl.utils.rand_nonce() encrypted = b64encode( libnacl.crypto_box(response, nonce, her_public, my_private)) offer = { 'type': 'credentials', 'interface': 'udp', 'message': encrypted, 'n': b64encode(nonce), 'pk': b64encode(my_public), 'wrbtVersion': WRBT_VERSION } return PREFIX + '#' + urlencode(offer)
def crypto_hello(self) -> bytes: """Create a client tunnel packet consisting of: * 8 bytes: the ASCII bytes "oqQN2kaH" * 32 bytes: client's short-term public key C' * 64 bytes: all zero * 8 bytes: a client-selected compressed nonce in little-endian form. This compressed nonce is implicitly prefixed by "splonebox-client" to form a 24-byte nonce * 80 bytes: a cryptographic box encrypted and authenticated to the server's long-term public key S from the client's short-term public key C' using this 24-byte nonce. The 64-byte plaintext inside the box has the following contents: * 64 bytes: all zero :return: client hello packet """ self.crypto_nonce_update() identifier = struct.pack("<8s", b"oqQN2kaH") nonce = struct.pack("<16sQ", b"splonebox-client-H", self.nonce) zeros = bytearray(64) self.clientshorttermpk, \ self.clientshorttermsk = libnacl.crypto_box_keypair() box = libnacl.crypto_box(zeros, nonce, self.serverlongtermpk, self.clientshorttermsk) nonce = struct.pack("<Q", self.nonce) return b"".join( [identifier, self.clientshorttermpk, zeros, nonce, box])
def test_box_seal(self): msg = b'Are you suggesting coconuts migrate?' # run 1 pk, sk = libnacl.crypto_box_keypair() enc_msg = libnacl.crypto_box_seal(msg, pk) self.assertNotEqual(msg, enc_msg) clear_msg = libnacl.crypto_box_seal_open(enc_msg, pk, sk) self.assertEqual(clear_msg, msg) # run 2 pk2, sk2 = libnacl.crypto_box_keypair() enc_msg2 = libnacl.crypto_box_seal(msg, pk2) self.assertNotEqual(msg, enc_msg2) clear_msg2 = libnacl.crypto_box_seal_open(enc_msg2, pk2, sk2) self.assertEqual(clear_msg2, msg) # Check bits self.assertNotEqual(enc_msg, enc_msg2)
def test_guest_rpc(self): s_pub, s_pk = libnacl.crypto_box_keypair() cid2 = b'cid2' * 4 #Servers identify clients by client id and key pairs. #In this case, the server is allowing a guest login from a server it's never heard of. #The special value 'guest' tells the client to generate a new keypair. s = Server(allow_guest=True, ecc_keypair=(s_pub, s_pk)) c = Client(keypair='guest', serverkey=s_pub, clientID=cid2, cipher=2) time.sleep(0.55) r = Register("test", "foooo") s.registers[400] = r #Using the "Direct function" method which doesn't have as much introspection capability s.registers[401] = lambda c, a: a x = c.call(400, b'A test string') self.assertEqual(x, b'A test string') x = c.call(401, b'A test string') self.assertEqual(x, b'A test string')
def test_gen(self): pk1, sk1 = libnacl.crypto_box_keypair() pk2, sk2 = libnacl.crypto_box_keypair() pk3, sk3 = libnacl.crypto_box_keypair() self.assertEqual(len(pk1), libnacl.crypto_box_PUBLICKEYBYTES) self.assertEqual(len(sk1), libnacl.crypto_box_PUBLICKEYBYTES) self.assertEqual(len(pk2), libnacl.crypto_box_PUBLICKEYBYTES) self.assertEqual(len(sk2), libnacl.crypto_box_PUBLICKEYBYTES) self.assertEqual(len(pk3), libnacl.crypto_box_PUBLICKEYBYTES) self.assertEqual(len(sk3), libnacl.crypto_box_PUBLICKEYBYTES) self.assertNotEqual(pk1, sk1) self.assertNotEqual(pk2, sk2) self.assertNotEqual(pk3, sk3) self.assertNotEqual(pk1, pk2) self.assertNotEqual(pk1, pk3) self.assertNotEqual(sk1, sk2) self.assertNotEqual(sk2, sk3)
def request(): my_public, my_private = libnacl.crypto_box_keypair() query = { 'type': 'peer', 'interface': 'udp', 'pk': b64encode(my_public), 'wrbtVersion': WRBT_VERSION } url = PREFIX + '#' + urlencode(query) return url, b64encode(my_private)
def __init__(self, sk=None): ''' If a secret key is not passed in then it will be generated ''' if sk is None: self.pk, self.sk = libnacl.crypto_box_keypair() elif len(sk) == libnacl.crypto_box_SECRETKEYBYTES: self.sk = sk self.pk = libnacl.crypto_scalarmult_base(sk) else: raise ValueError('Passed in invalid secret key')
def __init__(self, providerName, providerFingerprint, resolverAddress, resolverPort=443): self._providerName = providerName self._providerFingerprint = providerFingerprint.lower().replace(':', '').decode('hex') self._resolverAddress = resolverAddress self._resolverPort = resolverPort self._resolverCertificates = [] self._publicKey, self._privateKey = libnacl.crypto_box_keypair() addrType = self._addrToSocketType(self._resolverAddress) self._sock = socket.socket(addrType, socket.SOCK_DGRAM) self._sock.connect((self._resolverAddress, self._resolverPort)) self._sock.settimeout(2)
def __init__(self, providerName, providerFingerprint, resolverAddress, resolverPort=443, timeout=2): self._providerName = providerName self._providerFingerprint = providerFingerprint.lower().replace(':', '').decode('hex') self._resolverAddress = resolverAddress self._resolverPort = resolverPort self._resolverCertificates = [] self._publicKey, self._privateKey = libnacl.crypto_box_keypair() addrType = self._addrToSocketType(self._resolverAddress) self._sock = socket.socket(addrType, socket.SOCK_DGRAM) self._sock.settimeout(timeout) self._sock.connect((self._resolverAddress, self._resolverPort))
def test_box(self): msg = b'Are you suggesting coconuts migrate?' # run 1 nonce1 = libnacl.utils.rand_nonce() pk1, sk1 = libnacl.crypto_box_keypair() pk2, sk2 = libnacl.crypto_box_keypair() enc_msg = libnacl.crypto_box(msg, nonce1, pk2, sk1) self.assertNotEqual(msg, enc_msg) clear_msg = libnacl.crypto_box_open(enc_msg, nonce1, pk1, sk2) self.assertEqual(clear_msg, msg) # run 2 nonce2 = libnacl.utils.rand_nonce() pk3, sk3 = libnacl.crypto_box_keypair() pk4, sk4 = libnacl.crypto_box_keypair() enc_msg2 = libnacl.crypto_box(msg, nonce2, pk4, sk3) self.assertNotEqual(msg, enc_msg2) clear_msg2 = libnacl.crypto_box_open(enc_msg2, nonce2, pk3, sk4) self.assertEqual(clear_msg2, msg) # Check bits self.assertNotEqual(nonce1, nonce2) self.assertNotEqual(enc_msg, enc_msg2)
def test_rpc(self): c_pub, c_pk = libnacl.crypto_box_keypair() s_pub, s_pk = libnacl.crypto_box_keypair() cid2 = b'cid2' * 4 #Servers identify clients by client id and key pairs. s = Server(pubkeys={cid2: c_pub}, ecc_keypair=(s_pub, s_pk), openWANPort=6070) #Get one of our WAN addressess, and from there import pavillion.upnpwrapper wan_addr = pavillion.upnpwrapper.getWANAddresses()[0] c = Client(address=(wan_addr, 6070), keypair=(c_pub, c_pk), serverkey=s_pub, clientID=cid2, cipher=2) time.sleep(5) r = Register("test", "foooo") s.registers[400] = r #Using the "Direct function" method which doesn't have as much introspection capability s.registers[401] = lambda c, a: a x = c.call(400, b'A test string') self.assertEqual(x, b'A test string') x = c.call(401, b'A test string') self.assertEqual(x, b'A test string')
def refreshKeys(self): """ Refreshes keys as needed so valid set of keys """ if not self.seed: # no signing key seed so create new one self.seed = libnacl.randombytes(libnacl.crypto_sign_SEEDBYTES) if not self.sigkey or not self.verkey: # ensure also sigkey and verkey self.verkey, self.sigkey = libnacl.crypto_sign_seed_keypair( self.seed) if not self.prikey: # no private encryption key so create new pair self.pubkey, self.prikey = libnacl.crypto_box_keypair() if not self.pubkey: # no public decryption key so create one from prikey self.pubkey = libnacl.crypto_scalarmult_base(self.prikey)
def generateKeypair(self): keypair = libnacl.crypto_box_keypair() self.publicKey = keypair[0] self.secretKey = keypair[1]
def generate_keypair(cls): return KeyPair(*libnacl.crypto_box_keypair())
def __init__(self, address:Tuple[str,int]=('255.255.255.255',DEFAULT_PORT),clientID=None,psk=None,cipher=1,server=None,keypair=None, serverkey=None, handle=None,daemon=None): "Represents a Pavillion client that can both initiate and respond to requests" if daemon is None: daemon=pavillion.daemon #Last time we were known to be connected #We're trying to pretend to be connectionless, so #this is really just a guess of if there's at least one #server connected self.connectedAt =0 #The address of our associated server self.server_address = address #The default timeout. self.timeout = 2 #Used for optimizing the response timing self.fastestOverallCallResponse = 0.05 #Average response time for each type of call we know about #Listed by the RPC number self.averageResponseTimes = {} self.stdDevResponseTimes = {} #Used to keeo track of the optimization where some broadcasts are converted to unicasts. #We occasionally send real broadcasts for new server discovery. self.lastActualBroadcast = 0 #Our message counter self.counter = random.randint(1024,1000000000) self.server_counter = 0 self.cipher= ciphers[cipher] self.keypair = keypair self.server_pubkey = serverkey #Clients can be associated with a server self.server = server psk = preprocessKey(psk) self.psk = psk self.clientID = clientID self.lastChangedChallenge = time.time() self.challengelock = threading.Lock() self.targetslock = threading.Lock() self.lock = threading.Lock() self.nonce = os.urandom(32) self.challenge = os.urandom(16) self.usedServerNonces = {} #Conceptually, there is exactly one server, but in the case of multicast there's #multiple machines even if they all have the same key. self.max_servers = 128 #Known servers, indexed by (addr,port) self.known_servers = {} #Last sent message that was sent to the default address self._keepalive_time = time.time() self.skey = None self.messageTargets = {} if self.keypair == "guest": self.keypair = libnacl.crypto_box_keypair() if self.psk: self.key = self.cipher.keyedhash(self.nonce,psk) self.sessionID = os.urandom(16) elif self.keypair: self.key = os.urandom(32) self.sessionID = os.urandom(16) else: self.key= None self.sessionID = os.urandom(16) if not self.clientID: if self.keypair: self.clientID = libnacl.crypto_generichash(self.keypair[0])[:16] self_address = ('', 0) self.lock=threading.Lock() # Create the socket self.sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM) self.sock.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1) self.sock.setsockopt(socket.SOL_SOCKET, socket.SO_BROADCAST, 1) # Bind to the server address self.sock.bind(self_address) self.sock.settimeout(1) if is_multicast(address[0]): # Create the socket self.msock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM) self.msock.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEPORT, 1) self.msock.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1) self.msock.setsockopt(socket.SOL_SOCKET, socket.SO_BROADCAST, 1) # Bind to the server address self.msock.bind((self_address[0],self.server_address[1])) self.msock.settimeout(1) group = socket.inet_aton(address[0]) mreq = struct.pack('4sL', group, socket.INADDR_ANY) self.msock.setsockopt(socket.IPPROTO_IP, socket.IP_ADD_MEMBERSHIP, mreq) else: self.msock = False self.running = True def cl(*args): self.close() self.clfun = cl #If we have a handle, make it so that if the handle gets collected the server thread stops if handle: self.handle = weakref.ref(handle,cl) #lastseen time dicts indexed by the name of what you are subscribing to, then indexed by subscriber IP #This is a list of *other* machines that are subscribing. # A "subscription" can be implicit, a response to a multicast packet. #Or it can be an explicit subscribe message #If we get less responses than usual, we know we should retry. self.knownSubscribers = {} self.subslock = threading.Lock() self.waitingForAck = weakref.WeakValueDictionary() self.backoff_until = time.time() t = threading.Thread(target=self.loop) t.daemon = daemon t.name+=":PavillionClient" t.start() self._kathread = threading.Thread(target=self._keepAliveLoop) self._kathread.daemon = True self._kathread.name+=":PavillionClientKeepalive" self._kathread.start() #Attempt to connect. The protocol has reconnection built in, #But this lets us connect in advance if self.psk and self.clientID: pass self.sendNonceRequest() elif self.keypair: self.sendNonceRequest() pass else: self.synced = False counter = 8 while not self.synced and counter: self.sendSetup(0, 1, struct.pack("<B",self.cipher.id)+self.clientID+self.challenge) time.sleep(0.05) counter-=1