def make_test_orgentry() -> keycard.OrgEntry: '''Generates an organizational entry for testing purposes''' # Primary signing key pskey = nacl.signing.SigningKey( b'msvXw(nII<Qm6oBHc+92xwRI3>VFF-RcZ=7DEu3|', Base85Encoder) orgcard = keycard.OrgEntry() orgcard.set_fields({ 'Name': 'Acme Widgets, Inc.', 'Contact-Admin': 'c590b44c-798d-4055-8d72-725a7942f3f6/acme.com', 'Language': 'en', 'Domain': 'acme.com', 'Primary-Verification-Key': 'ED25519:)8id(gE02^S<{3H>9B;X4{DuYcb`%wo^mC&1lN88', 'Encryption-Key': 'CURVE25519:@b?cjpeY;<&y+LSOA&yUQ&ZIrp(JGt{W$*V>ATLG' }) # Organization sign, hash, and verify rv = orgcard.generate_hash('BLAKE2B-256') assert not rv.error(), 'entry failed to hash' pskeystring = CryptoString() pskeystring.set('ED25519:' + base64.b85encode(pskey.encode()).decode()) rv = orgcard.sign(pskeystring, 'Organization') assert not rv.error(), 'Unexpected RetVal error %s' % rv.error() assert orgcard.signatures['Organization'], 'entry failed to user sign' ovkey = nacl.signing.VerifyKey(pskey.verify_key.encode()) ovkeystring = CryptoString() ovkeystring.prefix = 'ED25519' ovkeystring.data = base64.b85encode(ovkey.encode()).decode() rv = orgcard.verify_signature(ovkeystring, 'Organization') assert not rv.error(), 'org entry failed to verify' status = orgcard.is_compliant() assert not status.error(), f"OrgEntry wasn't compliant: {str(status)}" return orgcard
def test_is_compliant_org(): '''Tests compliance testing for the OrgEntry class''' # Organization signing key oskey = nacl.signing.SigningKey( b'msvXw(nII<Qm6oBHc+92xwRI3>VFF-RcZ=7DEu3|', Base85Encoder) orgcard = keycard.OrgEntry() orgcard.set_fields({ 'Name': 'Acme Widgets, Inc', 'Contact-Admin': '54025843-bacc-40cc-a0e4-df48a099c2f3/example.com', 'Contact-Abuse': '54025843-bacc-40cc-a0e4-df48a099c2f3/example.com', 'Language': 'en', 'Primary-Verification-Key': 'ED25519:7dfD==!Jmt4cDtQDBxYa7(dV|N$}8mYwe$=RZuW|', 'Encryption-Key': 'CURVE25519:_`UC|vltn_%P5}~vwV^)oY){#uvQSSy(dOD_l(yE' }) # sign and verify okeystring = CryptoString() okeystring.set('ED25519:' + base64.b85encode(oskey.encode()).decode()) rv = orgcard.sign(okeystring, 'Organization') assert not rv.error(), 'Unexpected RetVal error %s' % rv.error() assert orgcard.signatures['Organization'], 'entry failed to user sign' ovkey = nacl.signing.VerifyKey(oskey.verify_key.encode()) ovkeystring = CryptoString() ovkeystring.prefix = 'ED25519' ovkeystring.data = base64.b85encode(ovkey.encode()).decode() rv = orgcard.verify_signature(ovkeystring, 'Organization') assert not rv.error(), 'entry failed to org verify' rv = orgcard.generate_hash('BLAKE2B-256') assert not rv.error(), 'entry failed to hash' status = orgcard.is_compliant() assert not status.error(), f"OrgEntry wasn't compliant: {str(status)}"
def get_hash(self, algorithm: str) -> RetVal: '''Generates a hash containing the expected signatures and the previous hash, if it exists. The supported hash algorithms are 'BLAKE2-256', 'BLAKE3-256', 'SHA-256', and 'SHA3-256'.''' # if algorithm not in ['BLAKE3-256','BLAKE2B-256','SHA-256','SHA3-256']: if algorithm not in ['BLAKE2B-256', 'SHA-256', 'SHA3-256']: return RetVal(UnsupportedHashType, f'{algorithm} not a supported hash algorithm') hash_string = CryptoString() hash_level = -1 for sig in self.signature_info: if sig['type'] == SIGINFO_HASH: hash_level = sig['level'] break assert hash_level > 0, "BUG: signature_info missing hash entry" # if algorithm == 'BLAKE3-256': # hasher = blake3.blake3() # pylint: disable=c-extension-no-member # hasher.update(self.make_bytestring(hash_level)) # hash_string.data = base64.b85encode(hasher.digest()).decode() # else: # hasher = None # if algorithm == 'BLAKE2B-256': # hasher = hashlib.blake2b(digest_size=32) # elif algorithm == 'SHA-256': # hasher = hashlib.sha256() # else: # hasher = hashlib.sha3_256() # hasher.update(self.make_bytestring(hash_level)) # hash_string.data = base64.b85encode(hasher.digest()).decode() hasher = None if algorithm == 'BLAKE2B-256': hasher = hashlib.blake2b(digest_size=32) elif algorithm == 'SHA-256': hasher = hashlib.sha256() else: hasher = hashlib.sha3_256() hasher.update(self.make_bytestring(hash_level)) hash_string.data = base64.b85encode(hasher.digest()).decode() hash_string.prefix = algorithm return RetVal().set_value('hash', str(hash_string))
def make_test_userentry() -> keycard.UserEntry: '''Generates a user entry for testing purposes''' # User signing key skey = nacl.signing.SigningKey(b'p;XXU0XF#UO^}vKbC-wS(#5W6=OEIFmR2z`rS1j+', Base85Encoder) # Organization signing key oskey = nacl.signing.SigningKey( b'msvXw(nII<Qm6oBHc+92xwRI3>VFF-RcZ=7DEu3|', Base85Encoder) # crskey = nacl.signing.SigningKey(b'ip52{ps^jH)t$k-9bc_RzkegpIW?}FFe~BX&<V}9', Base85Encoder) # crekey = nacl.public.PrivateKey(b'VyFX5PC~?eL5)>q|6W7ciRrOJw$etlej<tY$f+t_', Base85Encoder) # ekey = nacl.public.PrivateKey(b'Wsx6BC(HP~goS-C_`K=6Daqr97kapfc=vQUzi?KI', Base85Encoder) usercard = keycard.UserEntry() usercard.set_fields({ 'Name': 'Corbin Simons', 'Workspace-ID': '4418bf6c-000b-4bb3-8111-316e72030468', 'User-ID': 'csimons', 'Domain': 'example.com', 'Contact-Request-Verification-Key': 'ED25519:d0-oQb;{QxwnO{=!|^62+E=UYk2Y3mr2?XKScF4D', 'Contact-Request-Encryption-Key': 'CURVE25519:yBZ0{1fE9{2<b~#i^R+JT-yh-y5M(Wyw_)}_SZOn', 'Public-Encryption-Key': 'CURVE25519:_`UC|vltn_%P5}~vwV^)oY){#uvQSSy(dOD_l(yE' }) # Organization sign and verify okeystring = CryptoString() okeystring.set('ED25519:' + base64.b85encode(oskey.encode()).decode()) rv = usercard.sign(okeystring, 'Organization') assert not rv.error(), 'Unexpected RetVal error %s' % rv.error() assert usercard.signatures['Organization'], 'entry failed to user sign' ovkey = nacl.signing.VerifyKey(oskey.verify_key.encode()) ovkeystring = CryptoString() ovkeystring.prefix = 'ED25519' ovkeystring.data = base64.b85encode(ovkey.encode()).decode() rv = usercard.verify_signature(ovkeystring, 'Organization') assert not rv.error(), 'entry failed to org verify' # Add the hash rv = usercard.generate_hash('BLAKE2B-256') assert not rv.error(), 'entry failed to hash' # User sign and verify keystring = CryptoString() keystring.set('ED25519:' + base64.b85encode(skey.encode()).decode()) rv = usercard.sign(keystring, 'User') assert not rv.error(), 'Unexpected RetVal error %s / %s' % (rv.error(), rv.info()) assert usercard.signatures['User'], 'entry failed to user sign' vkey = nacl.signing.VerifyKey(skey.verify_key.encode()) vkeystring = CryptoString() vkeystring.prefix = 'ED25519' vkeystring.data = base64.b85encode(vkey.encode()).decode() rv = usercard.verify_signature(vkeystring, 'User') assert not rv.error(), 'entry failed to user verify' status = usercard.is_compliant() assert not status.error(), f"UserEntry wasn't compliant: {str(status)}" return usercard
def test_verify_signature(): '''Tests the signing of a test keycard entry''' # This is an extensive test because while it doesn't utilize all the fields that a standard # entry would normally have, it tests signing and verification of user, org, and entry # signatures. This test is also only intended to confirm success states of the method. # User signing key skey = nacl.signing.SigningKey(b'p;XXU0XF#UO^}vKbC-wS(#5W6=OEIFmR2z`rS1j+', Base85Encoder) # Organization signing key oskey = nacl.signing.SigningKey( b'msvXw(nII<Qm6oBHc+92xwRI3>VFF-RcZ=7DEu3|', Base85Encoder) # crekey = nacl.public.PrivateKey(b'VyFX5PC~?eL5)>q|6W7ciRrOJw$etlej<tY$f+t_', Base85Encoder) # ekey = nacl.public.PrivateKey(b'Wsx6BC(HP~goS-C_`K=6Daqr97kapfc=vQUzi?KI', Base85Encoder) basecard = keycard.EntryBase() basecard.type = "Test" basecard.field_names = [ 'Name', 'Workspace-ID', 'Domain', 'Contact-Request-Verification-Key', 'Contact-Request-Encryption-Key', 'Public-Encryption-Key', 'Expires' ] basecard.set_fields({ 'Name': 'Corbin Simons', 'Workspace-ID': '4418bf6c-000b-4bb3-8111-316e72030468', 'Domain': 'example.com', 'Contact-Request-Verification-Key': 'ED25519:d0-oQb;{QxwnO{=!|^62+E=UYk2Y3mr2?XKScF4D', 'Contact-Request-Encryption-Key': 'CURVE25519:yBZ0{1fE9{2<b~#i^R+JT-yh-y5M(Wyw_)}_SZOn', 'Public-Encryption-Key': 'CURVE25519:_`UC|vltn_%P5}~vwV^)oY){#uvQSSy(dOD_l(yE', 'Expires': '20201002', # These junk signatures will end up being cleared when sign('User') is called 'User-Signature': '1111111111', 'Organization-Signature': '2222222222', 'Entry-Signature': '3333333333' }) basecard.signature_info = [{ 'name': 'Custody', 'level': 1, 'optional': True, 'type': SIGINFO_SIGNATURE }, { 'name': 'Organization', 'level': 2, 'optional': False, 'type': SIGINFO_SIGNATURE }, { 'name': 'Hashes', 'level': 3, 'optional': False, 'type': SIGINFO_HASH }, { 'name': 'User', 'level': 4, 'optional': False, 'type': SIGINFO_SIGNATURE }] # Organization sign and verify okeystring = CryptoString() okeystring.set('ED25519:' + base64.b85encode(oskey.encode()).decode()) rv = basecard.sign(okeystring, 'Organization') assert not rv.error(), 'Unexpected RetVal error %s' % rv.error() assert basecard.signatures['Organization'], 'entry failed to user sign' expected_sig = \ 'ED25519:>>6(c|MBt?66%ywF=2yw4k}%;-8J)218?T=4XtV**m9S4Wzo@%E0Xme7@op7Vky?>VnCb?h(%WGO9(g!' assert basecard.signatures['Organization'] == expected_sig, \ "entry did not yield the expected org signature" ovkey = nacl.signing.VerifyKey(oskey.verify_key.encode()) ovkeystring = CryptoString() ovkeystring.prefix = 'ED25519' ovkeystring.data = base64.b85encode(ovkey.encode()).decode() rv = basecard.verify_signature(ovkeystring, 'Organization') assert not rv.error(), 'entry failed to org verify' # Set up the hashes basecard.prev_hash = '1234567890' rv = basecard.generate_hash('BLAKE2B-256') assert not rv.error(), 'entry failed to BLAKE3 hash' expected_hash = r'BLAKE2B-256:kBO4*3!t3M2PONHy>*Ew)Hw8!v)rZcvpo;azDJvx' assert basecard.hash == expected_hash, "entry did not yield the expected hash" # User sign and verify keystring = CryptoString() keystring.set('ED25519:' + base64.b85encode(skey.encode()).decode()) rv = basecard.sign(keystring, 'User') assert not rv.error(), 'Unexpected RetVal error %s' % rv.error() assert basecard.signatures['User'], 'entry failed to user sign' expected_sig = \ 'ED25519:@R53O{bS93YmZq5qs2`f0Uj)Ks^_cl{3Tl;lce#{hF-LsexWsbWqH_5erOQ+VY^pBkADo)@zxG)YZVU#' assert basecard.signatures['User'] == expected_sig, \ "entry did not yield the expected user signature" vkey = nacl.signing.VerifyKey(skey.verify_key.encode()) vkeystring = CryptoString() vkeystring.prefix = 'ED25519' vkeystring.data = base64.b85encode(vkey.encode()).decode() rv = basecard.verify_signature(vkeystring, 'User') assert not rv.error(), 'entry failed to user verify'