Compute uniswap pair address via python - python

I`m trying to compute (off-line, i.e. without an http requests) address of an Uniswap pair,
with python, web3 and eth-abi libraries, based on this solidity
example.
address factory = 0x5C69bEe701ef814a2B6a3EDD4B1652CB9cc5aA6f;
address token0 = 0xCAFE000000000000000000000000000000000000; // change me!
address token1 = 0xF00D000000000000000000000000000000000000; // change me!
address pair = address(uint(keccak256(abi.encodePacked(
hex'ff',
factory,
keccak256(abi.encodePacked(token0, token1)),
hex'96e8ac4277198ff8b6f785478aa9a39f403cb768dd02cbee326c3e7da348845f'
))));
Have some thoughts:
hexadem_ ='0x96e8ac4277198ff8b6f785478aa9a39f403cb768dd02cbee326c3e7da348845f'
hexadem_1 = 0xff
abiEncoded_1 = encode_abi_packed(['address', 'address'], ( token_0, token_1 ))
salt_ = web3.Web3.solidityKeccak(['bytes'], ['0x' +abiEncoded_1.hex()])
abiEncoded_2 = encode_abi_packed(['bytes', 'address', 'bytes32'], (bytes(hexadem_1), factory, salt_))
resPair = web3.Web3.solidityKeccak(['bytes','bytes'], ['0x' +abiEncoded_2.hex(), hexadem_])
Can somebody suggest me, what is wrong, which way it should be considered?

Firstly, resPair is too long to be a contract address.
The rules can be explained by reading this: https://eips.ethereum.org/EIPS/eip-1014
Also make sure you enter the two addresses in alphabetical order. Use the .sort() function to do this.
Here is the correct code:
hexadem_ ='0x96e8ac4277198ff8b6f785478aa9a39f403cb768dd02cbee326c3e7da348845f'
hexadem_1 = 0xff
factory = '0x5C69bEe701ef814a2B6a3EDD4B1652CB9cc5aA6f'
abiEncoded_1 = encode_abi_packed(['address', 'address'], ('0x7825e833d495f3d1c28872415a4aee339d26ac88', '0xc02aaa39b223fe8d0a0e5c4f27ead9083c756cc2' )) #these two addresses to be changed as fit. Currently they are TLOS and WETH
salt_ = w3.solidityKeccak(['bytes'], ['0x' +abiEncoded_1.hex()])
abiEncoded_2 = encode_abi_packed([ 'address', 'bytes32'], ( factory, salt_))
resPair = w3.solidityKeccak(['bytes','bytes'], ['0xff' + abiEncoded_2.hex(), hexadem_])[12:]
resPair

You are using wrong hexadem_
Use this one:
hexadem_ = 0x00fb7f630766e6a796048ea87d01acd3068e8ff67d078148a3fa3f4a84f69bd5
See line 298 in the contract source of PancakeRouter
https://bscscan.com/address/0x10ED43C718714eb63d5aA57B78B54704E256024E#code

Related

nodejs crypto-js vs python sha256

I have a problem with crypto-js vs python sha256. It would like to write a nodejs client for duplicati. So I tried to port some python code to js.
https://github.com/Pectojin/duplicati-client/blob/master/auth.py#L136
Javascript
const CryptoJS = require('crypto-js');
function sha256(to_sign) {
var hash = CryptoJS.SHA256(to_sign.toString());
var hashInBase64 = CryptoJS.enc.Base64.stringify(hash);
return hashInBase64.toString('utf-8');
}
let salt = "ZAwQqEAAwR78oZOxFu0nVH2FLy/BnulVxhuu9IOnBwg="
let salt2 = "YQ=="
let password = "abc"
let saltedpwd = sha256(Buffer.concat([Buffer.from(password),Buffer.from(salt,'base64')]));
let saltedpwd2 = sha256(Buffer.concat([Buffer.from(password),Buffer.from(salt2,'base64')]));
let new_password = saltedpwd.toString('base64');
let new_password2 = saltedpwd2.toString('base64');
console.log(new_password)
console.log(new_password2)
returns:
pw1: 0udYFffMXd2QWW9dVXbFl3qp/6lnRcnspr4M1VEtgJA=
pw2: XD9nt/qE374RGDh8rRR5OSmEWlvHwAgMTYMJ03uqaNA=
Python
import base64
import hashlib
import sys
password = "abc"
salt = "ZAwQqEAAwR78oZOxFu0nVH2FLy/BnulVxhuu9IOnBwg="
salt2 = "YQ=="
salt_password = password.encode() + base64.b64decode(salt)
saltedpwd = hashlib.sha256(salt_password).digest()
print (base64.b64encode(saltedpwd).decode('utf-8'))
salt_password2 = password.encode() + base64.b64decode(salt2)
saltedpwd2 = hashlib.sha256(salt_password2).digest()
print (base64.b64encode(saltedpwd2).decode('utf-8'))
returns:
pw1: v9bAzxPatGzA2W7ORkraUvh+nyXotWXItAKpawGSo+A=
pw2: XD9nt/qE374RGDh8rRR5OSmEWlvHwAgMTYMJ03uqaNA=
as you can see, pw2 with the very simple base64 salt is both the same.
the salt from pw1 comes from the duplicati server, so I can't control it...
I've tried some many combinations of encoding, CryptoJS options, so I'm at the point where I will soon stop my 'project'... :(
Can you please give me any advice, what I'm doing wrong? I would be glad about any information.
Regards,
Benjamin
You're 99% of the way there, I think the fix is a one liner (isn't it so often!).
We just have to change
var hash = CryptoJS.SHA256(to_sign.toString());
to
var hash = CryptoJS.SHA256(CryptoJS.lib.WordArray.create(to_sign));
I believe this is because we want to convert directly from the buffer we created by concatenating the password and salt, rather than converting to a string, which is causing the wrong hash to be computed.
In any case, we get the same output as the Python code, which is what we want, ie
v9bAzxPatGzA2W7ORkraUvh+nyXotWXItAKpawGSo+A=
XD9nt/qE374RGDh8rRR5OSmEWlvHwAgMTYMJ03uqaNA=
The new code would look like this in Node.js:
const CryptoJS = require('crypto-js');
function sha256(to_sign) {
var hash = CryptoJS.SHA256(CryptoJS.lib.WordArray.create(to_sign));
var hashInBase64 = CryptoJS.enc.Base64.stringify(hash);
return hashInBase64.toString('utf-8');
}
let salt = "ZAwQqEAAwR78oZOxFu0nVH2FLy/BnulVxhuu9IOnBwg="
let salt2 = "YQ=="
let password = "abc"
let saltedpwd = sha256(Buffer.concat([Buffer.from(password),Buffer.from(salt,'base64')]));
let saltedpwd2 = sha256(Buffer.concat([Buffer.from(password),Buffer.from(salt2,'base64')]));
let new_password = saltedpwd.toString('base64');
let new_password2 = saltedpwd2.toString('base64');
console.log(new_password)
console.log(new_password2)

scapy: get DNSQR / DNSRR field values in symbolic/string form

I'm trying to decode DNS traffic and print query/response data and I'm using python/scapy to decode the packets.
A code snippet:
def dns_sniff_v2(pkt):
if IP in pkt:
if pkt.haslayer(DNS):
dns = pkt.getlayer(DNS)
pkt_time = pkt.sprintf('%sent.time%')
if pkt.haslayer(DNSQR):
qr = pkt.getlayer(DNSQR) # DNS query
values = [ pkt_time, str(ip_src), str(ip_dst), str(dns.id), str(qr.qname), str(qr.qtype), str(qr.qclass) ]
print "|".join(values)
sniff(iface="eth0", filter="port 53", prn=dns_sniff_v2, store=0)
The problem is that qr.qtype or qr.qclass is getting me the enum's internal int representation (1) instead of the symbolic string value ("A", or "IN"). The same applies to the DNSRR section of response packets.
How can I get a DNSQR or DNSRR field in the symbolic form?
You can get the symbolic string value of qr.qtype and of qr.qclass by invoking the following:
qr.get_field('qtype').i2repr(qr, qr.qtype)
qr.get_field('qclass').i2repr(qr, qr.qclass)
Note that rather than invoking qr.get_field('qtype') and qr.get_field('qclass') over and over again, you can invoke it once in advance:
qtype_field = qr.get_field('qtype')
qclass_field = qr.get_field('qclass')
...
qtype_field.i2repr(qr, qr.qtype)
qclass_field.i2repr(qr, qr.qclass)

Boto / Cloudwatch recover instance alarm

I've been banging my head against a wall trying to make this work.
I'm attempting to use python/boto to create a cloutwatch alarm that recovers a failed ec2 instance.
I'm having difficulty in getting the ec2:RecoverInstance action to work. I suspect my topic isn't setup correctly.
topics = sns_conn.get_all_topics()
topic = topics[u'ListTopicsResponse']['ListTopicsResult']['Topics'][0]['TopicArn']
# arn:aws:sns:us-east-1:*********:CloudWatch
status_check_failed_alarm = boto.ec2.cloudwatch.alarm.MetricAlarm(
connection=cw_conn,
name=_INSTANCE_NAME + "RECOVERY-High-Status-Check-Failed-Any",
metric='StatusCheckFailed',
namespace='AWS/EC2',
statistic='Average',
comparison='>=',
description='status check for %s %s' % (_INSTANCE, _INSTANCE_NAME),
threshold=1.0,
period=60,
evaluation_periods=5,
dimensions={'InstanceId': _INSTANCE},
# alarm_actions = [topic],
ok_actions=[topic],
insufficient_data_actions=[topic])
# status_check_failed_alarm.add_alarm_action('arn:aws:sns:us-east-1:<acct#>:ec2:recover')
# status_check_failed_alarm.add_alarm_action('arn:aws:sns:us-east-1:<acct#>:ec2:RecoverInstances')
status_check_failed_alarm.add_alarm_action('ec2:RecoverInstances')
cw_conn.put_metric_alarm(status_check_failed_alarm)
Any suggestions would be highly appreciated.
Thank you.
--MIke
I think the issue is these alarm actions do not have <acct> in the arn. The cli reference documents the valid arns:
Valid Values: arn:aws:automate:region:ec2:stop | arn:aws:automate:region:ec2:terminate | arn:aws:automate:region:ec2:recover
I would think it is easier to pull the metric from AWS and create an alarm from that rather than trying to construct it from the ground up, e.g. (untested code):
topics = sns_conn.get_all_topics()
topic = topics[u'ListTopicsResponse']['ListTopicsResult']['Topics'][0]['TopicArn']
metric = cloudwatch_conn.list_metrics(dimensions={'InstanceId': _INSTANCE},
metric_name="StatusCheckFailed")[0]
alarm = metric.create_alarm(name=_INSTANCE_NAME + "RECOVERY-High-Status-Check-Failed-Any",
description='status check for {} {}'.format(_INSTANCE, _INSTANCE_NAME),
alarm_actions=[topic, 'arn:aws:automate:us-east-1:ec2:recover'],
ok_actions=[topic],
insufficient_data_actions=[topic],
statistic='Average',
comparison='>=',
threshold=1.0,
period=60,
evaluation_periods=5)

Dpkt lib - how to add timestamp to packet

So I am trying to create my own pcap file, I've created a msg using dpkt but I am not understanding how to maneuver timestamp, from what I've seen it is the 3rd parameter in writepkt but I don't understand how to initial the variable.. this is a part of my code
output_pcapfile = dpkt.pcap.Writer(open(__file__+'.pcap','wb'))
tcpSrc.data = 'Some data\r\n'
ipSrc.data = tcpSrc
ipSrc.len = len(str(ipSrc))
ethSrc.data = ipSrc
packet_count = 1
output_pcapfile.writepkt(ethSrc,packet_count) # somehow get timestamp for third parameter!!
Anyone has an idea? thanks !
looking at the 1.7 source for pcap.py,
I see:
def writepkt(self, pkt, ts=None):
if ts is None:
ts = time.time()
#some more code..
This function takes two non-self arguments
The timestamp will be created if you only pass in the pkt itself, e.g.
output_pcapfile.writepkt(ethSrc)

How do you determine if an IP address is private, in Python?

In Python, what is the best way to determine if an IP address (e.g., '127.0.0.1' or '10.98.76.6') is on a private network? The code does not sound difficult to write. But there may be more edge cases than are immediately apparent, and there's IPv6 support to consider, etc. Is there an existing library that does it?
Since Python 3.3 there is an ipaddress module in the stdlib that you can use.
>>> import ipaddress
>>> ipaddress.ip_address('192.168.0.1').is_private
True
If using Python 2.6 or higher I would strongly recommend to use a backport of this module.
Check out the IPy module. If has a function iptype() that seems to do what you want:
>>> from IPy import IP
>>> ip = IP('127.0.0.0/30')
>>> ip.iptype()
'PRIVATE'
You can check that yourself using
https://www.rfc-editor.org/rfc/rfc1918 and https://www.rfc-editor.org/rfc/rfc3330. If you have 127.0.0.1 you just need to & it with the mask (lets say 255.0.0.0) and see if the value matches any of the private network's network address. So using inet_pton you can do: 127.0.0.1 & 255.0.0.0 = 127.0.0.0
Here is the code that illustrates that:
from struct import unpack
from socket import AF_INET, inet_pton
def lookup(ip):
f = unpack('!I',inet_pton(AF_INET,ip))[0]
private = (
[ 2130706432, 4278190080 ], # 127.0.0.0, 255.0.0.0 https://www.rfc-editor.org/rfc/rfc3330
[ 3232235520, 4294901760 ], # 192.168.0.0, 255.255.0.0 https://www.rfc-editor.org/rfc/rfc1918
[ 2886729728, 4293918720 ], # 172.16.0.0, 255.240.0.0 https://www.rfc-editor.org/rfc/rfc1918
[ 167772160, 4278190080 ], # 10.0.0.0, 255.0.0.0 https://www.rfc-editor.org/rfc/rfc1918
)
for net in private:
if (f & net[1]) == net[0]:
return True
return False
# example
print(lookup("127.0.0.1"))
print(lookup("192.168.10.1"))
print(lookup("10.10.10.10"))
print(lookup("172.17.255.255"))
# outputs True True True True
another implementation is to compute the int values of all private blocks:
from struct import unpack
from socket import AF_INET, inet_pton
lookup = "127.0.0.1"
f = unpack('!I',inet_pton(AF_INET,lookup))[0]
private = (["127.0.0.0","255.0.0.0"],["192.168.0.0","255.255.0.0"],["172.16.0.0","255.240.0.0"],["10.0.0.0","255.0.0.0"])
for net in private:
mask = unpack('!I',inet_aton(net[1]))[0]
p = unpack('!I',inet_aton(net[0]))[0]
if (f & mask) == p:
print lookup + " is private"
This is the fixed version of the regex approach suggested by #Kurt including the fix recommended by #RobEvans
^127.\d{1,3}.\d{1,3}.\d{1,3}$
^10.\d{1,3}.\d{1,3}.\d{1,3}$
^192.168.\d{1,3}.\d{1,3}$
^172.(1[6-9]|2[0-9]|3[0-1]).[0-9]{1,3}.[0-9]{1,3}$
def is_ip_private(ip):
# https://en.wikipedia.org/wiki/Private_network
priv_lo = re.compile("^127\.\d{1,3}\.\d{1,3}\.\d{1,3}$")
priv_24 = re.compile("^10\.\d{1,3}\.\d{1,3}\.\d{1,3}$")
priv_20 = re.compile("^192\.168\.\d{1,3}.\d{1,3}$")
priv_16 = re.compile("^172.(1[6-9]|2[0-9]|3[0-1]).[0-9]{1,3}.[0-9]{1,3}$")
res = priv_lo.match(ip) or priv_24.match(ip) or priv_20.match(ip) or priv_16.match(ip)
return res is not None
This will not 100.x.x.x range which is used internally in kubernetes
A few days after asking this question, I found out about this Google project, ipaddr-py, which appears to have some of the same functionality with respect to determining if an address is private (is_rfc1918). Apparently this will be standard in Python 3.1.
I find this in cuckoo.There is no need to install new modules.Just import two built-in modules: socket and struct. And use function below.
def _is_private_ip(self, ip):
"""Check if the IP belongs to private network blocks.
#param ip: IP address to verify.
#return: boolean representing whether the IP belongs or not to
a private network block.
"""
networks = [
"0.0.0.0/8",
"10.0.0.0/8",
"100.64.0.0/10",
"127.0.0.0/8",
"169.254.0.0/16",
"172.16.0.0/12",
"192.0.0.0/24",
"192.0.2.0/24",
"192.88.99.0/24",
"192.168.0.0/16",
"198.18.0.0/15",
"198.51.100.0/24",
"203.0.113.0/24",
"240.0.0.0/4",
"255.255.255.255/32",
"224.0.0.0/4",
]
for network in networks:
try:
ipaddr = struct.unpack(">I", socket.inet_aton(ip))[0]
netaddr, bits = network.split("/")
network_low = struct.unpack(">I", socket.inet_aton(netaddr))[0]
network_high = network_low | 1 << (32 - int(bits)) - 1
if ipaddr <= network_high and ipaddr >= network_low:
return True
except Exception,err:
continue
return False
If you want to avoid importing a module you can just apply a simple regex:
^127.\d{1,3}.\d{1,3}.\d{1,3}$
^10.\d{1,3}.\d{1,3}.\d{1,3}$
^192.168.\d{1,3}$
^172.(1[6-9]|2[0-9]|3[0-1]).[0-9]{1,3}.[0-9]{1,3}$

Categories