golix/_spec.py
'''
Spec-based definition of Golix objects. It sure ain't beautiful, but it's
getting the job done for now.
LICENSING
-------------------------------------------------
golix: A python library for Golix protocol object manipulation.
Copyright (C) 2016 Muterra, Inc.
Contributors
------------
Nick Badger
badg@muterra.io | badg@nickbadger.com | nickbadger.com
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
License along with this library; if not, write to the
Free Software Foundation, Inc.,
51 Franklin Street,
Fifth Floor,
Boston, MA 02110-1301 USA
------------------------------------------------------
'''
from smartyparse import ParseHelper
from smartyparse import SmartyParser
from smartyparse import ListyParser
from smartyparse import parsers
from smartyparse import references
from .utils import Ghid
from .utils import _dummy_ghid
from .crypto_utils import _gen_dispatch
from .crypto_utils import _gen_body_update
from .crypto_utils import _callback_multi
from .crypto_utils import _dummy_asym
from .crypto_utils import _dummy_mac
from .crypto_utils import _dummy_signature
from .crypto_utils import _dummy_address
from .crypto_utils import _dummy_pubkey
from .crypto_utils import generate_ghid_parser
from .crypto_utils import generate_ghidlist_parser
# ----------------------------------------------------------------------
# Crypto parsers definition block
_signature_parsers = {}
_signature_parsers[0] = ParseHelper(
parsers.Blob(length=512))
_signature_parsers[1] = ParseHelper(
parsers.Blob(length=512))
_signature_parsers[2] = ParseHelper(
parsers.Blob(length=512))
_mac_parsers = {}
_mac_parsers[0] = ParseHelper(
parsers.Blob(length=64))
_mac_parsers[1] = ParseHelper(
parsers.Blob(length=64))
_mac_parsers[2] = ParseHelper(
parsers.Blob(length=64))
_asym_parsers = {}
_asym_parsers[0] = ParseHelper(
parsers.Blob(length=512))
_asym_parsers[1] = ParseHelper(
parsers.Blob(length=512))
_asym_parsers[2] = ParseHelper(
parsers.Blob(length=512))
_pubkey_parsers_sig = {}
_pubkey_parsers_sig[0] = ParseHelper(
parsers.Blob(length=512))
_pubkey_parsers_sig[1] = ParseHelper(
parsers.Blob(length=512))
_pubkey_parsers_sig[2] = ParseHelper(
parsers.Blob(length=512))
_pubkey_parsers_encrypt = {}
_pubkey_parsers_encrypt[0] = ParseHelper(
parsers.Blob(length=512))
_pubkey_parsers_encrypt[1] = ParseHelper(
parsers.Blob(length=512))
_pubkey_parsers_encrypt[2] = ParseHelper(
parsers.Blob(length=512))
_pubkey_parsers_exchange = {}
_pubkey_parsers_exchange[0] = ParseHelper(
parsers.Blob(length=32))
_pubkey_parsers_exchange[1] = ParseHelper(
parsers.Blob(length=32))
_pubkey_parsers_exchange[2] = ParseHelper(
parsers.Blob(length=32))
# ----------------------------------------------------------------------
# Use this whenever a GHID list is required
_ghidlist = generate_ghidlist_parser()
# ----------------------------------------------------------------------
# GIDC format blocks
_gidc = SmartyParser()
_gidc['magic'] = ParseHelper(parsers.Literal(b'GIDC'))
_gidc['version'] = ParseHelper(parsers.Int32(signed=False))
_gidc['cipher'] = ParseHelper(parsers.Int8(signed=False))
_gidc['body'] = None
_gidc['ghid'] = generate_ghid_parser()
_gidc['signature'] = ParseHelper(parsers.Null())
_gidc_lookup = {}
_gidc_lookup[2] = SmartyParser()
_gidc_lookup[2]['signature_key'] = None
_gidc_lookup[2]['encryption_key'] = None
_gidc_lookup[2]['exchange_key'] = None
_gidc_cipher_update = _callback_multi(
_gen_body_update(_gidc, _pubkey_parsers_sig, 'signature_key'),
_gen_body_update(_gidc, _pubkey_parsers_encrypt, 'encryption_key'),
_gen_body_update(_gidc, _pubkey_parsers_exchange, 'exchange_key')
)
_gidc['version'].register_callback(
'prepack',
_gen_dispatch(_gidc, _gidc_lookup, 'body')
)
_gidc['version'].register_callback(
'postunpack',
_gen_dispatch(_gidc, _gidc_lookup, 'body')
)
_gidc['cipher'].register_callback(
'prepack',
_gidc_cipher_update
)
_gidc['cipher'].register_callback(
'postunpack',
_gidc_cipher_update
)
_gidc.latest = max(list(_gidc_lookup))
_gidc.versions = set(_gidc_lookup)
# ----------------------------------------------------------------------
# GEOC format blocks
_geoc = SmartyParser()
_geoc['magic'] = ParseHelper(parsers.Literal(b'GEOC'))
_geoc['version'] = ParseHelper(parsers.Int32(signed=False))
_geoc['cipher'] = ParseHelper(parsers.Int8(signed=False))
_geoc['body'] = None
_geoc['ghid'] = generate_ghid_parser()
_geoc['signature'] = None
_geoc_lookup = {}
_geoc_lookup[14] = SmartyParser()
_geoc_lookup[14]['author'] = generate_ghid_parser()
_geoc_lookup[14]['len_payload'] = ParseHelper(parsers.Int64(signed=False))
_geoc_lookup[14]['payload'] = ParseHelper(parsers.Blob())
_geoc_lookup[14].link_length('payload', 'len_payload')
_geoc['version'].register_callback(
'prepack',
_gen_dispatch(_geoc, _geoc_lookup, 'body')
)
_geoc['version'].register_callback(
'postunpack',
_gen_dispatch(_geoc, _geoc_lookup, 'body')
)
_geoc['cipher'].register_callback(
'prepack',
_gen_dispatch(_geoc, _signature_parsers, 'signature')
)
_geoc['cipher'].register_callback(
'postunpack',
_gen_dispatch(_geoc, _signature_parsers, 'signature')
)
_geoc.latest = max(list(_geoc_lookup))
_geoc.versions = set(_geoc_lookup)
# ----------------------------------------------------------------------
# GOBS format blocks
_gobs = SmartyParser()
_gobs['magic'] = ParseHelper(parsers.Literal(b'GOBS'))
_gobs['version'] = ParseHelper(parsers.Int32(signed=False))
_gobs['cipher'] = ParseHelper(parsers.Int8(signed=False))
_gobs['body'] = None
_gobs['ghid'] = generate_ghid_parser()
_gobs['signature'] = None
_gobs_lookup = {}
_gobs_lookup[6] = SmartyParser()
_gobs_lookup[6]['binder'] = generate_ghid_parser()
_gobs_lookup[6]['target'] = generate_ghid_parser()
_gobs['version'].register_callback(
'prepack',
_gen_dispatch(_gobs, _gobs_lookup, 'body')
)
_gobs['version'].register_callback(
'postunpack',
_gen_dispatch(_gobs, _gobs_lookup, 'body')
)
_gobs['cipher'].register_callback(
'prepack',
_gen_dispatch(_gobs, _signature_parsers, 'signature')
)
_gobs['cipher'].register_callback(
'postunpack',
_gen_dispatch(_gobs, _signature_parsers, 'signature')
)
_gobs.latest = max(list(_gobs_lookup))
_gobs.versions = set(_gobs_lookup)
# ----------------------------------------------------------------------
# GOBD format blocks
_gobd = SmartyParser()
_gobd['magic'] = ParseHelper(parsers.Literal(b'GOBD'))
_gobd['version'] = ParseHelper(parsers.Int32(signed=False))
_gobd['cipher'] = ParseHelper(parsers.Int8(signed=False))
_gobd['body'] = None
_gobd['ghid_dynamic'] = generate_ghid_parser()
_gobd['ghid'] = generate_ghid_parser()
_gobd['signature'] = None
_gobd_lookup = {}
_gobd_lookup[16] = SmartyParser()
_gobd_lookup[16]['binder'] = generate_ghid_parser()
_gobd_lookup[16]['counter'] = ParseHelper(parsers.Int64(signed=False))
_gobd_lookup[16]['tarvec_length'] = ParseHelper(parsers.Int16(signed=False))
_gobd_lookup[16]['target_vector'] = _ghidlist
_gobd_lookup[16].link_length('target_vector', 'tarvec_length')
_gobd['version'].register_callback(
'prepack',
_gen_dispatch(_gobd, _gobd_lookup, 'body')
)
_gobd['version'].register_callback(
'postunpack',
_gen_dispatch(_gobd, _gobd_lookup, 'body')
)
_gobd['cipher'].register_callback(
'prepack',
_gen_dispatch(_gobd, _signature_parsers, 'signature')
)
_gobd['cipher'].register_callback(
'postunpack',
_gen_dispatch(_gobd, _signature_parsers, 'signature')
)
_gobd.latest = max(list(_gobd_lookup))
_gobd.versions = set(_gobd_lookup)
# ----------------------------------------------------------------------
# GDXX format blocks
_gdxx = SmartyParser()
_gdxx['magic'] = ParseHelper(parsers.Literal(b'GDXX'))
_gdxx['version'] = ParseHelper(parsers.Int32(signed=False))
_gdxx['cipher'] = ParseHelper(parsers.Int8(signed=False))
_gdxx['body'] = None
_gdxx['ghid'] = generate_ghid_parser()
_gdxx['signature'] = None
_gdxx_lookup = {}
_gdxx_lookup[9] = SmartyParser()
_gdxx_lookup[9]['debinder'] = generate_ghid_parser()
_gdxx_lookup[9]['target'] = generate_ghid_parser()
_gdxx['version'].register_callback(
'prepack',
_gen_dispatch(_gdxx, _gdxx_lookup, 'body')
)
_gdxx['version'].register_callback(
'postunpack',
_gen_dispatch(_gdxx, _gdxx_lookup, 'body')
)
_gdxx['cipher'].register_callback(
'prepack',
_gen_dispatch(_gdxx, _signature_parsers, 'signature')
)
_gdxx['cipher'].register_callback(
'postunpack',
_gen_dispatch(_gdxx, _signature_parsers, 'signature')
)
_gdxx.latest = max(list(_gdxx_lookup))
_gdxx.versions = set(_gdxx_lookup)
# ----------------------------------------------------------------------
# GARQ format blocks
_garq = SmartyParser()
_garq['magic'] = ParseHelper(parsers.Literal(b'GARQ'))
_garq['version'] = ParseHelper(parsers.Int32(signed=False))
_garq['cipher'] = ParseHelper(parsers.Int8(signed=False))
_garq['body'] = None
_garq['ghid'] = generate_ghid_parser()
_garq['signature'] = None
_garq_lookup = {}
_garq_lookup[12] = SmartyParser()
_garq_lookup[12]['recipient'] = generate_ghid_parser()
_garq_lookup[12]['payload'] = None
_garq_cipher_update = _callback_multi(
_gen_dispatch(_garq, _mac_parsers, 'signature'),
_gen_body_update(_garq, _asym_parsers, 'payload')
)
_garq['version'].register_callback(
'prepack',
_gen_dispatch(_garq, _garq_lookup, 'body')
)
_garq['version'].register_callback(
'postunpack',
_gen_dispatch(_garq, _garq_lookup, 'body')
)
_garq['cipher'].register_callback(
'prepack',
_garq_cipher_update
)
_garq['cipher'].register_callback(
'postunpack',
_garq_cipher_update
)
_garq.latest = max(list(_garq_lookup))
_garq.versions = set(_garq_lookup)
# ----------------------------------------------------------------------
# Asymmetric payload format blocks
_asym_hand_payload = SmartyParser()
_asym_hand_payload['target'] = generate_ghid_parser()
_asym_hand_payload['secret_length'] = ParseHelper(parsers.Int8(signed=False))
_asym_hand_payload['secret'] = ParseHelper(parsers.Blob())
_asym_hand_payload.link_length('secret', 'secret_length')
_asym_ak_payload = SmartyParser()
_asym_ak_payload['target'] = generate_ghid_parser()
_asym_ak_payload['status'] = ParseHelper(parsers.Int32(signed=False))
_asym_nk_payload = SmartyParser()
_asym_nk_payload['target'] = generate_ghid_parser()
_asym_nk_payload['status'] = ParseHelper(parsers.Int32(signed=False))
_asym_hand = SmartyParser()
_asym_hand['author'] = generate_ghid_parser()
_asym_hand['magic'] = ParseHelper(parsers.Literal(b'HS'))
_asym_hand['payload_length'] = ParseHelper(parsers.Int16(signed=False))
_asym_hand['payload'] = _asym_hand_payload
_asym_hand.link_length('payload', 'payload_length')
_asym_ak = SmartyParser()
_asym_ak['author'] = generate_ghid_parser()
_asym_ak['magic'] = ParseHelper(parsers.Literal(b'AK'))
_asym_ak['payload_length'] = ParseHelper(parsers.Int16(signed=False))
_asym_ak['payload'] = _asym_ak_payload
_asym_ak.link_length('payload', 'payload_length')
_asym_nk = SmartyParser()
_asym_nk['author'] = generate_ghid_parser()
_asym_nk['magic'] = ParseHelper(parsers.Literal(b'NK'))
_asym_nk['payload_length'] = ParseHelper(parsers.Int16(signed=False))
_asym_nk['payload'] = _asym_nk_payload
_asym_nk.link_length('payload', 'payload_length')
_asym_else = SmartyParser()
_asym_else['author'] = generate_ghid_parser()
_asym_else['magic'] = ParseHelper(parsers.Literal(b'\x00\x00'))
_asym_else['payload_length'] = ParseHelper(parsers.Int16(signed=False))
_asym_else['payload'] = ParseHelper(parsers.Blob())
_asym_else.link_length('payload', 'payload_length')