Compare commits

...

2 Commits
main ... test

Author SHA1 Message Date
Lee Miller d97ea82c1f
A proper sample
buildbot/travis_bionic Build done. Details
buildbot/multibuild_parent Build done. Details
2023-01-05 07:20:58 +02:00
Lee Miller 43ba487d67
Add an example script on assembling a message
buildbot/multibuild_parent Build done. Details
buildbot/travis_bionic Build done. Details
2022-12-30 23:02:09 +02:00
2 changed files with 249 additions and 23 deletions

221
assemble_msg.py Normal file
View File

@ -0,0 +1,221 @@
import hashlib
import logging
import random
import time
from binascii import hexlify, unhexlify
from struct import pack
from pybitmessage import (
defaults, helper_msgcoding, highlevelcrypto, protocol, shared)
from pybitmessage.addresses import (
decodeAddress, decodeVarint, encodeAddress, encodeVarint)
from pybitmessage.fallback import RIPEMD160Hash
from pybitmessage.helper_ackPayload import genAckPayload
logger = logging.getLogger('default')
class Address(object):
version = 4
stream = 1
sigkey = None
enkey = None
ripe = None
bitfield = pack('>I', 0)
avg_pow = defaults.networkDefaultProofOfWorkNonceTrialsPerByte
avg_extra_bytes = defaults.networkDefaultPayloadLengthExtraBytes
@classmethod
def fromData(cls, data, addr=None):
# parse addr_data
# SELECT transmitdata FROM pubkeys WHERE address = ?
version, _ = decodeVarint(data[0])
pos = 1
stream, length = decodeVarint(data[pos:pos + 10])
pos += length
bitfield = data[pos:pos + 4]
# TODO: mobile
pos += 4
sigkey = data[pos:pos + 64]
pos += 64
enkey = data[pos:pos + 64]
pos += 64
if version >= 3:
avg_pow = decodeVarint(data[pos:pos + 10])
pos += length
extra_bytes, length = decodeVarint(data[pos:pos + 10])
avg_pow = max(
defaults.networkDefaultProofOfWorkNonceTrialsPerByte, avg_pow)
extra_bytes = max(
defaults.networkDefaultPayloadLengthExtraBytes, extra_bytes)
else:
avg_pow = None
extra_bytes = None
return cls(
version, stream, sigkey, enkey,
addr=addr, avg_pow=avg_pow, extra_bytes=extra_bytes,
bitfield=bitfield)
def __init__(
self, version, stream, sigkey, enkey, addr=None, ripe=None,
avg_pow=None, extra_bytes=None, bitfield=None
):
self.version = version
self.stream = stream
self.sigkey = sigkey
self.enkey = enkey
if bitfield:
self.bitfield = bitfield
if ripe is None:
if addr:
status, dversion, dstream, ripe = decodeAddress(addr)
assert status == 'success'
assert version == dversion
assert stream == dstream
else:
_sha = hashlib.new('sha512')
_sha.update(sigkey + enkey)
ripe = RIPEMD160Hash(_sha.digest()).digest()
self.ripe = ripe
if avg_pow:
self.avg_pow = avg_pow
if extra_bytes:
self.extra_bytes = extra_bytes
self.addr = addr or encodeAddress(self.version, self.stream, self.ripe)
def encrypt(self, data):
return highlevelcrypto.encrypt(data, b'04' + hexlify(self.enkey))
class Identity(Address):
priv_sigkey = None
priv_enkey = None
@classmethod
def fromWIF(cls, sigkey, enkey, bitfield=pack('>I', 0)):
return cls(
hexlify(shared.decodeWalletImportFormat(sigkey)),
hexlify(shared.decodeWalletImportFormat(enkey)), bitfield=bitfield)
@classmethod
def fromConfig(cls, addr, config):
sigkey_base58 = config.get(addr, 'privsigningkey')
enkey_base58 = config.get(addr, 'privencryptionkey')
bitfield = 0
# send ack
if not config.safeGetBoolean(addr, 'dontsendack'):
bitfield |= protocol.BITFIELD_DOESACK
return cls.fromWIF(
sigkey_base58, enkey_base58, bitfield=pack('>I', bitfield))
def __init__(
self, sigkey, enkey, addr=None, bitfield=None,
version=None, stream=None, ripe=None,
avg_pow=None, extra_bytes=None
):
self.priv_sigkey = sigkey
self.priv_enkey = enkey
if version:
self.version = version
if stream:
self.stream = stream
sigkey = unhexlify(highlevelcrypto.privToPub(sigkey))[1:]
enkey = unhexlify(highlevelcrypto.privToPub(enkey))[1:]
super(Identity, self).__init__(
self.version, self.stream, sigkey, enkey,
addr, ripe, avg_pow, extra_bytes)
def sign(self, data):
return highlevelcrypto.sign(data, self.priv_sigkey)
def decrypt(self):
pass
def assemble_msg(
fromid, toaddr, subject, message,
friend=False, ttl=86400, encoding=2
):
if ttl > 28 * 24 * 60 * 60:
ttl = 28 * 24 * 60 * 60
# add some randomness to the TTL
ttl = int(ttl + random.randrange(-300, 300))
embedded_time = int(time.time() + ttl)
payload = encodeVarint(fromid.version)
payload += encodeVarint(fromid.stream)
payload += fromid.bitfield
payload += fromid.sigkey + fromid.enkey
if fromid.version >= 3:
payload += encodeVarint(
defaults.networkDefaultProofOfWorkNonceTrialsPerByte if friend
else fromid.avg_pow)
payload += encodeVarint(
defaults.networkDefaultPayloadLengthExtraBytes if friend
else fromid.extra_bytes)
payload += toaddr.ripe
payload += encodeVarint(encoding)
encoded_message = helper_msgcoding.MsgEncode(
{"subject": subject, "body": message}, encoding)
payload += encodeVarint(encoded_message.length)
payload += encoded_message.data
if not protocol.checkBitfield(
toaddr.bitfield, protocol.BITFIELD_DOESACK
):
logger.info(
'Not bothering to include ackdata because'
' the receiver said that they won\'t relay it anyway.'
)
ack_payload = ''
else:
if ttl < 24 * 60 * 60:
ttl = 24 * 60 * 60 # 1 day
elif ttl < 7 * 24 * 60 * 60:
ttl = 7 * 24 * 60 * 60 # 1 week
else:
ttl = 28 * 24 * 60 * 60 # 4 weeks
ttl = int(ttl + random.randrange(-300, 300))
ack_payload = pack('>Q', int(time.time() + ttl)) + \
genAckPayload(toaddr.stream)
ack_payload = protocol.CreatePacket('object', ack_payload)
payload += encodeVarint(len(ack_payload))
payload += ack_payload
logger.info('Payload: %s', hexlify(payload))
header_tmp = pack('>Q', embedded_time) + '\x00\x00\x00\x02' + \
encodeVarint(1) + encodeVarint(toaddr.stream)
signature = fromid.sign(header_tmp + payload)
payload += encodeVarint(len(signature))
payload += signature
encrypted = toaddr.encrypt(payload)
encrypted_payload = header_tmp + encrypted
return encrypted_payload
if __name__ == "__main__":
fromid = Identity(
'93d0b61371a54b53df143b954035d612f8efa8a3ed1cf842c2186bfd8f876665',
'4b0b73a54e19b059dc274ab69df095fe699f43b17397bca26fdf40f4d7400a3a',
'BM-onkVu1KKL2UaUss5Upg9vXmqd3esTmV79', version=2)
# TODO: generate -> [chan] test
toaddr = Identity.fromWIF(
'5JY1CFeeyN4eyfL35guWAuUqu5VLmd7LojtkNP6wmt5msZxxZ57',
'5J1oDgZDicNhUgbfzBDQqi2m5jUPnDrfZinnTqEEEaLv63jVFTM')
print(hexlify(
assemble_msg(
fromid, toaddr,
'hello', 'The quick brown fox jumps over the lazy dog.', True)
))

View File

@ -5,34 +5,39 @@ var TcpTransport = require('bitmessage-transports').TcpTransport;
var eccrypto = require("eccrypto");
(async () => {
const sender = Address({
version: 2, stream: 1,
signPrivateKey: Buffer.from(
'93d0b61371a54b53df143b954035d612f8efa8a3ed1cf842c2186bfd8f876665', 'hex'
),
encPrivateKey: Buffer.from(
'4b0b73a54e19b059dc274ab69df095fe699f43b17397bca26fdf40f4d7400a3a', 'hex'
)}),
recipient = Address.fromPassphrase('test');
const from = Address.fromPassphrase('loremipsum1');
console.log('[from]', from.encode());
console.log('[from sign priv key]', from.signPrivateKey.toString('hex'));
console.log('[from version]', from.version);
console.log('[from stream]', from.stream);
console.log('[from behaviour]', from.behavior);
const toAddr = Address.fromPassphrase('gru');
console.log('[toAddr]', toAddr.encode());
console.log('[toAddr enc pub key]', toAddr.encPublicKey.toString('hex'));
console.log('[toAddr version]', toAddr.version);
console.log('[toAddr stream]', toAddr.stream);
console.log('[toAddr ripe]', toAddr.ripe);
const encodedMsg = await objects.msg.encodePayloadAsync({
ttl: 1800,
from: from,
to: toAddr,
message: 'hey there!',
subject: 'Lorem Ipsum',
console.log('[sender]', sender.encode());
console.log('[recipient]', toAddr.encode());
console.log('[recipient enc pub key]', toAddr.encPublicKey.toString('hex'));
console.log('[recipient version]', toAddr.version);
console.log('[recipient stream]', toAddr.stream);
console.log('[recipient ripe]', toAddr.ripe);
var encodedMsg = await objects.msg.encodePayloadAsync({
ttl: 24 * 60 * 60,
from: sender,
to: recipient,
message: 'The quick brown fox jumps over the lazy dog.',
subject: 'hello',
encoding: 2,
friend: true,
skipPow: true,
// skipPow: true,
});
const strippedMsg = encodedMsg.slice(8);
console.log('[check messages]', strippedMsg);
console.log('[check messages]', strippedMsg.toString('hex'));
console.log('[message]', encodedMsg.toString('hex'));
var d = await objects.msg.decodePayloadAsync(encodedMsg, {
skipPow: true,
identities: toAddr,
// skipPow: true,
identities: recipient,
});
console.log('[decoded]', d.message);
// const encPublicKey = '04a60f6cd97ecd16768215ef059ccfbb1840b736bcdb0763872ddfeef4c417d2ec8439383ce68de9a2b30ad44e9f0e56a13fc2895a6e41f7cf3757e46181d32dd0';