from . import lib, GoSlice, DataError from .error import GoError from ctypes import * from typing import Callable, List, Dict, Any from enum import Enum import json def getList(func: Callable) -> List[Dict[str, Any]]: dataError = func() ptr = dataError.data error = dataError.error body = "" if not error: body_value = cast(ptr, c_char_p).value if body_value: body = body_value.decode() lib.FreeString(ptr) if error: raise RequestError(error) return json.loads(body) def GetOrganizationsList() -> List[Dict[str, Any]]: return getList(lib.GetOrganizationsList) def GetServersList() -> List[Dict[str, Any]]: return getList(lib.GetServersList) class RequestErrorCode(Enum): ErrRequestFileError = 1 # The request for the file has failed. ErrVerifySigError = 2 # The signature failed to verify. Unknown = -1 # Other unknown error. class RequestError(GoError): def __init__(self, err: int): super().__init__(RequestErrorCode(err), { RequestErrorCode.ErrRequestFileError: "file request error", RequestErrorCode.ErrVerifySigError: "signature verify error", RequestErrorCode.Unknown: "unknown error", }) class VerifyErrorCode(Enum): ErrUnknownExpectedFileName = 1 # Unknown expected file name specified. The signature has not been verified. ErrInvalidSignature = 2 # Signature is invalid (for the expected file type). ErrInvalidSignatureUnknownKey = 3 # Signature was created with an unknown key and has not been verified. ErrTooOld = 4 # Signature timestamp smaller than specified minimum signing time (rollback). Unknown = -1 # Other unknown error. class VerifyError(GoError): def __init__(self, err: int): super().__init__(VerifyErrorCode(err), { VerifyErrorCode.ErrUnknownExpectedFileName: "unknown expected file name", VerifyErrorCode.ErrInvalidSignature: "invalid signature", VerifyErrorCode.ErrInvalidSignatureUnknownKey: "invalid signature (unknown key)", VerifyErrorCode.ErrTooOld: "replay of previous signature (rollback)", VerifyErrorCode.Unknown: "unknown error", }) def verify(signature: bytes, signed_json: bytes, expected_file_name: str, min_sign_time: int) -> None: """ Verifies the signature on the JSON server_list.json/organization_list.json file. If the function returns, the signature is valid for the given file type. :param signature: .minisig signature file contents. :param signed_json: Signed .json file contents. :param expected_file_name: The file type to be verified, one of "server_list.json" or "organization_list.json". :param min_sign_time: Minimum time for signature (UNIX timestamp, seconds). Should be set to at least the time of the previous signature. :raises VerifyException: If signature verification fails or expectedFileName is not one of the allowed values. """ err = lib.Verify(GoSlice.make(signature), GoSlice.make(signed_json), GoSlice.make(expected_file_name.encode()), min_sign_time) if err: raise VerifyError(err) def _insecure_testing_set_extra_key(key_string: str) -> None: """Use for testing only, see Go documentation.""" lib.InsecureTestingSetExtraKey(GoSlice.make(key_string.encode()))