import sys from typing import Optional from importlib import resources def compile_asn1_subdir(subdir_name:str): """Helper function that compiles ASN.1 syntax from all files within given subdir""" import asn1tools asn_txt = '' __ver = sys.version_info if (__ver.major, __ver.minor) >= (3, 9): for i in resources.files('pySim.esim').joinpath('asn1').joinpath(subdir_name).iterdir(): asn_txt += i.read_text() asn_txt += "\n" #else: #print(resources.read_text(__name__, 'asn1/rsp.asn')) return asn1tools.compile_string(asn_txt, codec='der') # SGP.22 section 4.1 Activation Code class ActivationCode: def __init__(self, hostname:str, token:str, oid: Optional[str] = None, cc_required: Optional[bool] = False): if '$' in hostname: raise ValueError('$ sign not permitted in hostname') self.hostname = hostname if '$' in token: raise ValueError('$ sign not permitted in token') self.token = token # TODO: validate OID self.oid = oid self.cc_required = cc_required # only format 1 is specified and supported here self.format = 1 @staticmethod def decode_str(ac: str) -> dict: if ac[0] != '1': raise ValueError("Unsupported AC_Format '%s'!" % ac[0]) ac_elements = ac.split('$') d = { 'oid': None, 'cc_required': False, } d['format'] = ac_elements.pop(0) d['hostname'] = ac_elements.pop(0) d['token'] = ac_elements.pop(0) if len(ac_elements): oid = ac_elements.pop(0) if oid != '': d['oid'] = oid if len(ac_elements): ccr = ac_elements.pop(0) if ccr == '1': d['cc_required'] = True return d @classmethod def from_string(cls, ac: str) -> 'ActivationCode': """Create new instance from SGP.22 section 4.1 string representation.""" d = cls.decode_str(ac) return cls(d['hostname'], d['token'], d['oid'], d['cc_required']) def to_string(self, for_qrcode:bool = False) -> str: """Convert from internal representation to SGP.22 section 4.1 string representation.""" if for_qrcode: ret = 'LPA:' else: ret = '' ret += '%d$%s$%s' % (self.format, self.hostname, self.token) if self.oid: ret += '$%s' % (self.oid) elif self.cc_required: ret += '$' if self.cc_required: ret += '$1' return ret def __str__(self): return self.to_string() def to_qrcode(self): """Encode internal representation to QR code.""" import qrcode qr = qrcode.QRCode() qr.add_data(self.to_string(for_qrcode=True)) return qr.make_image() def __repr__(self): return "ActivationCode(format=%u, hostname='%s', token='%s', oid=%s, cc_required=%s)" % (self.format, self.hostname, self.token, self.oid, self.cc_required)