bacommon.securedata
Functionality related to verifying ballistica server generated data.
1# Released under the MIT License. See LICENSE for details. 2# 3"""Functionality related to verifying ballistica server generated data.""" 4 5import datetime 6from dataclasses import dataclass 7from typing import TYPE_CHECKING, Annotated 8 9from efro.util import utc_now 10from efro.dataclassio import ioprepped, IOAttrs 11 12if TYPE_CHECKING: 13 pass 14 15 16@ioprepped 17@dataclass 18class SecureDataChecker: 19 """Verifies data as being signed by our master server.""" 20 21 # Time period this checker is valid for. 22 starttime: Annotated[datetime.datetime, IOAttrs('s')] 23 endtime: Annotated[datetime.datetime, IOAttrs('e')] 24 25 # Current set of public keys. 26 publickeys: Annotated[list[bytes], IOAttrs('k')] 27 28 def check(self, data: bytes, signature: bytes) -> bool: 29 """Verify data, returning True if successful. 30 31 Note that this call imports and uses the cryptography module and 32 can be slow; it generally should be done in a background thread 33 or on a server. 34 """ 35 from cryptography.hazmat.primitives.asymmetric import ed25519 36 from cryptography.exceptions import InvalidSignature 37 38 now = utc_now() 39 40 # Make sure we seem valid based on local time. 41 if now < self.starttime: 42 raise RuntimeError('SecureDataChecker starttime is in the future.') 43 if now > self.endtime: 44 raise RuntimeError('SecureDataChecker endtime is in the past.') 45 46 # Try our keys from newest to oldest. Most stuff will be using 47 # the newest key so this should be most efficient. 48 for key in reversed(self.publickeys): 49 try: 50 publickey = ed25519.Ed25519PublicKey.from_public_bytes(key) 51 publickey.verify(signature, data) 52 return True 53 except InvalidSignature: 54 pass 55 56 return False
@ioprepped
@dataclass
class
SecureDataChecker:
17@ioprepped 18@dataclass 19class SecureDataChecker: 20 """Verifies data as being signed by our master server.""" 21 22 # Time period this checker is valid for. 23 starttime: Annotated[datetime.datetime, IOAttrs('s')] 24 endtime: Annotated[datetime.datetime, IOAttrs('e')] 25 26 # Current set of public keys. 27 publickeys: Annotated[list[bytes], IOAttrs('k')] 28 29 def check(self, data: bytes, signature: bytes) -> bool: 30 """Verify data, returning True if successful. 31 32 Note that this call imports and uses the cryptography module and 33 can be slow; it generally should be done in a background thread 34 or on a server. 35 """ 36 from cryptography.hazmat.primitives.asymmetric import ed25519 37 from cryptography.exceptions import InvalidSignature 38 39 now = utc_now() 40 41 # Make sure we seem valid based on local time. 42 if now < self.starttime: 43 raise RuntimeError('SecureDataChecker starttime is in the future.') 44 if now > self.endtime: 45 raise RuntimeError('SecureDataChecker endtime is in the past.') 46 47 # Try our keys from newest to oldest. Most stuff will be using 48 # the newest key so this should be most efficient. 49 for key in reversed(self.publickeys): 50 try: 51 publickey = ed25519.Ed25519PublicKey.from_public_bytes(key) 52 publickey.verify(signature, data) 53 return True 54 except InvalidSignature: 55 pass 56 57 return False
Verifies data as being signed by our master server.
SecureDataChecker( starttime: Annotated[datetime.datetime, <efro.dataclassio.IOAttrs object>], endtime: Annotated[datetime.datetime, <efro.dataclassio.IOAttrs object>], publickeys: Annotated[list[bytes], <efro.dataclassio.IOAttrs object>])
starttime: Annotated[datetime.datetime, <efro.dataclassio.IOAttrs object at 0x103fc3560>]
endtime: Annotated[datetime.datetime, <efro.dataclassio.IOAttrs object at 0x103fd1ac0>]
publickeys: Annotated[list[bytes], <efro.dataclassio.IOAttrs object at 0x103ff2cc0>]
def
check(self, data: bytes, signature: bytes) -> bool:
29 def check(self, data: bytes, signature: bytes) -> bool: 30 """Verify data, returning True if successful. 31 32 Note that this call imports and uses the cryptography module and 33 can be slow; it generally should be done in a background thread 34 or on a server. 35 """ 36 from cryptography.hazmat.primitives.asymmetric import ed25519 37 from cryptography.exceptions import InvalidSignature 38 39 now = utc_now() 40 41 # Make sure we seem valid based on local time. 42 if now < self.starttime: 43 raise RuntimeError('SecureDataChecker starttime is in the future.') 44 if now > self.endtime: 45 raise RuntimeError('SecureDataChecker endtime is in the past.') 46 47 # Try our keys from newest to oldest. Most stuff will be using 48 # the newest key so this should be most efficient. 49 for key in reversed(self.publickeys): 50 try: 51 publickey = ed25519.Ed25519PublicKey.from_public_bytes(key) 52 publickey.verify(signature, data) 53 return True 54 except InvalidSignature: 55 pass 56 57 return False
Verify data, returning True if successful.
Note that this call imports and uses the cryptography module and can be slow; it generally should be done in a background thread or on a server.