Beispiel #1
0
 def make(cls):
     private = ec.generate_private_key(ec.SECP256K1(), default_backend())
     public_bytes = private.public_key().public_bytes(
         Encoding.X962, PublicFormat.UncompressedPoint)
     private_num = private.private_numbers().private_value
     private_bytes = pad32(int_to_big(private_num))
     return cls(private_bytes, public_bytes[1:])
Beispiel #2
0
def recover(hashes: bytes, sig_vrs):
    r, s, v = sig_vrs
    v = v + 33
    # todo range exception
    x = r
    a = (x * x * x + CURVE.A * x + CURVE.B) % CURVE.P
    b = pow(a, (CURVE.P + 1) // 4, CURVE.P)

    y = b if (b - (v % 2)) % 2 == 0 else CURVE.P - b
    e = int_from_big(hashes)

    mg = ec_mul((CURVE.Gx, CURVE.Gy, 1), (CURVE.N - e) % CURVE.N)
    xy = ec_mul((x, y, 1), s)
    _xy = ec_add(mg, xy)
    Q = ec_mul(_xy, ec_inv(r, CURVE.N))

    p, q = from_jacob(Q)
    return b''.join((pad32(int_to_big(p)), pad32(int_to_big(q))))
Beispiel #3
0
def _encode(data):
    if isinstance(data, Serializer):
        payload = b''.join(_encode(field) for field in data)
        offset_type = 216    # obj
    elif isinstance(data, bytes):
        payload = pad32(data)
        offset_type = 27    # data

    prefix = encode_prefix(len(data), offset_type)
    return prefix + payload
Beispiel #4
0
async def accept_handshake(reader: asyncio.StreamReader,
                           writer: asyncio.StreamWriter, keys, cipher: bytes):
    exchange_random, ephem_pubkey, pubkey = _accept_decode_secret(keys, cipher)

    address, port, *_ = writer.get_extra_info('peername')
    endpoint = EndPoint.make(pubkey, address, port)

    # responder [keys, endpoint, token, (bool) got eip8]

    random = os.urandom(16)
    random_secret = sha3_256(random).digest()
    sequence = pad32(int_to_big32(1))

    ephemeral_keys = ecies.generate_random()
    payload = encode_payload(sequence, ephemeral_keys.public_bytes,
                             random_secret)

    cipher = ecies.encrypt(payload, pubkey)

    return endpoint
Beispiel #5
0
async def _handshake_shared_secret(reader: asyncio.StreamReader,
                                   writer: asyncio.StreamWriter,
                                   endpoint: EndPoint, keys, token):
    ephemeral_keys = ecies.generate_random()

    shared_secret = ecies.make_shared_secret(keys.private_bytes,
                                             endpoint.pubkey)
    random = os.urandom(16)
    random_secret = sha3_256(random).digest()
    sequence = pad32(int_to_big32(0))

    exchange_secret = sha3_256(shared_secret + random_secret +
                               sequence).digest()

    sig = ephemeral_keys.sign(exchange_secret)
    encode_sig = encode_signature(sig)

    # --- temporary
    version = pad16(int_to_big16(1))
    handshake_suffix = pad16(int_to_big16(0))
    # --------------------------------------------- #

    payload = encode_payload(sequence, encode_sig, keys.public_bytes,
                             random_secret, version, handshake_suffix)

    cipher = ecies.encrypt(ephemeral_keys.public_bytes, payload)

    if writer.is_closing():
        raise ConnectionError(
            'during open_connection handling, connection closed')

    writer.write(cipher)
    await writer.drain()

    token.cancellable_wait(reader.read(169), timeout=5)

    if reader.at_eof():
        raise ConnectionError('disconnected')
Beispiel #6
0
def handshake_flows():

    # $ exchange keys $ #

    # peer private, public
    my_keys = ecies.generate_random()
    # ephemeral private, public
    my_ephem_keys = ecies.generate_random()

    # stranger key
    keys = ecies.generate_random()

    # *-- connect --* #

    # my private key, stranger public key = shared secret
    shared_secret = ecies.make_shared_secret(my_keys.private_bytes,
                                             keys.public_bytes)

    random = os.urandom(16)
    nonce = sha3_256(random).digest()
    seq = pad32(int_to_big(0))
    secret = sha3_256(shared_secret + nonce + seq).digest()

    s = my_ephem_keys.sign(secret)
    encode_sig = encode_signature(s)

    # 65, 65, 32, 4, 4
    # signature, public, nonce, version, suffix (170): handshake messages

    encode_payload = b''.join((seq, encode_sig, my_keys.public_bytes, nonce,
                               pad16(int_to_big(1)), pad16(int_to_big(0))))
    cipher = ecies.encrypt(keys.public_bytes, encode_payload)

    # -------------------------------------------------------------------------------#

    # *-- accept --* #
    plain = ecies.decrypt(keys.private_bytes, cipher)
    if plain != encode_payload:
        raise ValueError('plain != payload')
    if len(plain) != 169:
        raise ValueError('payload size error', len(plain))

    # decode payload
    seqe = plain[:4]
    plain = plain[4:]
    accept_sig = plain[:65]
    accept_public = plain[65:129]
    accept_nonce = plain[129:161]
    ve, suff = plain[-4:-2], plain[-2:]

    if ve != b'\x00\x01':
        raise ValueError
    if suff != b'\x00\x00':
        raise ValueError

    # stranger private key, my public key = shared secret
    stranger_shared_secret = ecies.make_shared_secret(keys.private_bytes,
                                                      accept_public)

    accept_secret = sha3_256(stranger_shared_secret + accept_nonce +
                             seqe).digest()
    if accept_secret != secret:
        raise ValueError

    decode_sig = decode_signature(accept_sig)
    if s != decode_sig:
        raise ValueError

    accept_ephem_key = recover(accept_secret, decode_sig)
    handshake_sset = (accept_ephem_key, accept_nonce, accept_public)

    print('verifies:', verifies(accept_secret, decode_sig[:2],
                                accept_ephem_key))
Beispiel #7
0
def encode_signature(sig_vrs):
    r, s, v = sig_vrs
    r_bytes = pad32(int_to_big(r))
    s_bytes = pad32(int_to_big(s))
    v_bytes = int_to_big(v)
    return b''.join((r_bytes, s_bytes, v_bytes))
Beispiel #8
0
def encode_payload(body, mackey, shared, pubkey):
    body_size = pad32(int_to_big(len(body)))
    checksum = sha3_256_mac(mackey, body + body_size + shared)
    payload = [b'\x04' + pubkey, checksum, body, body_size]
    return b''.join(payload)