Experiment: Running a UDP socket [client/server] ARP broadcaster for each WiFi AP (better client association tracking)

If you are running multiple WiFI APs that are part of the same flat network and bridged together it can be tricky keeping a current list of which client is connected to which AP (sometimes clients can just stop responding on one AP and then wake up and appear on another AP). In addition, the one common question a router needs to know is, is this client connected to me OR are they connected through one of my peer routers and which one is the best one?… I wrote a small service which allows an AP to periodically broadcast out, relay/forward, and receive the current WiFi client associations it has and the best association is chosen to amongst all the APs to be able to keep a common set of ARP entries for each access point! The tables are way cleaner and way more consistent with each other now that I have this thing running. I wrote it in both C and python which are supported on OpenWRT routers and can communicate with each other using a common key/pwd. You simply list which radio interfaces the AP has and the IP address you gave the AP on the flat network and it should be ready to send, forward, & receive ARP related messages. The program will write out a standard file with the following information formatted in it and it can also be used with the relayd service modification post below:

/tmp/arp.txt: [dev] [mac/peer] [ip]
wlan1 00:11:22:dd:ee:ff 192.168.100.123

The code can be found here if you are interested!:

C: https://github.com/stoops/broadarp/blob/init/barp.c
Py2: https://github.com/stoops/broadarp/blob/python/barp.py
relayd-mod: https://github.com/stoops/relayd/compare/master…stoops:merged [blog post]

🙂
Jon C

Experiment: Running a UDP socket [client/server] ARP broadcaster for each WiFi AP (better client association tracking)

Modifying the OpenWRT relayd package C source code to help set better static ARP entries (ATF_PERM)

If you are bridging 2+ wireless networks together, it can get tricky for the ARP mappings to take place efficiently throughout the network as you move around from AP to AP. I wrote a small shell script that runs on each router which reports in its WiFi-AP associations & DHCP entries that are part of the overall /20 network. This client mapping data is sent around to each router to determine who has the proper client and where/how to find them. I noticed that the relayd bridging app was putting in ARP entries that were becoming stale/incorrect over time as you moved around so I modified it’s source code to outsource this work to a file that has an updated master set of static interface entries based on each DHCP/WIFI association for each router on the network.

(I lost access to my fossjon github account due to 2-factor auth being lost)

https://github.com/stoops/relayd/compare/master…stoops:merged

(the steps to compile this on a armv7l router itself are in the README I added)

For example, a shell script running on the router (with all the relevant network information) can determine and write out a small mapping file that this modified framework can use to keep a cleaner and better ARP tableset (/tmp/arp.txt):

wlan1 00:2b:3d:5a:4a:9e 192.168.18.103

The added capability in relayd will then ensure that for any of the bridged interfaces listed, the only ARP entry that will exist is for the one specified in the file and that it will be set to permanent status instead (deletion of incorrect entries added in).

I am running this as a test on my parents home network to see how long it lasts for, modifying C is tricky for me! 🙂

Modifying the OpenWRT relayd package C source code to help set better static ARP entries (ATF_PERM)

dnsmasq dhcp mac address hashing algorithm

So during this quarantine break I was setting up a new network layout for my parents place which includes 2 wireless OpenWRT routers connected together via an 802.11ac channel. Each wifi router broadcasts an 802.11n AP which has the same SSID & KEY but on different CHANNELS and BSSIDS. The traffic can be forwarded back and forth between the 2 separate APs via the single private AC connection (using the OWRT relayd package):

/usr/sbin/relayd -I wlan1 -I wlan0 -t -1 -p -1 -B

Each AP has dnsmasq running, however, they are each set to hand out a subset of unique addresses that are shared in a /20 block (so that whatever AP you are on, you can communicate to any other host on any of the APs as if you are on the same network). I noticed that when switching between the 2 APs, my machine was getting the same last octet in the IP range set! I thought this was pretty cool because even though the rest of the IP prefix was different, I could simply memorize the last digits if I wanted to connect to another machine on the network in the future. I then started looking into dnsmasq’s source code to see how it was doing this since the only info DHCP usually has is one’s MAC address:

https://github.com/dnsmasq/dnsmasq/blob/master/src/dhcp.c#L638

…note: they added a fix for the j variable recently: j= instead of j+=…
…note: note: there is a IP loop and epoch counter variable that gets increased in case of any hashing collisions or errors that occur!

So if you compile the code below and want to pre-calculate your likely IP address when asking dnsmasq for one, you can run the following (you need to know the IP range that was given in your configs):

$ a="11:22:33:44:55:66"
$ b=$(echo "$a" | sed -e 's/^/\\x/' -e 's/:/\\x/g')
$ c=$(printf "${b}")
$ ./dd "$c" 6 192.168.17.101 192.168.17.190

[192.168.17.106] [3842235635] [6]

---

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <arpa/inet.h>

int main(int argc, char *argv[])
{
	int i, l=atoi(argv[2]);
	unsigned int j, e=0;
	struct in_addr temp, addr;
	struct sockaddr_in beg, end;
	unsigned char *hwaddr = (unsigned char *)argv[1];

	for (j = 0, i = 0; i < l; i++) {
		j = hwaddr[i] + (j << 6) + (j << 16) - j;
	}

	int pass;
	for (pass = 0; pass <= 1; pass++) {
		inet_pton(AF_INET, argv[3], &(beg.sin_addr));
		inet_pton(AF_INET, argv[4], &(end.sin_addr));
		temp.s_addr = htonl(ntohl(beg.sin_addr.s_addr) + 
					 ((j + e) % (1 + ntohl(end.sin_addr.s_addr) - ntohl(beg.sin_addr.s_addr))));
		addr = temp;
		do {
			addr.s_addr = htonl(ntohl(addr.s_addr) + 1);
			if (addr.s_addr == htonl(ntohl(end.sin_addr.s_addr) + 1))
				addr = beg.sin_addr;
		} while (addr.s_addr != temp.s_addr);
	}

	char str[64];
	bzero(str, 64 * sizeof(char));
	inet_ntop(AF_INET, &(addr.s_addr), str, INET_ADDRSTRLEN);

	printf("[%s] [%u] [%d]\n", str, j, l);
	return 0;
}

dnsmasq dhcp mac address hashing algorithm

Playing around with XOR (my fav operation) during the holidays

# cipher design notes:
## purpose?
### cheap single byte keyed stream cipher
### cheaply obfuscate data based on a simple password
### use a simple language with as few lines & dependencies as possible
## internal key setup:
### produce a random byte for every pw byte (KEY IV)
### generate a secret internal state byte for every pw byte (KEY HASH):
#### loop through the each pw byte & mix together its random byte & a counter value
#### set the final looped result as the state byte for that key byte
#### order the operations used to try & reduce getting a null byte output
#### end the internal state byte with the current counter value mixed in (CBC MODE)
## message cipher steps:
### use the looped key counter above as an index to get a key list item
### XOR the message byte with each byte in key item: random byte, pwd byte, state byte
### mix the cipher byte in with the internal state byte (new secret internal state)
### XOR the prior internal state byte with the cipher byte (cipher output)
## notes:
### this does not prevent or detect bit-flipping (integrity with a hash function)
import sys, random
def h(n):
  sys.stdout.write(hex(n).replace("x","")[-2:])
i=0xff; j=0x00; l=len(sys.argv[1]); s=sys.stdin.read()
if (s[:2]=="ff"):
  r=s[2:2+(l*2)]; t=s[2+(l*2):].strip()
  s="".join([chr(int(t[x:x+2],16)) for x in range(0,len(t),2)])
  k=[[int(r[x*2:(x*2)+2],16), ord(sys.argv[1][x])] for x in range(0,l)]
else:
  k=[[random.randint(0x00, 0xff), ord(d)] for d in sys.argv[1]]
  h(i); z=[h(d[0]) for d in k]; r=""
for e in k:
  for d in k:
    i=(((i+j)*(d[0]^d[1]))%256); j=((j+1)%256)
  e.append(i); i=((i+j)%256); j=((j+1)%256)
j=0
for c in s:
  p=ord(c); m=k[j%l]; o=(((p^m[0])^m[1])^m[2]); j=(j+1); n=(j%256)
  if (r==""):
    t=i; i=((k[o%l][0]+o+n)%256); o=(o^t); h(o)
  else:
    d=(p^i); t=i; i=((k[d%l][0]+d+n)%256); o=(o^t); sys.stdout.write(chr(o))

Cipher testing output (Message: 000000, Key: 000000):

a=$(echo '000000' | python ~/tmp/en.py "000000") ; echo "Cipher-Out: [$a]" ; \
k="000000" ; echo -n "Decrypt-Test[$k]: " ; echo "$a" | tr -d '|' | python ~/tmp/en.py "$k" ; \
for x in 1 2 3 ; do
k="00000$x" ; echo -n "Bad-Key-Test[$k]: "
echo "$a" | tr -d '|' | python ~/tmp/en.py "$k" | xxd | sed -e 's/^[^ ]* //' | sed -e 's/  [ ]*/|/g' | sed -e 's/\(..[ |]\)/ \1/g' | tr -s ' '
done
Cipher-Out: [ff372f4ca01971de08925718521c]
Decrypt-Test[000000]: 000000
Bad-Key-Test[000001]: 70 b0 bf f0 cc 98 0e|p......
Bad-Key-Test[000002]: 6c e0 ac c5 9d 59 54|l....YT
Bad-Key-Test[000003]: 5c 50 e0 c3 da a8 1f|\P.....
Playing around with XOR (my fav operation) during the holidays

Python: Layer-3 tunnel device traffic under client & server TCP sockets

# notes: PoC, single threaded, single client, single interface, single address, ipv4 over tcp
# 
# server: python tun.py -s 0.0.0.0 31337 key
#   ('[conn]:new', [socket._socketobject object at 0xb6b20c00], ('192.168.160.241', 64227))
#   ('[auth]:good', [socket._socketobject object at 0xb6b20c00])
# 
# client: python tun.py -c 1.2.3.4 31337 key
#   client: route add -host 1.2.3.4 [real gateway]
#   client: route add -net 0.0.0.0/0 10.0.0.1
#   client: host yahoo.com 4.2.2.1
#!/usr/bin/python

import os, sys
import ctypes, fcntl, struct
import select, socket, subprocess
import time, random, hashlib

def tclose(sobj):
	try:
		sobj.close()
	except:
		pass

def ksa4(k):
	s = []
	for i in range(0, 256):
		s.append(i)
	j = 0
	l = len(k)
	for i in range(0, 256):
		j = ((j + s[i] + ord(k[i % l])) % 256)
		t = s[i]; s[i] = s[j]; s[j] = t
	return (s, 0, 0)

def arc4(m, k):
	(s, i, j) = k
	l = len(m)
	o = ""
	for x in range(0, l):
		i = ((i + 1) % 256)
		j = ((j + s[i]) % 256)
		t = s[i]; s[i] = s[j]; s[j] = t
		c = s[(s[i] + s[j]) % 256]
		o += chr(ord(m[x]) ^ c)
	k = (s, i, j)
	return (o, k)

def set4(n, k):
	if (n == ""):
		n = (str(time.time()) + ":" + str(random.random()) + "-")
	s = ksa4(n + "s" + k)
	r = ksa4(n + "r" + k)
	(null, s) = arc4("x"*4096, s)
	(null, r) = arc4("x"*4096, r)
	return (n, s, r)

def client(h, p, n, k):
	f = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
	f.connect((h, p))
	(enc, k) = arc4(n, k)
	f.send(n + enc)
	return (f, k)

# initialize some common variables
BUFFER_SIZE = 2000
PR_MODE = "client"
PR_HOST = "1.2.3.4"
PR_PORT = 31337
PR_SKEY = "key"
OS_TYPE = sys.platform
IF_CMD = ["/sbin/ifconfig", "tun0", "10.0.0.1", "10.0.0.2", "up"]

# process command line args usage: tun.py mode:[-c,-s] ip:[0.0.0.0] port:[4321] secret:[key]
if (sys.argv[1] == "-s"):
	PR_MODE = "server"
PR_HOST = sys.argv[2]
PR_PORT = int(sys.argv[3])
PR_SKEY = sys.argv[4]

# initialize the clients secret key state
last = 0
(nonce, skey, rkey) = set4("", PR_SKEY)

# define the remote connection socket descriptors - tcp client or tcp server
srv_fd = None
net_fd = None
if (PR_MODE == "client"):
	tmp = IF_CMD[2]
	IF_CMD[2] = IF_CMD[3]
	IF_CMD[3] = tmp
	(net_fd, skey) = client(PR_HOST, PR_PORT, nonce, skey)
else:
	srv_fd = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
	srv_fd.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
	srv_fd.bind(("0.0.0.0", PR_PORT))
	srv_fd.listen(1)

# determine how to bring up the tun0 interface - mac or linux
if (OS_TYPE == "darwin"):
	tun_fd = os.open("/dev/tun0", os.O_RDWR)
else:
	TUNSETIFF = 0x400454ca
	IFF_TUN = 0x0001
	IFF_TAP = 0x0002
	IFF_NO_PI = 0x1000
	
	tun_fd = os.open("/dev/net/tun", os.O_RDWR)
	ifr = struct.pack("16sH", "tun0", IFF_TUN | IFF_NO_PI)
	fcntl.ioctl(tun_fd, TUNSETIFF, ifr)
	
	IF_CMD.insert(3, "pointopoint")
subprocess.call(IF_CMD)

# main processing loop for network traffic tunneling
conns = []
while (1):
	#print("loop")
	
	# set the list of available socket descriptors to listen for
	fd_list = [tun_fd]
	if (srv_fd):
		fd_list.append(srv_fd)
	if (net_fd):
		fd_list.append(net_fd)
	for conn in conns:
		fd_list.append(conn)
	
	# select the available fds ready for reading
	rd = select.select(fd_list, [], [])
	
	# loop through each socket now to process each action
	for ready_fd in rd[0]:
		# if we are reading from our tun device then encrypt the message and write it to the network socket
		if (ready_fd == tun_fd):
			packet = os.read(tun_fd, BUFFER_SIZE)
			plen = len(packet)
			if ((plen > 0) and (net_fd)):
				(enc, skey) = arc4(packet, skey)
				smac = str(skey)
				hmac = hashlib.sha256(smac + enc + smac).digest()
				net_fd.send(enc + hmac)
		
		# if the server gets a new client connection then add it to a list to be authenticated next
		if (ready_fd == srv_fd):
			(conn, addr) = srv_fd.accept()
			print("[conn]:new",conn,addr)
			conns.append(conn)
		
		# if we get a network message decrypted and authenticated then write it to our tunnel device
		if (ready_fd == net_fd):
			data = net_fd.recv(BUFFER_SIZE)
			dlen = len(data)
			if (dlen > 0):
				try:
					temp = data[:-32]
					(dec, tkey) = arc4(temp, rkey)
					tmac = str(tkey)
					hmac = hashlib.sha256(tmac + temp + tmac).digest()
					if (hmac == data[-32:]):
						rkey = tkey
						os.write(tun_fd, dec)
					else:
						print("[hmac]:fail",hmac,data[-32:])
				except:
					dlen = 0
			if (dlen < 1):
				tclose(net_fd)
				net_fd = None
		
		# loop through any unauthenticated clients who have sent us data
		tmps = []
		conl = (len(conns) - 1)
		while (conl > -1):
			conn = conns[conl]
			
			# if the connection is ready
			if (ready_fd == conn):
				data = conn.recv(BUFFER_SIZE)
				dlen = len(data)
				indx = data.find("-")
				
				# if they sent us some actual data
				if ((dlen > 0) and (indx > -1)):
					# try to decrypt the nonce and verify an increase in the time
					try:
						temp = float(data.split(":")[0])
					except:
						temp = 0
					(tnonce, trkey, tskey) = set4(data[:indx+1], PR_SKEY)
					(dec, trkey) = arc4(data[indx+1:], trkey)
					
					# if the auth succeeds then setup the new key state and set the new client socket
					if ((temp > last) and (tnonce == dec)):
						print("[auth]:good",conn)
						
						nonce = tnonce
						skey = tskey
						rkey = trkey
						
						tclose(net_fd)
						net_fd = conn
						
						last = temp
						conns[conl] = None
					else:
						dlen = 0
				else:
					dlen = 0
				
				# if the auth failed then remove the client now
				if (dlen < 1):
					print("[auth]:fail",conns[conl])
					tclose(conns[conl])
					conns[conl] = None
			
			if (conns[conl]):
				tmps.append(conns[conl])
			conl -= 1
		
		conns = tmps[:]

Python: Layer-3 tunnel device traffic under client & server TCP sockets

Agile development w/ CI/CD – Automated cloud building & deployment (from scratch)

So I went to an interview recently and I was asked on the spot how I would implement an entire agile development platform, end-to-end, with specific details, (no requirements listed) – and it had to be cloud friendly/scalable! I was running different ideas through my head because it was a fairly open ended question and I felt like it deserved more thought than I could provide in just the 30 minutes given to me…

There are a dozen different ways this can be achieved but I wanted to post an example proof-of-concept of the essential steps needed to accomplish something like this. There are basically 5 different pieces to this puzzle that need to be solved:

  1. The developers need a central repository with local branching capabilities so they can test different versions of their changes on demand
  2. They need to be able to take an automatic snapshot of their code base that they are currently working on so they can specify which change they want to test
  3. They need a simple mechanism, which when triggered, takes that code-change snapshot and sends it to a build server for compilation
  4. The build server, when finished, should deploy and run their compiled test code, usually in a temporary, clean, isolated environment like a vm
  5. The build server returns a simple and unique URL pointing to their new test instance so the developer can easily see and test their desired changes

Example Tech Env: GIT, SSH, NetCat, Bash Scripts, Java

Components Workflow:

  • Developer (java)
  • Central Repo (git/ssh)
  • Automatic Snapshot Transfer (netcat)
  • Automatic Building (javac)
  • Automatic Deployment (bash script)
  • Temporary Test Instance (netcat website)

 

[devops engineer setup]

git init
git add project
git commit -a

# setup initial supporting scripts

 

[developer]

# get the code
git clone ssh://[email protected]:/home/git/projects

# make a change
cd project/
vim src/program.java
# @@ -11,5 +11,6 @@ public class program {
#  			System.out.println(x+": "+resList.get(x));
#  		}
# +		System.out.println("Changed!");
#  	}
#  }

./make.sh # magic!
# this script tar's up the current code and connects to the server to run an init.sh bootstrap script
# the init.sh script chooses an initial random port and calls the deploy.sh script
#   to perform the snapshot code transfer
# the deploy.sh script opens a netcat port to receive the snapshot'd code
#   and then runs build.sh on the result (port is closed after)
# the build.sh script opens a netcat port to communicate the build results
#   and then runs a http netcat instance of the executed code for the developer to test/visit

 

[automated build, deploy, test instance]

Extracting build...
./src/
./src/dep.java
./src/program.java
Extraction completed!

Building started...
Build completed!


Visit the build URL below:
http://192.168.161.2:29792/testing

[example web change test output]

Fri Nov 11 05:22:10 UTC 2016

0: [A, D]
1: [B, E]
2: [C, F]
Changed!

Completed!

 

[project file tree layout]

project/
|-- make.sh
|-- init.sh
|-- deploy.sh
|-- build.sh
`-- src
    |-- dep.java
    |-- lib
    `-- program.java

 

[script source code]

[make.sh]

#!/bin/bash
tar -czf snapshot.tgz ./src
USRN=`git config --get remote.origin.url | sed -e 's/@.*$//' -e '[email protected]^.*/@@'`
REPO=`git config --get remote.origin.url | sed -e 's/^.*://'`
PROJ="project"
PORT=`ssh "${USRN}@buildsrv" "${REPO}/${PROJ}/init.sh"`
false
while [ $? -ne 0 ] ; do
	sleep 1
	nc buildsrv "$PORT" < snapshot.tgz
done
rm snapshot.tgz
let PORT="$PORT + 1"
false
while [ $? -ne 0 ] ; do
	sleep 1
	nc buildsrv "$PORT"
done

[init.sh]

#!/bin/bash

DIR=$(dirname "$0")
let PORT="1028 + ( $RANDOM % 64000 )"

nohup "$DIR/deploy.sh" "$PORT" > /dev/null 2> /dev/null < /dev/null &
echo "$PORT"

[deploy.sh]

#!/bin/bash

DIR=$(dirname "$0")
PORT="$1"

TMP="/tmp/build.`date '+%s'`"

mkdir -p "$TMP/"
nc -l -p "$PORT" -w 30 > "$TMP/src.tgz"

if [ -s "$TMP/src.tgz" ] ; then
	let PORT="$PORT + 1"
	"$DIR/build.sh" "$PORT" "$TMP" | nc -l -p "$PORT" -w 30 -q 1
fi

[build.sh]

#!/bin/bash

export PATH="/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin"

let PORT="$1 + 1"
TMP="$2"

echo
echo "Extracting build..."
cd "$TMP/"
tar -xzvf "src.tgz"
cd src/
echo "Extraction completed!"
echo
echo "Building started..."
javac -d . dep.java 2>&1
javac -cp . program.java 2>&1
echo "Build completed!"
echo

GW=`netstat -nr | grep -i '^0.0.0.0' | awk '{ print $2 }' | cut -c 1-4`
IP=`ifconfig | grep -i "inet addr:$GW" | awk '{ print $2 }' | sed -e 's/^[^:]*://'`

echo
echo "Visit the build URL below:"
echo "http://${IP}:${PORT}/testing"
echo

( echo -e 'HTTP/1.1 200 OK\r\n\r\n' ; date ; echo ; java program ; echo ; echo 'Completed!' ) | nohup nc -l -p "$PORT" -w 60 -q 1 > /dev/null 2> /dev/null &

[src/dep.java]

package lib;
import java.util.*;
public class dep {
	public dep() {
	}
	public static ArrayList merge(ArrayList listA, ArrayList listB) {
		ArrayList outList = new ArrayList();
		for (int x = 0; x < listA.size(); ++x) {
			ArrayList tmpList = new ArrayList();
			tmpList.add(listA.get(x));
			tmpList.add(listB.get(x));
			outList.add(tmpList);
		}
		return outList;
	}
}

[src/program.java]

import java.util.*;
import lib.dep;
public class program {
	public static void main(String[] args) {
		ArrayList inA = new ArrayList();
		ArrayList inB = new ArrayList();
		inA.add("A"); inA.add("B"); inA.add("C");
		inB.add("D"); inB.add("E"); inB.add("F");
		dep help = new dep();
		ArrayList resList = help.merge(inA, inB);
		for (int x = 0; x < resList.size(); ++x) {
			System.out.println(x+": "+resList.get(x));
		}
	}
}
Agile development w/ CI/CD – Automated cloud building & deployment (from scratch)

OpenWRT dhcp-lease file arping-based host-removal (dnsmasq)

To help prevent DHCP starvation DoS attacks (not fool-proof though if you can fake ARP replies back)

rm /tmp/arp.*
cat /tmp/dhcp.leases | awk '{ print $3 }' | while read a ; do
  ( arping -f -q -c 1 -w 1 -I br-lan "$a" ; if [ $? -ne 0 ] ; then echo "$a" > /tmp/arp.host."$a" ; fi ) &
done
sleep 3
cat /tmp/arp.host.* | while read a ; do
  sed "/^.*$a.*$/d" -i /tmp/dhcp.leases
  touch /tmp/arp.run
done
if [ -f /tmp/arp.run ] ; then
  kill `ps | grep -i 'dnsmasq' | grep -iv 'grep' | awk '{ print $1 }'`
  /usr/sbin/dnsmasq -C /var/etc/dnsmasq.conf -k -x /var/run/dnsmasq/dnsmasq.pid &
fi
rm /tmp/arp.*
OpenWRT dhcp-lease file arping-based host-removal (dnsmasq)

Having fun with numbers & Python – Randomization & Shuffling – Stream Cipher

import sys,time
def hexs(s):
	o = ""
	for c in s:
		h = hex(ord(c))[2:]
		if (len(h) < 2):
			h = ("0" + h)
		if (o != ""):
			o += ":"
		o += h
	return o
def nice(s):
	o = ""
	for i in range(0, len(s)):
		if (i > 0):
			if ((i % 16) == 0):
				o += "\n  "
			else:
				o += ":"
		t = str(s[i])
		while (len(t) < 3):
			t = ("0" + t)
		o += t
	return o
def rnds():
	n = 2; s = ""
	while ((int(time.time()) % n) != 0):
		pass
	while (len(s) != 32):
		time.sleep(1)
		r = 0
		while ((int(time.time()) % n) != 0):
			r = (r + 1)
		#sys.stderr.write("r="+str(r)+"\n");break
		s = (s + chr((r >> 8) & 0xff) + chr(r & 0xff))
	return s
if (len(sys.argv) < 2):
	h = rnds()
	sys.stderr.write("k="+hexs(h)+"\n")
else:
	def keys(k):
		s = []
		for x in range(0, 256):
			s.append(x)
		for y in range(0, len(k)):
			l = ord(k[y])
			for x in range(0, 256):
				t = s[x] ; s[x] = s[l] ; s[l] = t
				l = ((l + x) % 256)
		return s
	s = keys(sys.argv[1])
	if (len(sys.argv) > 2):
		sys.stderr.write("s="+nice(s)+"\n\n")
	def ciph(m, s, z):
		j = 0; o = ""
		for y in range(0, len(m)):
			l = ord(m[y])
			c = (l ^ s[y % 256])
			o += chr(c)
			i = l
			if (z == "d"):
				i = c
			j = ((j ^ i) % 256)
			for x in range(0, 256):
				t = s[x] ; s[x] = s[j] ; s[j] = t
				j = ((j + x) % 256)
		return o
	if (len(sys.argv) < 3):
		m = sys.stdin.read()
		z = "d"
	else:
		m = sys.argv[2]
		z = "e"
	o = ciph(m, s, z)
	if (len(sys.argv) > 2):
		sys.stderr.write("m="+hexs(o)+"\n")
	sys.stdout.write(o)

$ clear ; echo ; python fun.py ; python fun.py ; echo ; python fun.py key msg | python fun.py key ; echo

k=74:ed:3c:1d:62:72:92:61:3c:27:f8:7c:c4:98:92:47:0d:18:c0:47:a6:44:b6:13:19:5c:90:30:4b:23:cf:12
k=fd:e7:4d:1d:c7:b0:a6:d9:45:0e:c9:68:95:35:46:e9:08:e9:8c:4f:53:42:9d:29:7b:30:65:f6:cd:00:ae:f6

s=054:166:020:190:252:207:029:030:042:098:156:055:041:108:058:032
  073:208:253:242:115:250:053:106:192:168:087:173:045:161:124:186
  163:049:162:067:040:096:086:039:057:023:100:216:203:123:217:175
  248:107:224:131:038:172:014:011:085:003:214:149:110:215:159:129
  046:125:144:043:077:126:150:167:200:169:097:153:188:201:071:254
  246:244:080:184:232:010:006:176:241:183:019:027:118:090:104:065
  000:033:210:220:236:234:063:205:048:155:095:133:218:050:022:158
  130:068:221:170:202:079:213:101:164:111:099:074:034:239:082:238
  031:181:092:230:088:017:007:251:083:193:051:245:237:209:064:070
  016:139:013:037:113:180:119:009:191:148:026:189:136:059:142:233
  056:160:243:135:076:165:012:035:222:212:231:084:249:061:152:093
  255:015:174:178:223:102:052:177:021:062:117:028:225:105:025:069
  121:002:227:122:143:047:134:137:146:219:194:060:005:089:044:140
  182:247:147:145:179:198:075:081:138:094:109:141:151:116:187:127
  103:128:001:132:036:154:066:112:078:196:229:004:226:211:206:199
  091:072:171:008:114:228:197:157:240:120:185:235:018:204:195:024

m=5b:c4:90
msg

Having fun with numbers & Python – Randomization & Shuffling – Stream Cipher

Basic HTTPS TLS Proxy Server In Python

#!/usr/bin/python
# Usage: ./net.py
# Description: Proof-of-concept HTTPS proxy script to hide the domain name in a TLS connection
#              so that firewalling appliances can't see who you are trying to connect to.
# Example setup: Edit ../hosts to include "127.0.0.1 imgur.com"
# Browser: http://imgur.com
#          -> TCP 127.0.0.1 80 (Python is listening & reads headers "GET / && Host imgur.com")
#          -> UDP 4.2.2.1 53 (Python performs DNS query on "imgur.com" [non-hosts file lookup])
#          -> TCP 1.2.3.4 443 (Python connects to TLS server & sends headers over encrypted channel [non-cert verify])
#          -> HTTPS response data is proxied back to browser localhost connection
# Warning: This script is very slow and insecure

import re
import socket
import ssl
import subprocess
import SocketServer

resolv = {}

class MyTCPHandler(SocketServer.BaseRequestHandler):
    def handle(self):
        global resolv
        
        heads = self.request.recv(10024).strip().split("\n")
        
        page = ""; host = ""
        for head in heads:
            match = re.match("^get ([^ ]+).*$", head.strip(), re.I)
            if (match):
                page = match.group(1)
            match = re.match("^host: ([^ ]+).*$", head.strip(), re.I)
            if (match):
                host = match.group(1)
        
        if ((not page) or (not host)):
            print("err",heads)
        else:
            addr = ""
            if (host in resolv.keys()):
                addr = resolv[host]
            else:
                looks = subprocess.check_output(["nslookup", host]).split("\n")
                for look in looks:
                    match = re.match("^address:[ ]+([^ ]+).*$", look.strip(), re.I)
                    if (match):
                        addr = match.group(1)
                resolv[host] = addr
            
            print(page,host,addr)
            
            context = ssl.SSLContext(ssl.PROTOCOL_TLSv1_2)
            context.verify_mode = ssl.CERT_NONE
            context.check_hostname = False
            conn = context.wrap_socket(socket.socket(socket.AF_INET), server_hostname=addr)
            conn.connect((addr, 443))
            conn.sendall("GET "+page+" HTTP/1.1\r\n"+"Host: "+host+"\r\n"+"Connection: close\r\n"+"\r\n")
            
            resp = "";
            while (1):
                temp = conn.recv(10024)
                if (not temp):
                    break
                resp += temp
            self.request.sendall(resp)

if (__name__ == "__main__"):
    (HOST, PORT) = ("127.0.0.1", 80)
    server = SocketServer.TCPServer((HOST, PORT), MyTCPHandler)
    server.serve_forever()

Basic HTTPS TLS Proxy Server In Python

A cool SSH auto password program – sshpass – for sys admin remote automation (probably should use keys instead tho)

#!/usr/bin/python
# Usage: ./sshpw.py <password> ssh user@host date
# Description: This is a demo SSH auto password login script via a pseudo tty device (stolen from sshpass - not recommended obviously!)
# Note: This is a rough example script which assumes you have already accepted the fingerprint & have the right password

import os, sys, time

import glob, struct, termios, fcntl, pty

from ctypes import *

try:
	libc = cdll.LoadLibrary(glob.glob("/lib/*-linux-gnu/libc-*.so")[0])
except:
	libc = cdll.LoadLibrary(glob.glob("/usr/lib/libc.dylib")[0])

(master, slave) = pty.openpty()
#fcntl.fcntl(master, fcntl.F_SETFL, os.O_NONBLOCK)

libc.ptsname.restype = c_char_p
name = libc.ptsname(c_int(master))
slavept = -10

ourtty = os.open("/dev/tty", 0)

s = struct.pack("HHHH", 0, 0, 0, 0)
t = fcntl.ioctl(ourtty, termios.TIOCGWINSZ, s)
fcntl.ioctl(master, termios.TIOCSWINSZ, t)

pidn = os.fork()

if (pidn == 0):
	os.setsid()
	slavept = os.open(name, os.O_RDWR)
	os.close(slavept)
	os.close(master)
	os.execvp(sys.argv[2], sys.argv[2:])
	os._exit(0)

else:
	slavept = os.open(name, os.O_RDWR | os.O_NOCTTY)
	print("["+os.read(master, 128)+"]")
	os.write(master, sys.argv[1] + "\r\n")
	print("["+os.read(master, 8)+"]")
	os.wait()

A cool SSH auto password program – sshpass – for sys admin remote automation (probably should use keys instead tho)

Simple LinkedIn Resume Generator (js)

LinkedIn recently disabled it’s third party APIs which took out an auto-resume builder service based on my public profile. I wrote some JS to try and at least generate a basic resume from my LinkedIn profile now:

From LinkedIn Profile -to- a simple clean resume! with just a little bit of effort! (done in Safari with print-to-PDF graphics enabled & headers disabled):

var s = 0, q = 0;
function y() {
  if (s < document.body.scrollHeight) {
    // scroll
    window.scrollBy(0, 125); s += 125;
    setTimeout(y, 0.125 * 1000);
  } else {
    if (q == 0) { q = 1; z(); }
    else { window.scrollTo(0, 0); }
  }
}

var mail = ["[email protected]", "[email protected]"];
var webs = ["fossjon.com", "github.com/fossjon", "github.com/stoops"];

function z() {
  // hide
  var l = [
    "resume-builder-top-nav", "scaffold-layout__header", "scaffold-layout__aside",
    "resume-builder__section-edit-button", "resume-builder__subsection-edit-button",
    "global-nav__a11y-menu", "global-nav", "msg-overlay-container"];
  for (var i in l) {
    var a = document.getElementById(l[i]);
    var b = document.getElementsByClassName(l[i]);
    var c = 1;
    try { a.setAttribute("style", "display: none !important;"); c = 0; } catch(e) { /* no-op */ }
    for (var j in b) { try { b[j].setAttribute("style", "display: none !important;"); c = 0; } catch(e) { /* no-op */ } }
    if (c == 1) { console.log("hide:"+l[i]); }
  }
  var p = document.getElementsByClassName("resume-builder__job-apply-educational-card-illustration");
  if (p) { p[0].parentNode.setAttribute("style", "display: none !important;"); }

  document.title = "resume";
  document.body.setAttribute("style", "background-color: white !important;");

  // high
  try {
    document.getElementsByClassName("authentication-outlet")[0].style.background = "white";
    document.getElementsByClassName("authentication-outlet")[0].style.paddingTop = "1px";
    document.getElementsByClassName("authentication-outlet")[0].style.paddingBottom = "256px";
    var p = document.getElementsByClassName("resume-builder-contact-info__name")[0].parentNode.parentNode;
    p.setAttribute("style", "padding-top: 1px !important; padding-bottom: 0px !important; box-shadow: none !important;");
  } catch(e) { /* no-op */ }

  // wide
  try {
    document.getElementsByClassName("scaffold-layout__inner")[0].style.marginLeft = "10px";
    document.getElementsByClassName("scaffold-layout__inner")[0].style.marginRight = "10px";
    document.getElementById("main").style.width = (document.getElementById("main").parentNode.offsetWidth+"px");
  } catch(e) { /* no-op */ }

  // dots
  while (document.getElementsByClassName("white-space-pre-wrap").length > 0) {
    var li = document.getElementsByClassName("white-space-pre-wrap")[0];
    var h = li.innerHTML; if (!h) { h = ""; }
    h = h.replace(/\*/mig, "•");
    while (h.match(/^.*••.*$/mig)) {
      h = h.replace(/••([^\r\n]+)/mig, "<table style='display:inline;'><tr><td style='padding-left:25px;'>•$1</td></tr></table>");
    }
    console.log("dots:"+i);
    h = h.replace(/•[ ]*([^\r\n]+)/mig, "<table style='display:inline;'><tr><td style='padding-left:25px;white-space:nowrap;'><b style='font-size:16px;'>•&nbsp;</b></td><td>$1</td></tr></table>");
    for (var k in imgs) {
      h = h.replace("["+k+"]", "\n<span><br><img style='width: 65%; margin-left: 25px;' src='data:image/png;base64,"+imgs[k]+"' /></span>");
    }
    h = h.replace(/[\r\n]/mig, "<span><br/></span>") + "<div>&nbsp;<br/></div>";
    li.outerHTML = ('<span class="t-16 t-black main-text">' + h + '</span>');
  }

  // imgs && path && flat
  var info = "";
  var d = {};
  var l = document.getElementsByClassName("lazy-image");
  for (var i = 0; i < l.length; ++i) {
    var f = 1;
    var o = "", v = " opacity: 0%; ";
    if (l[i].src in d) { f = 0; }
    /* imgs */
    if (f == 0) { o = " opacity: 0%; "; }
    l[i].setAttribute("style", "width: 42px; height: 42px; margin-top: 6px !important; margin-right: 4px !important;"+o);
    d[l[i].src] = "*";
    /* dots */
    if (f == 0) { v = ""; }
    if (!document.getElementById("dot"+i)) {
      var x = document.createElement("SPAN");
      x.setAttribute("id", "dot"+i);
      x.setAttribute("class", "pvs-entity__path-node");
      x.setAttribute("style", "left: -28px;" + v);
      l[i].parentNode.insertBefore(x, l[i].nextSibling);
    }
    /* less */
    try {
      var p = l[i].parentNode.getElementsByTagName("div")[0];
      var a = p.getElementsByTagName("*");
      if (i == 0) { info = (" # " + a[0].innerHTML + " @ " + a[1].innerHTML); }
      var e = 0;
      try {
        var t = p.parentNode.parentNode.parentNode.getElementsByTagName("h3")[0];
        if (t.innerHTML.match(/^.*education.*$/mig)) { e = 1; }
      } catch(e) { /* no-op */ }
      a[1].setAttribute("class", "t-14 t-black");
      if (e == 0) {
        a[0].innerHTML = (a[0].innerHTML + " at " + a[1].innerHTML);
        a[1].innerHTML = a[2].innerHTML;
        a[2].innerHTML = " &nbsp; ";
      } else {
          a[0].innerHTML = (a[1].innerHTML + " at " + a[0].innerHTML);
          a[1].innerHTML = a[2].innerHTML;
          a[2].innerHTML = " &nbsp; ";
      }
      if (f == 0) {
        p.classList.add("full-width");
        p.classList.add("pvs-entity--with-path");
      } else {
        var h = p.innerHTML;
        if (h.match(/^.*<.h[4]>.*$/mig)) {
          h = (h.replace(/(<.h[4]>)/mig, '$1<div class="pvs-entity--with-path">') + "</div>");
        }
        p.innerHTML = h;
      }
    } catch(e) { /* no-op */ }
  }

  // find
  var l = document.getElementsByClassName("resume-builder__section-container");
  for (var i = 0; i < l.length; ++i) {
    if (l[i].innerHTML && l[i].innerHTML.match(/^.*this section is empty.*$/mig)) {
      l[i].style.display = "none";
    }
  }

  // info
  try {
    var p = document.getElementsByClassName("resume-builder-contact-info__field-container")[0].parentNode;
    var h = "";
    for (var i = 0; i < Math.max(mail.length,webs.length); ++i) {
      var a = ""; if (i < mail.length) { a = mail[i]; }
      var b = ""; if (i < webs.length) { b = webs[i]; }
      if (a != "") {
        var path = '<path d="M8 1L1 4.47V11a3 3 0 003 3h8a3 3 0 003-3V4.47zm5 10a1 1 0 01-1 1H4a1 1 0 01-1-1V6.51L8 9l5-2.49z"></path>';
        a = ('<a href="mailto:'+a+'"><li-icon type="envelope-open" class="resume-builder-contact-info__email-icon" size="small" role="img" aria-label="Email"><svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 16 16" data-supported-dps="16x16" fill="currentColor" class="mercado-match" width="16" height="16" focusable="false">'+path+'</svg></li-icon>'+a+'</a>');
      }
      h += ('<div class="resume-builder-contact-info__field-container">'+a+'</div>');
      if (b != "") {
        var path = '<path d="M11 2a3 3 0 00-2.1.87L6.87 4.94a2.93 2.93 0 00-.72 1.21 2.93 2.93 0 00-1.21.72L2.87 8.94a3 3 0 104.19 4.19l2.07-2.07a2.93 2.93 0 00.72-1.21 2.93 2.93 0 001.21-.72l2.07-2.07A3 3 0 0011 2zm-5.17 9.89a1.22 1.22 0 01-1.72-1.72l2.06-2.06A3 3 0 007.91 9.8zm6.07-6.07L9.83 7.89A3 3 0 008.09 6.2l2.07-2.07a1.22 1.22 0 011.73 1.7z"></path>';
        b = ('<a href="https://'+b+'"><li-icon type="link" class="resume-builder-contact-info__website-icon" size="small" color="true" role="img" aria-label="Website link"><svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 16 16" data-supported-dps="16x16" fill="currentColor" width="16" height="16" focusable="false">'+path+'</svg></li-icon>'+b+'</a>');
      }
      h += ('<div class="resume-builder-contact-info__field-container">'+b+'</div>');
    }
    p.innerHTML = h;
    var q = document.getElementsByClassName("resume-builder-contact-info__name")[0].parentNode;
    q.getElementsByTagName("p")[0].style.fontFamily = "monospace";
    q.getElementsByTagName("p")[0].style.fontSize = "14px";
    q.getElementsByTagName("p")[0].style.paddingLeft = "3px";
    q.getElementsByTagName("p")[0].style.paddingTop = "6px";
    q.getElementsByTagName("p")[0].innerHTML = info;
  } catch(e) { /* no-op */ }

  // clik
  var l = document.getElementsByClassName("main-text");
  for (var i = 0; i < l.length; ++i) {
    l[i].onclick = function() {
      var pb = parseInt(this.parentNode.parentNode.style.paddingBottom);
      if (!pb) { pb = 0; } this.parentNode.parentNode.style.paddingBottom = ((pb+50)+"px");
    };
  }

  // end!
  window.scrollTo(0, 0);

  return 0;

  // wide
  try {
    document.getElementsByClassName("scaffold-layout__main")[0].style.width = "125%";
    document.getElementsByClassName("scaffold-layout__main")[0].style.background = "white";
    document.getElementsByClassName("scaffold-layout")[0].style.setProperty("--scaffold-layout-gutter", "0px");
    document.getElementsByClassName("scaffold-layout")[0].style.background = "white";
    document.getElementsByClassName("scaffold-layout-container")[0].style.margin = "0px";
    document.getElementsByClassName("scaffold-layout-container")[0].style.paddingLeft = "5px";
    document.getElementsByClassName("scaffold-layout-container")[0].style.background = "white";
  } catch(e) { /* no-op */ }
}

s = 0; y();

var imgs = {};

imgs["img0"] = ""+
"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"+
"u+x/+cSVoCunr3KvXrgWda3jeuL1mzfSbnTeFNx8divv1qvbRbc/35l1l3C37J7mvYr7xver/7D/Y3enR+fRB0EP2h7GP7zziP/oxeOCx1+65j6hPal4ava05pnrsyPdId2Xno953vVC8uJzT+mfWn9WvbR7eeCvgL/aekf3dr2Svup/vfCN4Zttb93etvTF9N1/l//u8/uyD4Yftn9kfTzzKfnT08+TvpC+rP5q/7XpW8S3u/35/f0SnpSn+BXA"+
"YEUzMwF4vQ0AWgoADHg+o4xRnv8UBVGeWRUI/CesPCMqigcAdfD/PbYH/t3cAGDPFnj8gvoaaQDE0ABI8ALoiBGDdeCspjhXygsRngM2Rn3NyM8A/6Yoz5w/xP1zC+SqbuDn9l8D6nxC3rNDpgAAAIplWElmTU0AKgAAAAgABAEaAAUAAAABAAAAPgEbAAUAAAABAAAARgEoAAMAAAABAAIAAIdpAAQAAAABAAAATgAAAAAAAACQAAAAAQAAAJAA"+
"AAABAAOShgAHAAAAEgAAAHigAgAEAAAAAQAABVqgAwAEAAAAAQAAAQQAAAAAQVNDSUkAAABTY3JlZW5zaG901F1L9gAAAAlwSFlzAAAWJQAAFiUBSVIk8AAAAddpVFh0WE1MOmNvbS5hZG9iZS54bXAAAAAAADx4OnhtcG1ldGEgeG1sbnM6eD0iYWRvYmU6bnM6bWV0YS8iIHg6eG1wdGs9IlhNUCBDb3JlIDYuMC4wIj4KICAgPHJkZjpSREYg"+
"eG1sbnM6cmRmPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5LzAyLzIyLXJkZi1zeW50YXgtbnMjIj4KICAgICAgPHJkZjpEZXNjcmlwdGlvbiByZGY6YWJvdXQ9IiIKICAgICAgICAgICAgeG1sbnM6ZXhpZj0iaHR0cDovL25zLmFkb2JlLmNvbS9leGlmLzEuMC8iPgogICAgICAgICA8ZXhpZjpQaXhlbFlEaW1lbnNpb24+MjYwPC9leGlmOlBp"+
"eGVsWURpbWVuc2lvbj4KICAgICAgICAgPGV4aWY6UGl4ZWxYRGltZW5zaW9uPjEzNzA8L2V4aWY6UGl4ZWxYRGltZW5zaW9uPgogICAgICAgICA8ZXhpZjpVc2VyQ29tbWVudD5TY3JlZW5zaG90PC9leGlmOlVzZXJDb21tZW50PgogICAgICA8L3JkZjpEZXNjcmlwdGlvbj4KICAgPC9yZGY6UkRGPgo8L3g6eG1wbWV0YT4KxSxVFQAAABxp"+
"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"+
"pkmTBuaaa7ZIl4jGKmsE0Oh84oknbBl/+9vfmh//+MdlXd76XrjRo0ebESNG2GpcdtllZv/996/vVdLylxECz7/4pvnokyWmAf27uP3PzHcabVlGpSu+KPPmzTN//etfbYQTTzzRnHbaacVHroWQ99xzD70Tr7E5vfbaa+a4446rhVzrRxYgIFasWGGaNm1qunbtWj8KTaWMosh88cUXZttttzWNGjWqN+XWgioCmyoCafzwt99+a77//e+badOm"+
"mebNm5sPP/zQfOc730kE4aJFi0yzZs1snPbt25uHH344UXwNrAgoAoqAIqAIlDMCiYhWnaM13aXcZZc1ZunSyDRubKjjtHW6RDRWWSMwaNAg84c//MGW8aGHHjIXXXRR2ZT3zTffNAMGDHDl2W233cxtt93mfvs7gwcPNv/+97/t4bZt2xo0gMvNbr31Vkc+jBw50px66qnlVsRNpjzT3p9nXnjpLVfffVs1N+eccaz7LXceeXK0+WjBEnfozNN+"+
"ag7Yr6X7XS47nboNMP955wNbnOeG9jDbb7dtuRQtUTlef/1106ZNGxvn+uuvz/vcJ0o4g8Cff/652WuvvczKlSttGceMGZNBqhtPEk2aNLHYYPHRJUuqnplyrOHy5cvNXXfdZV566SXzn//8xxWxMTV68NHx9NNPNyeffLI54IAD3DndUQTqCwJoz8FfFWO43/GRpL5YKX74hRdesCMRUNc+ffqYjh07Jq72ddddZ+68804b7+2337YjHBInohEU"+
"AUVAEVAEFIFyRIDUB0UbNfYj/KklQ+C7310dGbMqatx4VbKIGYRu23atzRv5r6r97DOoQf1I4oEHHiCcjf0jorWsCk3DulzZuIxvvPFGbBkvvvhiF/6KK66IDVeXJ2655RZXRiJa67Iom3zeI16eEB17+tU5f2vXfVMNl5Vfr84JgzijX59cLVyWB6ZOn+vyfOjRUUUn/X9d73fxvvxqZdHxyi0gfTBxzwkRrWVVvC5duriykZq1rMpWDoUhktLi"+
"Q0RrORQntgxEtlDbprKs/H6J28YmoicUgVpAoGfPns7n0KiYonPEMxh3T/vH6aNv0emmDUhD/V15jj766LTJ2Hil+GFStUaHHHKILQt8AH00S1yWTz/91NWFPuwnjq8RFAFFQBFQBBSBckUgkaKVGhRqKRBo1WqNmTcvIvVOAzN37lYpUkgf5Zhj1ppx4761CaxcuTUN50uflsaMR6CcFa0YjnXhhRfmFB7zIQ4fPjznGP+45JJLzN///nf7k4hW"+
"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"+
"QAIkEBKg0MoTgQRIgARIgARIgARIgARIgARIgARIgARIgARIgARyEqDQmhMgDycBEiABEiABEiABEiABEiABEiABEiABEiABEiABCq08B0iABEiABEiABEiABEiABEiABEiABEiABEiABEggJ4FMQuuSJUvC7Hr06JEzWx5OAiRAAiRAAiRAAiRAAiRAAiRAAiRAAiRAAiRAAq1DIJPQOnv27LDme+65Z+sQYE1IgARIgARIgARIgARIgARIgARI"+
"gARIgARIgARIICeBTEIrLVpz0ubhJEACJEACJEACJEACJEACJEACJEACJEACJEACLUkgk9DakgRYKRIgARIggVgCp5xyihk/frzZZpttzMKFC82mm24aGzduRxFpxKXN7SRAAiRAAiSQROCqq64yQ4cONVtssYWZMWOG2XnnnZOic18ZAtOmTTMHH3xwGGv06NHm8MMPL3MEd5MACZAACZBA1yKQSWilRWtlJ8fVV7eZFSsCs/XW3cwZZ2QXKSrL"+
"tfmPeu+99wxejhF69+5tDjvssOavVEINxo4da2bOnBnGGDJkiPna176WELt5d7399tvm2muvDSvwb//2b6Zv377NW5kWLznOx3333Tes5YUXXmhwXmYNRaSRNc9miY+O/4oVK8JrvRK2zVLPRinnDTfcYN58803TrVs3M2LECLPZZps1StFYjhYlsHr1arNmzRqz7bbbhuddUjW72jsPxLq77747RHLMMceY/fbbLwlPrn0ffvih2WmnncI0jjvu"+
"OHPnnXfmSq+rH7xx40azzz77mFmzZpmePXuG99XNN9+8q2Nh/UmABEiABEggIpBJaKWP1ohbppVvfGO1WbIkMN27G9up3jLTsV05Ml7C//mf/zlEMGDAAHPllVe2NI5f/epXZty4cWEdIQZ897vfNc8//7y56aabonrvuOOOZuTIkdFvd+X22283zzzzTLi5T58+Bh2KRgvPPvtsKJyjXOecc05ifRqt7F2pPEEQmJ/97Gdm8uTJ9t7V3bz77ruZ"+
"xf8i0mhl5ltvvbX54osvDCaY/PjjjxuqqrfddpvBtSoBH0WOP/54+dlp+fvf/94+59onzOzfv39VRZNOmafc8POf/zy6P37++eehlXbKQxmNBFITwDMY7ysvv/yyef/996PjdtttN/Ov//qv5t///d/DZ+BWW20V7cNKV3vnGTVqlOnXr1/I4I477jAnnnhiuF6tf2effba57LLLwuRfeOEF8+Mf/7haWTVFukuXttn3y8XmjTdWh+XdYYevmEsv"+
"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"+
"N6uxoxbUXq5mJQBh9Xvf+154mB1VZKxFedYkwg/r+GAowbrJMdbVivzkkgRIgARIgASamkAmoZUWrU3d1iw8CZAACWQmgA4VrJEQ7CRGmYVWHFdEGkiHgQRIgARIgASyEsCIGVj4wor14IMPzno44zsEMELNTsoYbrXucczWW2/txCj/86abbjLWnVYU0bqKMD/5yU+i31whARIgARIggWYmkEloxXA/BAzrZSABEiABEiABEiABEiABEiABEiCB"+
"LATspGzGzkMQHgJr1rvvvjvL4YxLAiRAAiRAAg1NIJPQSovWhm5LFo4ESIAESIAESIAESIAESIAESIAESIAESIAESKBOBDIJrXUqI7MlARIgARIgARIgARIgARIgARIgARIgARIgARIggYYmkElopUVrQ7clC0cCJEACJEACJEACJEACJEACJEACJEACJEACJFAnApmE1jqVkdmSAAmQAAmQAAmQAAmQAAmQAAmQAAmQAAmQAAmQQEMToNDa0M3D"+
"wpEACZAACZAACZAACZAACZAACZAACZAACZAACTQDAQqtzdBKLCMJkAAJkAAJkAAJkAAJkAAJkAAJkAAJkAAJkEBDE6DQ2tDNw8KRAAmQAAmQAAmQAAmQAAmQAAmQAAmQAAmQAAk0AwEKrc3QSiwjCZAACZAACZAACZAACZAACZAACZAACZAACZBAQxOg0NrQzcPCkQAJkAAJkAAJkAAJkAAJkAAJkAAJkAAJkAAJNAMBCq3N0EosIwmQAAmQAAmQ"+
"AAmQAAmQAAmQAAmQAAmQAAmQQEMToNDa0M3DwpEACZAACZAACZAACZAACZAACZAACZAACZAACTQDAQqtzdBKLCMJkAAJkAAJkAAJkAAJkAAJkAAJkAAJkAAJkEBDE8gktC5ZsiSsTI8ePRq6UiwcCZAACZAACZAACZAACZAACZAACZAACZAACZAACdSSQCahdfbs2WHZ9txzz1qWkXmRAAmQAAmQAAmQAAmQAAmQAAmQAAmQAAmQAAmQQEMTyCS0"+
"0qK1oduShSMBEiABEiABEiABEiABEiABEiABEiABEiABEqgTgUxCa53KyGxJgARIgAS6MIG1a9eaH//4x2bhwoXml7/8pfnf//3fLkyDVScBEiCB6hOYNm2aOfjgg8OMRo8ebQ4//PDqZ8ocSIAESIAESIAESKAFCGQSWmnR2gItzioUQiAIAvPZZ5+Zrbbaymy22WZl07zlllvM3LlzTbdu3czFF19sttxyy7LHNGuETz75xAwfPjws/v7772+O"+
"PvroulQFncS77747zPuYY44x++23X13KwUyNef75582sWbPMO++8YyCaIuDaueiii1Lh+dOf/mTOOOOMMO7TTz9tfv7znyceN2TIEPPFF1+Yr3zlK+bSSy9NjMudJFBrAr///e/Nhg0bzE477WSw3sqhq9yHN27caM466yyD5S677BLdr5q5bVGXffbZJ7x39+zZ07z55ptm8803b+YqsewkQAIkQAIkQAIkUBMCmYRW+mitSZswkwYlsHz5cnP5"+
"5Zebxx9/3Lz44otRKbt37x6KeP/xH/9hDjnkELP77rtH+2TlF7/4RXgcfuODxfbbby+7Wm4JQVkYnHjiieaOO+6oSx1HjRpl+vXrF+aNMqAsEiD6DR48OPz5gx/8IGxX2ecuUZ9zzjkn7EBjH4TjY4891o3G3x4Cq1atClndf//9nfbiulmxYkWn7e6GTz/91PTq1SsUTnv37m0mTZrkRun0e+uttw7jYwc+ijRTgCh90003RUXecccdzciRI6Pf"+
"7srtt99unnnmmXBznz59zHHHHedG4e8GI4APbgi4T77++usNVrpiixN3Hx44cKDBtS3ht7/9rcGHOV/AR0350IL91157rdlmm218Ueu2bf369eGHHRTgRz/6kZk5c2bdylJkxo888kg4igBpXnHFFQbtxkACJEACJEACJEACJFCGgO2Epg4ff/xxgD+G5iHQp88aqzKsDP9WrmyecjdaSW1nI7DCEBSbsn++slsBNjrOCq2+KC2zbc6cOVFdrbhZ"+
"t3pZK+KoHFZoLSnHk08+Ge2zlq4l+/SPBQsWBD169IjiHnTQQYEVD3UUricQsBarETtcO9YqKrAiRPhnRcGEIzt2WUE8SsNas3bsSFjT12pCtIbcZYfoRvWV+83f/va32LKedNJJUfzf/OY3sfG4o3EISLtaobVxClWlksTdh/V9FTzwjIwLb7/9dnSOI+4HH3wQF7Vu29etWxeVEfe4VgnWqjXYa6+9wrrhvmpHCrRK1VgPEiABEiABEiABEqga"+
"AVj7MLQwgQMPXG1fkNuFVr4fV9bQWjhEJw+djV//+tfBhRdeGPTv3z+A+CYdZyx9gUKrj0p1t8V18JFrGqF10aJFoTAobXvAAQewk5mxybSYYocQZzw6CFavXh194IBIa4dbp0qj1YRW65c2tt4UWmPRNOwOuadQaC39cGlHinjbjEKrF0vNNl533XXRO461oK9ZvsyIBEiABEiABEiABJqVgF8ViqkNLVpjwDTwZgqt+RsHlnfSMe7bt29ghzF2"+
"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"+
"Ly7oSbeEmzvkHscuW7as0/WA+Hg2w0I96fkqzyBMLCdB+/mW6wT7tJXt7bffLtFDn9VSPjxT8L6srbhlH+7py5cvj47zrRTxbES6edsVaegPZnhvqCSAk9RflrW6XispL48hARIgARIgARIggbwEuiEB++KTKtjhlWE8+1KaKj4j5SfQ1mbMW29tNHbkmVm3zpiddupmevZs/8ufevkUkL91WWBsP8V84xvdzL77bmI237z8ca0Yw/rZNHZou7Gd"+
"vPDv7/7u78wuu+xidt55Z7PddtuZbt261aTayN92fsIy/OM//qOxYozZdNNNa5K3m4kVIc3LL79sttpqK7P//vubr371q26UVL+t5ZexQk7I9+tf/7o9z3cy3/72t82WW25Z9njrF9W88cYbxg5tNrZja/bee++68cA5Yi1e7fU6316v68J6WEHBXrM9y9ZDIhx88MHmiSeeCH9akd9YkV521WxpZzYP22PBggUG9/s99tgjPMdrVgAno//+7/82"+
"1jdxuNVas5kdd9zRiVHdn83erla4MdbCPTwvrb9F88Mf/jC8vqpLLT51vHagHXHNW0HS7LDDDuG1suuuu6a6du0HJ2OF8SgDK4SZoUOHRr9rsYJzAte5tTg3eDeyopb51re+Fd6DKr0PZi13I7VrI9yHcV7hmYRnAdj85Cc/MV/72teyYi00PspjJzM022+/vdlnn33CZ2WWDPI8G7PkExfXfiw1VigNd+N58J3vfCcuaux2+6HN2A9I0f56XK9R"+
"5lwhARIgARIgARIggRoQyCS01qA8zIIESIAEuiwBa3kVipoAAIETYlS9RPRGagSIhBDREazPRXPVVVc1UvHKloXtWhZR6ggQ0775zW+G4iYOgsBph9LXXVBLXQFGJIEmIQBh9Xvf+15YWmuJbqzbjMwlx/W6zTbbGDviJjyW12tmhDyABEiABEiABEigCQlkElpp0dqELcwikwAJNAUBO1TV2GGlxvoPDMt70UUXmfPOO68pyl6LQk6bNs1Y1wbm"+
"H/7hH4wdmluLLAvJg+1aCMYoEViv/+AHP4h+28mCjJ10KvrNFRIggWIIWHdFZsaMGWFi1gWN2XrrrTMnbF20mH/6p3+KjuP1GqHgCgmQAAmQAAmQQAsTyCS04oUJYc8992xhJKwaCZAACdSGgPUrGA55tv7qoqHxyBlWP9bHaV2H69eGQGvmwnatXrvaCbrMySefHGaA6wRW31gykAAJNB6BiRMnmt/+9rdhwbbddttQuOX12njtxBKRAAmQAAmQ"+
"AAkUSyCT0EqL1mLhMzUSIIGuTUAPiRcS6ITCqnXfffeVTVw2GQG2a/Ua7K9//av5y1/+YjbZZBMDKzs7IVj1MmPKJEACJEACJEACJEACJEACJJCRQCahNWPajE4CJEACJJBAABPpyGRXmCzlZz/7Weg+QA+NTjicuxqUANu1QRuGxSIBEiABEiABEiABEiABEiCBKhPIJLTSorXKrcHkSYAESIAESIAESIAESIAESIAESIAESIAESIAEmpJAJqG1"+
"KWvIQpMACZAACZAACZAACZAACZAACZAACZAACZAACZBAlQlQaK0yYCZPAiRAAiRAAiRAAiRAAiRAAiRAAiRAAiRAAiTQ+gQotLZ+G7OGJEACJEACJEACJEACJEACJEACJEACJEACJEACVSZAobXKgJk8CZAACZAACZAACZAACZAACZAACZAACZAACZBA6xOg0Nr6bcwakgAJkAAJkAAJkAAJkAAJkAAJkAAJkAAJkAAJVJkAhdYqA2byJEACJEAC"+
"JEACJEACJEACJEACJEACJEACJEACrU+AQmvrtzFrSAIkQAIkQAIkQAIkQAIkQAIkQAIkQAIkQAIkUGUCFFqrDJjJkwAJkAAJkAAJkAAJkAAJkAAJkAAJkAAJkAAJtD4BCq2t38asIQmQAAmQAAmQAAmQAAmQAAmQAAmQAAmQAAmQQJUJUGitMmAmTwIkQAIkQAIkQAIkQAIkQAIkQAIkQAIkQAIk0PoEKLS2fhuzhiRAAiRAAiRAAiRAAiRAAiRA"+
"AiRAAiRAAiRAAlUmkFtoXbhwoVm6dKnZbrvtTI8ePcyWW25Z5SIzeRIgARIgARIgARIgARIgARIgARIgARIgARIgARJoLAK5hdbjjz/ejBkzJqoVxNb/+Z//MQMGDDBbbLFFtJ0rJEACJEACJEACJEACJEACJEACJEACJEACJEACJNCqBHILrSeeeKIZPXp0Jz6XXHKJGTx4cKft3EACJEACJEACJEACJEACJEACJEACJEACJEACJEACrUYgt9Da"+
"1tZmVq1aZZYsWWLGjRtnhg4dGjHauHGj6datW/SbKyRAAiRAAiRAAiRAAiRAAiRAAiRAAiRAAiRAAiTQigRyC60ulD322MPMmTMn3Pzxxx+HflvdOPxNAiRAAiRAAiRAAiRAAiRAAiRAAiRAAiRAAiRAAq1EoHCh9aijjjL33HNPyOiVV14xe++9dyvxYl1IgARIgARIgARIgARIgARIgARIgARIgARIgARIoBOBwoXWfv36mVGjRoUZTZ061Rxw"+
"wAGdMuUGEiABEiABEiABEiABEiABEiABEiABEiABEiABEmglAoULraeccoq55ZZbQkYUWlvpVGFdSIAESIAESIAESIAESIAESIAESIAESIAESIAE4ghQaI0jw+0kQAIkQAIkQAIkQAIkQAIkQAIkQAIkQAIkQAIkkJJAVYXWZ5991vzLv/xLyqIwGgmQAAmQAAmQAAmQAAmQAAmQAAmQAAmQAAmQAAk0J4HChdY//OEPZvjw4SGNsWPHml/96lfN"+
"SYalJgESIAESIAESIAESIAESIAESIAESIAESIAESIIGUBAoXWuGfFX5aEfr27WseeeSRlEVhNBIgARIgARIgARIgARIgARIgARIgARIgARIgARJoTgKFC62fffaZ2XXXXc0XX3wREunXr5859dRTw22bbbaZ2Xzzzc0mm2zSnLRYahIgARIgARIgARIgARIgARIgARIgARIgARIgARLwEChcaEUe8+bNM5dccol58MEHI8FV8r733nvNf/7nf8pP"+
"LkmABEiABEiABEiABEiABEiABEiABEiABEiABEig6QlURWhdtWqVgQuB++67z0yePLkE0j333GP+67/+q2Qbf5AACZAACZAACZAACZAACZAACZAACZAACZAACZBAMxMoXGhdv3692Xfffc2sWbNCLj169DBDhgwxe+yxh9lyyy3NbrvtZrbddttmZsaykwAJkAAJkAAJkAAJkAAJkAAJkAAJkAAJkAAJkEAJgcKFVlisHnXUUWEm3bt3NwsWLDAQ"+
"WxlIgARIgARIgARIgARIgARIgARIgARIgARIgARIoFUJFC60wnr1oosuCnmNGDHCDBo0qFXZsV4kQAIkQAIkQAIkQAIkQAIkQAIkQAIkQAIkQAIkEBIoXGg95ZRTQv+sSP3xxx83Bx98MFGTAAmQAAmQAAmQAAmQAAmQAAmQAAmQAAmQAAmQQEsTqKrQOnXqVHPAAQe0NEBWjgRIgARIgARIgARIgARIgARIgARIgARIgARIgAQotPIcIAESIAES"+
"IAESIAESIAESIAESIAESIAESIAESIIGcBAoXWk888UQzevTosFi0aM3ZOjycBEiABEiABEiABEiABEiABEiABEiABEiABEigKQgULrT+4he/CH2zovavvfaa2XPPPZsCBAtJAiRAAiRAAiRAAiRAAiRAAiRAAiRAAiRAAiRAApUSKFRoXbhwoenVq1dUllWrVpktttgi+s0VEiABEiABEiABEiABEiABEiABEiABEiABEiABEmhFArmF1j//+c9m"+
"8uTJ5qOPPjKPPfZYxKh3795m0qRJ0W+ukAAJkAAJkAAJkAAJkAAJkAAJkAAJkAAJkAAJkECrEsgttB5//PFmzJgxJXx69uwZiq50G1CChT9IgARIgARIgARIgARIgARIgARIgARIgARIgARalEBuoXXUqFHm+eefN9tvv73p0aOH+f73v28OPfRQs+mmm7YoMlaLBEiABEiABEiABEiABEiABEiABEiABEiABEiABEoJ5BZaS5PjLxIgARIgARIg"+
"ARIgARIgARIgARIgARIgARIgARLoegQotHa9NmeNSYAESIAESIAESIAESIAESIAESIAESIAESIAECiZAobVgoEyOBEiABEiABEiABEiABEiABEiABEiABEiABEig6xGg0Nr12pw1JgESIAESIAESIAESIAESIAESIAESIAESIAESKJgAhdaCgTI5EiABEiABEiABEiABEiABEiABEiABEiABEiCBrkeAQmvXa3PWmARIgARIgARIgARIgARIgARI"+
"gARIgARIgARIoGACFFoLBsrkSIAESIAESIAESIAESIAESIAESIAESIAESIAEuh4BCq1dr81ZYxIgARIgARIgARIgARIgARIgARIgARIgARIggYIJUGgtGCiTIwESIAESIAESIAESIAESIAESIAESIAESIAES6HoEKLR2vTZnjUmABEiABEiABEiABEiABEiABEiABEiABEiABAomQKG1YKBMjgRIgARIgARIgARIgARIgARIgARIgARIgARIoOsR"+
"oNDa9dqcNSYBEiABEiABEiABEiABEiABEiABEiABEiABEiiYwP8HK2PMuJzZbBEAAAAASUVORK5CYII="+
"";

Simple LinkedIn Resume Generator (js)

Using a good Curve (25519) to implement a Dual_EC_DRBG based PRNG (bad) in Py

('(secret)', 'e=17211717500188099600568359980754843411619158773615107210604175251693280840607')

('(pub)', 'P', [15395204427582176828288140787842485523287609441875116301821962120815246523165L, 50972925492742860438904710940702337165443708937045978727200475339385656596802L])
('(pub)', 'Q', [54379753906375494870435841730857804485220282788952166778590221998932647140003L, 10542862410506568609831388869015874299228416047841839543681429954753256816461L])

Running first 3 prng outputs:
(1, '(pub)', 'rQ', [35085355371653225423586630859880842591953206407407058841980055259804158729190L, 17642611272178418467727837731595189739886826601909812633308152323681611088547L])
(2, '(pub)', 'rQ', [49239914602839976828302644790025511534554523065665058491590572885136905915179L, 8379389248907743775496938151971165397933498701999710225313910125914506554304L])
(3, '(pub)', 'rQ', [46183005535555809253746127552459776700939930656325949263490016267446108722393L, 39473869171813125431282259087083131250343325900631309529780555199432408899154L])

Predicting next prng output:
(4, '(pub)', 'sQ', [41709487842035263418257031106229715942424730101066821754384094668791902320545L, 47532264341329149594994883777108416347984877171111029279692175022666589952933L])
Running next prng output:
(4, '(pub)', 'rQ', [41709487842035263418257031106229715942424730101066821754384094668791902320545L, 47532264341329149594994883777108416347984877171111029279692175022666589952933L])
import sys
import random

def egcd(a, b):
	s = 0; news = 1
	r = b; newr = a
	while r != 0:
		quot = (newr / r)
		prev = s
		s = (news - (quot * prev))
		news = prev
		prev = r
		r = (newr - (quot * prev))
		newr = prev
	if (news < 0):
		news += b
	return news

def dub(p, a, b, n):
	# l = 3*x^2 + 2*a*x + 1 / 2*b*y
	xx = pow(p[0], 2, n)
	ya = (((3 * xx) + (2 * a * p[0]) + 1) % n)
	yd = ((2 * b * p[1]) % n)
	l = ((ya * egcd(yd, n)) % n)
	# xr = b*l^2 - a - 2*x
	ll = pow(l, 2, n)
	newx = (((b * ll) - a - (2 * p[0])) % n)
	# yr = ((3*x + a) * l) - b*l^3 - y
	yb = (((3 * p[0]) + a) % n)
	newy = (((yb * l) - (b * ll * l) - p[1]) % n)
	return [newx, newy]

def add(p, q, a, b, n):
	# l = (Qy - Py) / (Qx - Px)
	ya = ((q[1] - p[1]) % n)
	yd = ((q[0] - p[0]) % n)
	l = ((ya * egcd(yd, n)) % n)
	# xr = b*l^2 - a - Px - Qx
	ll = pow(l, 2, n)
	newx = (((b * ll) - a - p[0] - q[0]) % n)
	# yr = ((2*Px + Qx + a) * l) - b*l^3 - Py
	yb = (((2 * p[0]) + q[0] + a) % n)
	yc = ((b * ll * l) % n)
	newy = ((((yb * l) % n) - yc - p[1]) % n)
	return [newx, newy]

def mul(m, p, a, b, n):
	r = None
	while (m > 0):
		if ((m % 2) == 1):
			if (r == None):
				r = p
			else:
				r = add(r, p, a, b, n)
		p = dub(p, a, b, n)
		m = (m >> 1)
	return r

a = 486662
b = 1
n = 57896044618658097711785492504343953926634992332820282019728792003956564819949
try:
	p = [int(sys.argv[2]), int(sys.argv[3])]
except:
	p = [9, 43114425171068552920764898935933967039370386198203806730763910166200978582548]

# e is our secret key here
d = random.randint(3, n - 3)
e = random.randint(3, n - 3)
print("(secret)","e=%d"%e)
print("")

# let G = any base point
# calculate public point constants: P = edG & Q = dG
g = mul(d, p, a, b, n)
g = mul(e, g, a, b, n)
print("(pub)","P",g)
h = mul(d, p, a, b, n)
print("(pub)","Q",h)
print("")

# multiply random seed with the points: P' = rP & Q' = rQ
# these then equate to: P' = redG & Q' = rdG
# the 'key' to this is basing the next r' off of the output of P' and publishing the point info of Q' and repeat
r = random.randint(3, n - 3)
print("Running first 3 prng outputs:")
for x in range(1, 4):
	t = mul(r, g, a, b, n)
	u = mul(r, h, a, b, n)
	print(x,"(pub)","rQ",u)
	r = ((t[0] + t[1]) % n)
print("")

# to predict the next output then multiply: eQ' == erdQ == erdG == redG == P'
# you can now get r' and calculate the next P'' & Q''
print("Calculating next prng output (using e & latest Q):")
z = mul(e, [u[0], u[1]], a, b, n)
s = ((z[0] + z[1]) % n)
v = mul(s, z, a, b, n)
w = mul(s, h, a, b, n)
print(x+1,"(pub)","sQ",w)

# just to be sure
print("Running next prng output:")
for y in range(0, 1):
	t = mul(r, g, a, b, n)
	u = mul(r, h, a, b, n)
	print(x+1,"(pub)","rQ",u)
	r = ((t[0] + t[1]) % n)
print("")

Using a good Curve (25519) to implement a Dual_EC_DRBG based PRNG (bad) in Py

Secure Message iOS App in Swift

Using: Curve25519-ECDH, SHA256-HMAC, AES256-CBC — [Link to the GitHub Project Repo]

 
tcpdump pcap

01:07:18.371915 IP 192.168.1.171.64115 > 31.170.162.63.80: Flags [P.], seq 258:712, ack 1, win 8192, length 454: HTTP
mode=mesg&user=bob&rcpt=jon&mesg=key,31237969521267061265339920357754601118035663355449910125550985699827426505154,7903087581924324533759768883989441673564165222638106623548350836149345932721
--
01:07:18.783449 IP 31.170.162.63.80 > 192.168.1.171.64116: Flags [P.], seq 1:353, ack 539, win 250, length 352: HTTP: HTTP/1.1 200 OK
1450084038.47668400.66932:bob:key,31237969521267061265339920357754601118035663355449910125550985699827426505154,7903087581924324533759768883989441673564165222638106623548350836149345932721
--
01:07:19.547229 IP 192.168.1.171.64117 > 31.170.162.63.80: Flags [P.], seq 258:712, ack 1, win 8192, length 454: HTTP
mode=mesg&user=jon&rcpt=bob&mesg=key,20845162869924781138108110300526986101524551329253196414272755241823588505763,3845740679180735844612211279137657051909097428357280103024866020367868787613
--
01:07:20.637809 IP 31.170.162.63.80 > 192.168.1.171.64118: Flags [P.], seq 1:353, ack 539, win 250, length 352: HTTP: HTTP/1.1 200 OK
1450084039.65591500.56627:jon:key,20845162869924781138108110300526986101524551329253196414272755241823588505763,3845740679180735844612211279137657051909097428357280103024866020367868787613
--
01:07:30.861632 IP 192.168.1.171.64123 > 31.170.162.63.80: Flags [P.], seq 258:672, ack 1, win 8192, length 414: HTTP
mode=mesg&user=bob&rcpt=jon&mesg=msg,471776850.748092,8017053b9ea82e9d52e41052cc3518cd,8bd681694098a46a6ffbb01158672929d1fc5f3859f3fc5cc5030de8e4ed6d6e
--
01:07:33.788855 IP 31.170.162.63.80 > 192.168.1.171.64124: Flags [P.], seq 1:313, ack 539, win 250, length 312: HTTP: HTTP/1.1 200 OK
1450084050.96252100.73649:bob:msg,471776850.748092,8017053b9ea82e9d52e41052cc3518cd,8bd681694098a46a6ffbb01158672929d1fc5f3859f3fc5cc5030de8e4ed6d6e

/* c helper swift functions */

bnum *getx(ecc *e) { return e->x; }
bnum *gety(ecc *e) { return e->y; }

ecc *eccryp()
{
	char *a = "486662", *b = "1", *p = "57896044618658097711785492504343953926634992332820282019728792003956564819949";
	char *x = "9", *y = "43114425171068552920764898935933967039370386198203806730763910166200978582548";
	bnum *t, *u, *v, *w;
	ecc *e;
	
	t = bndec(p);
	u = bninit(t->size); w = bndec(x); bncopy(w, u); bnfree(w);
	v = bninit(t->size); w = bndec(y); bncopy(w, v); bnfree(w);
	e = ecinit(bndec(a), bndec(b), t, u, v);
	
	return e;
}

bnum *bnrnd(int size)
{
	FILE *f;
	bnum *r;
	
	r = bninit(size);
	f = fopen("/dev/urandom", "r");
	fread(r->nums, sizeof(unsigned int), size - 1, f);
	fclose(f);
	r->leng = size;
	while ((r->leng > 1) && (r->nums[r->leng - 1] == 0)) { r->leng -= 1; }
	
	return r;
}

/*
 Curve25519: a=486662, b=1, p=2^255 - 19
 ECC DH: o * (n * P) == onP == noP == n * (o * P)
 */

char *ecdh(ecc *e, const char *n)
{
	char *r = (char *)n;
	bnum *m;
	ecc *f;
	
	if (r == NULL)
	{
		m = bnrnd((e->p)->size);
		r = bnstr(m);
	}
	
	else
	{
		m = bndec((char *)n);
	}
	
	f = ecdup(e);
	pmul(m, e, f);
	
	(f->x)->leng = min((f->x)->leng, (e->p)->size); bncopy(f->x, e->x);
	(f->y)->leng = min((f->y)->leng, (e->p)->size); bncopy(f->y, e->y);
	bnfree(m);
	ecfree(f);
	
	return r;
}

void setexy(ecc *e, const char *x, const char *y)
{
	bnum *t;
	t = bndec((char *)x); t->leng = min(t->leng, (e->p)->size);
	bncopy(t, e->x); bnfree(t);
	t = bndec((char *)y); t->leng = min(t->leng, (e->p)->size);
	bncopy(t, e->y); bnfree(t);
}

char *shash(const char *m)
{
	char *o = malloc(256);
	sha256 hobj;
	sha256init(&hobj);
	sha256update(&hobj, (unsigned char *)m, (unsigned int)strlen(m));
	sha256final(&hobj, o);
	return o;
}

char *sencr(const char *i, const char *m, const char *k, int d)
{
	int x, y, w, z = 0;
	unsigned long ilen = strlen(i), mlen = strlen(m), klen = strlen(k);
	unsigned char tmp[16], ivn[16], msg[16], key[256];
	char *hex = "0123456789abcdef";
	char *enc = malloc(3 * strlen(m));
	
	bzero(key, 256);
	for (x = 0; ((x + 1) < 64) && ((x + 1) < klen); x += 2)
	{
		for (y = 0; y < 16; ++y)
		{
			if (k[x] == hex[y]) { key[x / 2] |= (y << 4); }
			if (k[x + 1] == hex[y]) { key[x / 2] |= y; }
		}
	}
	aes256keys(key);
	
	for (x = 0; x < 16; ++x)
	{
		ivn[x] = 0;
		if (x < ilen) { ivn[x] = i[x]; }
	}
	
	x = 0;
	while (x < mlen)
	{
		if (d == 0)
		{
			for (y = 0; y < 16; ++y)
			{
				msg[y] = 0;
				if (x < mlen) { msg[y] = m[x]; ++x; }
				msg[y] ^= ivn[y];
			}
		}
		else
		{
			for (y = 0; y < 16; ++y)
			{
				msg[y] = 0;
				if ((x + 1) < mlen)
				{
					for (w = 0; w < 16; ++w)
					{
						if (m[x] == hex[w]) { msg[y] |= (w << 4); }
						if (m[x + 1] == hex[w]) { msg[y] |= w; }
					}
					x += 2;
				}
				tmp[y] = msg[y];
			}
		}
		
		aes256core(msg, key, d);
		
		if (d == 0)
		{
			for (y = 0; y < 16; ++y)
			{
				enc[z] = hex[(msg[y] >> 4) & 0xf]; ++z;
				enc[z] = hex[msg[y] & 0xf]; ++z;
				ivn[y] = msg[y];
			}
		}
		else
		{
			for (y = 0; y < 16; ++y)
			{
				enc[z] = (msg[y] ^ ivn[y]); ++z;
				ivn[y] = tmp[y];
			}
		}
	}
	enc[z] = 0;
	
	return enc;
}

char *hmac(const char *m, const char *k)
{
	int x, y, i, j, bs = 64;
	unsigned long mlen = strlen(m), klen = strlen(k);
	char *hex = "0123456789abcdef", *hmout = malloc(256);
	unsigned char key[bs], ipad[bs], opad[bs];
	sha256 hobj;
	
	bzero(key, bs);
	for (x = 0; ((x + 1) < 64) && ((x + 1) < klen); x += 2)
	{
		for (y = 0; y < 16; ++y)
		{
			if (k[x] == hex[y]) { key[x / 2] |= (y << 4); }
			if (k[x + 1] == hex[y]) { key[x / 2] |= y; }
		}
	}
	
	for (x = 0; x < bs; ++x)
	{
		ipad[x] = (0x36 ^ key[x]);
		opad[x] = (0x5C ^ key[x]);
	}
	
	sha256init(&hobj);
	sha256update(&hobj, ipad, bs);
	sha256update(&hobj, (unsigned char *)m, (unsigned int)mlen);
	sha256final(&hobj, hmout);
	
	for (x = 0; x < 8; ++x)
	{
		for (y = 0; y < 4; ++y)
		{
			i = ((x * 4) + y);
			j = (24 - (y * 8));
			key[i] = ((hobj.h[x] >> j) & 0xff);
		}
	}
	
	sha256init(&hobj);
	sha256update(&hobj, opad, bs);
	sha256update(&hobj, key, 32);
	sha256final(&hobj, hmout);
	
	return hmout;
}

//
//  ViewController.swift
//  smsg
//

import UIKit

class ViewController: UIViewController, UITableViewDelegate, UITableViewDataSource {

	let userText: UITextField = UITextField(frame: CGRect(x: 10.00, y: 32.00, width: 200.00, height: 30.00))
	let passText: UITextField = UITextField(frame: CGRect(x: 10.00, y: 64.00, width: 200.00, height: 30.00))
	let authButn: UIButton = UIButton(frame: CGRect(x: 225.00, y: 64.00, width: 100.00, height: 30.00))
	
	let frndText: UITextField = UITextField(frame: CGRect(x: 10.00, y: 96.00, width: 200.00, height: 30.00))
	let frndButn: UIButton = UIButton(frame: CGRect(x: 225.00, y: 96.00, width: 100.00, height: 30.00))
	let seckText: UILabel = UILabel(frame: CGRect(x: 10.00, y: 128.00, width: 300.00, height: 30.00))
	
	var mesgList: [String] = ["line 1", "line 2", "line 3"]
	let mesgHist: UITableView = UITableView(frame: CGRect(x: 10.00, y: 160.00, width: 300.00, height: 120.00))
	let mesgText: UITextView = UITextView(frame: CGRect(x: 10.00, y: 284.00, width: 200.00, height: 60.00))
	let mesgButn: UIButton = UIButton(frame: CGRect(x: 225.00, y: 284.00, width: 100.00, height: 30.00))
	
	let vers = "1.9.9.1"
	let serv = "http://smsg.site88.net"
	var authkey: String = ""
	var dhkey: String = ""
	var dhx: String = ""
	var dhy: String = ""
	var skey: String = ""
	var tkey: String = ""
	var ecobj = eccryp()
	
	func readReply(mode: Int, response: String) {
		if (response != "") { print("r>"+response) }
		
		if (response.characters.count > 5)
		{
			if (mode == 0)
			{
				self.authkey = response.substringWithRange(Range<String.Index>(start:response.startIndex.advancedBy(5), end:response.endIndex))
				
				dispatch_async(dispatch_get_main_queue()) { self.seckText.text = (" " + self.authkey) }
			}
			
			else if (mode == 3)
			{
				let linelist = response.characters.split{$0 == "\n"}.map(String.init)
				for line in linelist
				{
					let readlist = line.characters.split{$0 == ":"}.map(String.init)
					if (readlist.count > 2)
					{
						let infolist = readlist[2].characters.split{$0 == ","}.map(String.init)
						
						if (infolist.count == 3)
						{
							if ((readlist[1] == frndText.text) && (infolist[0] == "key"))
							{
								if (self.dhkey == "")
								{
									self.dhkey = String.fromCString(ecdh(self.ecobj, nil))!
									self.dhx = String.fromCString(bnstr(getx(self.ecobj)))!
									self.dhy = String.fromCString(bnstr(gety(self.ecobj)))!
									self.sendMesg(1, mesg: self.dhx+","+self.dhy)
								}
								
								setexy(self.ecobj, infolist[1], infolist[2])
								ecdh(self.ecobj, self.dhkey)
								let tdhx = String.fromCString(bnstr(getx(self.ecobj)))
								let tdhy = String.fromCString(bnstr(gety(self.ecobj)))
								
								print("d>"+tdhx!+","+tdhy!)
								self.skey = String.fromCString(shash(tdhx!+","+tdhy!))!
								self.tkey = String.fromCString(shash(self.skey))!
								print("k>"+self.skey+","+self.tkey)
								dispatch_async(dispatch_get_main_queue()) { self.seckText.text = (" " + self.skey) }
							}
						}
						
						else if (infolist.count == 4)
						{
							if ((readlist[1] == frndText.text) && (infolist[0] == "msg"))
							{
								let smac = String.fromCString(hmac(infolist[1]+","+infolist[2], self.tkey))
								print("v>"+smac!+"=="+infolist[3])
								if (smac == infolist[3])
								{
									let smesg = String.fromCString(sencr(infolist[1], infolist[2], self.skey, 1))
									self.mesgList.append(smesg!)
									dispatch_async(dispatch_get_main_queue()) { self.mesgHist.reloadData() }
								}
							}
						}
					}
				}
			}
		}
	}
	
	func sendMesg(mode: Int, mesg: String) {
		var postdata: String = ""
		
		if (mode == 0)
		{
			postdata = ("mode=auth&user="+self.userText.text!+"&pass="+self.passText.text!)
		}
		
		else if (mode == 1)
		{
			postdata = ("mode=mesg&user="+self.userText.text!+"&auth="+self.authkey+"&rcpt="+self.frndText.text!+"&mesg=key,"+mesg)
		}
		
		else if (mode == 2)
		{
			postdata = ("mode=mesg&user="+self.userText.text!+"&auth="+self.authkey+"&rcpt="+self.frndText.text!+"&mesg=msg,"+mesg)
		}
		
		else if (mode == 3)
		{
			postdata = ("mode=read&user="+self.userText.text!+"&auth="+self.authkey)
		}
		
		let request = NSMutableURLRequest(URL: NSURL(string: self.serv)!)
		request.HTTPMethod = "POST"
		request.HTTPBody = postdata.dataUsingEncoding(NSUTF8StringEncoding)
		let task = NSURLSession.sharedSession().dataTaskWithRequest(request) {
			data, response, error in
			let reply = NSString(data: data!, encoding: NSUTF8StringEncoding)
			self.readReply(mode, response: reply as! String)
		}
		task.resume()
	}
	
	func butnPress(butn: UIButton) {
		if (butn.titleLabel?.text == "Login") { self.sendMesg(0, mesg: "") }
		if (butn.titleLabel?.text == "Add")
		{
			if (self.dhkey == "")
			{
				self.dhkey = String.fromCString(ecdh(self.ecobj, nil))!
				self.dhx = String.fromCString(bnstr(getx(self.ecobj)))!
				self.dhy = String.fromCString(bnstr(gety(self.ecobj)))!
			}
			self.sendMesg(1, mesg: self.dhx+","+self.dhy)
		}
		if (butn.titleLabel?.text == "Send")
		{
			if (self.skey != "")
			{
				let stime = String(NSDate.timeIntervalSinceReferenceDate())
				let smesg = String.fromCString(sencr(stime, self.mesgText.text, self.skey, 0))
				let smac = String.fromCString(hmac(stime+","+smesg!, self.tkey))
				self.sendMesg(2, mesg: stime+","+smesg!+","+smac!)
			}
		}
	}
	
	func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
		return self.mesgList.count
	}
	
	func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
		let cell = UITableViewCell(style: UITableViewCellStyle.Default, reuseIdentifier: "cell")
		cell.textLabel!.text = self.mesgList[indexPath.row]
		cell.textLabel!.font = cell.textLabel!.font.fontWithSize(10)
		return cell
	}
	
	func backFunc(timer: NSTimer) {
		self.sendMesg(3, mesg: "")
	}
	
	override func viewDidLoad() {
		super.viewDidLoad()
		// Do any additional setup after loading the view, typically from a nib.
		
		print("i>draw init")
		
		/* login elements */
		
		let userPadd = UIView(frame: CGRectMake(0, 0, 5, self.userText.frame.size.height))
		self.userText.leftView = userPadd
		self.userText.leftViewMode = UITextFieldViewMode.Always
		self.userText.layer.cornerRadius = 2.0
		self.userText.layer.borderColor = UIColor(red: 0/255, green: 0/255, blue: 0/255, alpha: 1.0).CGColor
		self.userText.layer.borderWidth = 2.0
		self.userText.autocorrectionType = UITextAutocorrectionType.No
		self.userText.autocapitalizationType = UITextAutocapitalizationType.None
		self.view.addSubview(self.userText)
		
		let passPadd = UIView(frame: CGRectMake(0, 0, 5, self.passText.frame.size.height))
		self.passText.leftView = passPadd
		self.passText.leftViewMode = UITextFieldViewMode.Always
		self.passText.layer.cornerRadius = 2.0
		self.passText.layer.borderColor = UIColor(red: 0/255, green: 0/255, blue: 0/255, alpha: 1.0).CGColor
		self.passText.layer.borderWidth = 2.0
		self.passText.secureTextEntry = true
		self.view.addSubview(self.passText)
		
		self.authButn.layer.cornerRadius = 2.0
		self.authButn.layer.borderColor = UIColor(red: 0/255, green: 0/255, blue: 0/255, alpha: 1.0).CGColor
		self.authButn.layer.borderWidth = 2.0
		self.authButn.setTitle("Login", forState: UIControlState.Normal)
		self.authButn.setTitleColor(UIColor.blackColor(), forState: UIControlState.Normal)
		self.authButn.addTarget(self, action: "butnPress:", forControlEvents: UIControlEvents.TouchUpInside)
		self.view.addSubview(self.authButn)
		
		/* friend elements */
		
		let frndPadd = UIView(frame: CGRectMake(0, 0, 5, self.userText.frame.size.height))
		self.frndText.leftView = frndPadd
		self.frndText.leftViewMode = UITextFieldViewMode.Always
		self.frndText.layer.cornerRadius = 2.0
		self.frndText.layer.borderColor = UIColor(red: 0/255, green: 0/255, blue: 0/255, alpha: 1.0).CGColor
		self.frndText.layer.borderWidth = 2.0
		self.frndText.autocorrectionType = UITextAutocorrectionType.No
		self.frndText.autocapitalizationType = UITextAutocapitalizationType.None
		self.view.addSubview(self.frndText)
		
		self.frndButn.layer.cornerRadius = 2.0
		self.frndButn.layer.borderColor = UIColor(red: 0/255, green: 0/255, blue: 0/255, alpha: 1.0).CGColor
		self.frndButn.layer.borderWidth = 2.0
		self.frndButn.setTitle("Add", forState: UIControlState.Normal)
		self.frndButn.setTitleColor(UIColor.blackColor(), forState: UIControlState.Normal)
		self.frndButn.addTarget(self, action: "butnPress:", forControlEvents: UIControlEvents.TouchUpInside)
		self.view.addSubview(self.frndButn)
		
		self.seckText.layer.cornerRadius = 2.0
		self.seckText.layer.borderColor = UIColor(red: 0/255, green: 0/255, blue: 0/255, alpha: 1.0).CGColor
		self.seckText.layer.borderWidth = 2.0
		self.seckText.font = self.seckText.font.fontWithSize(8)
		self.seckText.text = (" v" + self.vers)
		self.view.addSubview(self.seckText)
		
		/* message elements */
		
		self.mesgHist.layer.cornerRadius = 2.0
		self.mesgHist.layer.borderColor = UIColor(red: 0/255, green: 0/255, blue: 0/255, alpha: 1.0).CGColor
		self.mesgHist.layer.borderWidth = 2.0
		self.mesgHist.rowHeight = 20.0
		self.mesgHist.delegate = self
		self.mesgHist.dataSource = self
		self.view.addSubview(self.mesgHist)
		
		self.mesgText.layer.cornerRadius = 2.0
		self.mesgText.layer.borderColor = UIColor(red: 0/255, green: 0/255, blue: 0/255, alpha: 1.0).CGColor
		self.mesgText.layer.borderWidth = 2.0
		self.mesgText.autocorrectionType = UITextAutocorrectionType.No
		self.mesgText.autocapitalizationType = UITextAutocapitalizationType.None
		self.mesgText.text = "message string"
		self.view.addSubview(self.mesgText)
		
		self.mesgButn.layer.cornerRadius = 2.0
		self.mesgButn.layer.borderColor = UIColor(red: 0/255, green: 0/255, blue: 0/255, alpha: 1.0).CGColor
		self.mesgButn.layer.borderWidth = 2.0
		self.mesgButn.setTitle("Send", forState: UIControlState.Normal)
		self.mesgButn.setTitleColor(UIColor.blackColor(), forState: UIControlState.Normal)
		self.mesgButn.addTarget(self, action: "butnPress:", forControlEvents: UIControlEvents.TouchUpInside)
		self.view.addSubview(self.mesgButn)
		
		/* background reader */
		
		NSTimer.scheduledTimerWithTimeInterval(5.0, target: self, selector: "backFunc:", userInfo: nil, repeats: true)
	}

	override func didReceiveMemoryWarning() {
		super.didReceiveMemoryWarning()
		// Dispose of any resources that can be recreated.
	}

}

Secure Message iOS App in Swift

A Basic ECC Crypto C Library

$ gcc -Wall -O2 -o crypto.out crypto.c 
$ ./crypto.out pgen 

x: [0][7][8]=[4880449572248532107701327692677150037572104965674444437385142643512]
y^2: [0][8][8]=[55380869580354224246510320945966028555317502525493429017926966133843051295792]
y: [0][8][8]=[29139577269574826820926935201858599433659429201914524387051377879407947248399]

$ ./crypto.out ecdh 

  1*(y^2) = x^3 + 486662*(x^2) + x (mod 57896044618658097711785492504343953926634992332820282019728792003956564819949)
    17101372528228046186917539708449150102286202153232625914396359604563
      * P(x, y) = (9, 43114425171068552920764898935933967039370386198203806730763910166200978582548)

      = Q(x, y) = (38616894501258673852970036866543659072635089662921568068340331697101576554270, 11643169480892671629858370512120070259223559167488419079368716073871895962191)


  1*(y^2) = x^3 + 486662*(x^2) + x (mod 57896044618658097711785492504343953926634992332820282019728792003956564819949)
    12761708460950637051849206961623904377595162559992784492118523127724
      * P(x, y) = (9, 43114425171068552920764898935933967039370386198203806730763910166200978582548)

      = Q(x, y) = (32477568348650104756356831653582245276448206004887493791495532411741897328458, 28063399834915231969701720976238207473037393607389857712493721633327966471074)


  1*(y^2) = x^3 + 486662*(x^2) + x (mod 57896044618658097711785492504343953926634992332820282019728792003956564819949)
    17101372528228046186917539708449150102286202153232625914396359604563
      * P(x, y) = (32477568348650104756356831653582245276448206004887493791495532411741897328458, 28063399834915231969701720976238207473037393607389857712493721633327966471074)

      = Q(x, y) = (50351522368134241142819091458530332577142187603512687882689541070260459723459, 50221873001104206223375144395698504985316658966829066883833880358017679689691)


  1*(y^2) = x^3 + 486662*(x^2) + x (mod 57896044618658097711785492504343953926634992332820282019728792003956564819949)
    12761708460950637051849206961623904377595162559992784492118523127724
      * P(x, y) = (38616894501258673852970036866543659072635089662921568068340331697101576554270, 11643169480892671629858370512120070259223559167488419079368716073871895962191)

      = Q(x, y) = (50351522368134241142819091458530332577142187603512687882689541070260459723459, 50221873001104206223375144395698504985316658966829066883833880358017679689691)

$ ./crypto.out psig 1234
Sign:

d=[0][7][8]=[6538729008379423383518670268808646995288081785172776771199052697947]
P=(x, y) = (9, 43114425171068552920764898935933967039370386198203806730763910166200978582548)
dP=(x, y) = (14803911054618354585053684993263408691271520722671720792800356230205975217771, 11341018286853926408444620055947798723342444873304700039478772171855673884697)

h=[0][1][1]=[1234]

k=[0][7][8]=[8232207578348459001023088138872857936131335029042440438075457201646]
kP=(x, y) = (31369530948108575720266905846722071920323191212477028674668598541699791483098, 9139751042718096616566254849289158387164951389944576741553517798024823610265)
r=[0][15][40]=[149879290832663482850783820956010355668942537394521944880131051841396204961042266046319521062426903751537961621638691535228251607511236059222514]

Verify:

P=(x, y) = (9, 43114425171068552920764898935933967039370386198203806730763910166200978582548)
dP=(x, y) = (14803911054618354585053684993263408691271520722671720792800356230205975217771, 11341018286853926408444620055947798723342444873304700039478772171855673884697)

h=[0][1][1]=[1234]

kP=(x, y) = (31369530948108575720266905846722071920323191212477028674668598541699791483098, 9139751042718096616566254849289158387164951389944576741553517798024823610265)
r=[0][15][40]=[149879290832663482850783820956010355668942537394521944880131051841396204961042266046319521062426903751537961621638691535228251607511236059222514]

(ek+hd)P=(x, y) = (51608966471038425598161188547671772160458281462630354621077601757763167308540, 17341325372123419326180270058693292718501038313000707228169935748980907943680)
==
rP=(x, y) = (51608966471038425598161188547671772160458281462630354621077601757763167308540, 17341325372123419326180270058693292718501038313000707228169935748980907943680)

[GOOD]
$ ./crypto.out penc 1234
Encrypt:

P=(x, y) = (9, 43114425171068552920764898935933967039370386198203806730763910166200978582548)
dP=(x, y) = (19547865285467707344496388019666506767309887017163137556078134582670804301851, 36180672281078333342162157694938953906019362565570590334768364807054263309922)

h=[0][1][1]=[1234]

k=[0][7][8]=[3873062938517225834483697070677896532844396051944377142545351178872]
kP=(x, y) = (31307487414183777373465427652384958249613501222520858769326720798351611112341, 42327343332069595141617190350930625663948508466032477124028143798481079201841)
kdP=(x, y) = (17546014782981223520910010062776248455503090940217295620750099274078977893385, 40213720617506594547897783150731613585768378209283692064354760696398013829358)

Decrypt:

P=(x, y) = (9, 43114425171068552920764898935933967039370386198203806730763910166200978582548)
dP=(x, y) = (19547865285467707344496388019666506767309887017163137556078134582670804301851, 36180672281078333342162157694938953906019362565570590334768364807054263309922)

d=[0][7][8]=[22873181922607864299317581582398892665871088710637471622228302193764]
dkP=(x, y) = (17546014782981223520910010062776248455503090940217295620750099274078977892151, 40213720617506594547897783150731613585768378209283692064354760696398013829358)

t=[0][1][8]=[1234]

$ 
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <strings.h>

#include "../lib/sha256.c"
#include "../lib/aes256.c"
#include "../lib/ec.c"

bnum *bnrnd(int size)
{
	FILE *f;
	bnum *r;
	
	r = bninit(size);
	f = fopen("/dev/urandom", "r");
	fread(r->nums, sizeof(unsigned int), size - 1, f);
	fclose(f);
	r->leng = size;
	while ((r->leng > 1) && (r->nums[r->leng - 1] == 0)) { r->leng -= 1; }
	
	return r;
}

void eccp(ecc *e, char *xs)
{
	int psiz = (e->p)->size;
	bnum *x = bninit(psiz), *y = bninit(psiz), *t;
	
	bnum *xa = bninit(psiz * 4), *xx = bninit(psiz * 4);
	bnum *yy = bninit(psiz * 4), *vv = bninit(psiz * 4);
	
	if (xs != NULL) { t = bndec(xs); }
	else { t = bnrnd(psiz); }
	bncopy(t, x);
	
	while (1)
	{
		// yy = ((x * (x * x)) + (a * (x * x)) + x) % m
		bnzero(xx); bnmul(x, x, xx);
		bnzero(xa); bnmul(xx, e->a, xa);
		bnzero(vv); bnmul(x, xx, vv);
		
		bnzero(yy); bnadd(vv, xa, yy, 1); bnadd(yy, x, vv, 1);
		bndiv(vv, e->p, xx, t);
		// todo: divide t by b?
		
		printf("\n");
		bnout("x: ", x, "\n");
		bnout("y^2: ", t, "\n");
		
		if (sqrtmod(t, e->p, y) == 0) { break; }
		
		if (x != NULL) { bnfree(x); }
		x = bnrnd(psiz);
	}
	
	bnout("y: ", y, "\n\n");
	// note: another y point == p - y
	
	bnzero(yy); bncopy(t, yy);
	bnzero(vv); bnmul(y, y, vv);
	bnzero(xx); bndiv(vv, e->p, xa, xx);
	
	bnfree(xa); bnfree(vv); bnfree(t);
	
	if (bncmp(xx, yy) != 0)
	{
		bnout("y^2: ",xx," != "); bnout("y^2: ",yy,"\n");
	}
	
	bnfree(xx); bnfree(yy);
	bnfree(x); bnfree(y);
}

/*
Curve25519: a=486662, b=1, p=2^255 - 19
ECC DH: o * (n * P) == onP == noP == n * (o * P)
*/

char *ecdh(ecc *e, char *n, int o)
{
	char *r = n;
	bnum *m;
	ecc *f;
	
	if (r == NULL)
	{
		m = bnrnd((e->p)->size);
		r = bnstr(m);
	}
	
	else
	{
		m = bndec(n);
	}
	
	f = ecdup(e);
	pmul(m, e, f);
	
	if (o == 1)
	{
		char v[2050];
		bzero(v, 2050 * sizeof(char));
		strncat(v, "    "       , max(0, 2048 - strlen(v)));
		strncat(v, r            , max(0, 2048 - strlen(v)));
		strncat(v, "\n      * P", max(0, 2048 - strlen(v)));
		printf("\n");
		ecout(1,v,e,"\n\n");
		ecout(0,"      = Q",f,"\n");
		printf("\n");
	}
	
	bnfree(e->x); e->x = bndup(f->x);
	bnfree(e->y); e->y = bndup(f->y);
	bnfree(m);
	ecfree(f);
	
	return r;
}

/*
ECC - Private Sign / Public Verify

* initialize
- generate secret key          : d
- publish                      : P, dP

* private sign
- hash message                 : h = SHA256(m)
- secret unique multiplier     : k
- calculate public multipliers : kP
                               : e = hP(x)
                               : r = ((e * k) + (h * d))
- publish                      : kP, r

* public verify
                               : e = hP(x)
-                              : (e * kP) + (h * dP) == rP
*/

int ecsig(ecc *e, bnum *d, ecc *dp, char *hh, ecc *kp, bnum *r, int o)
{
	int a = 0, psiz = (e->p)->size;
	bnum *k, *h;
	bnum *t = bninit(psiz * 5), *u = bninit(psiz * 5);
	ecc *hp = ecdup(e), *ekp = ecdup(e), *hdp = ecdup(e), *ekhdp = ecdup(e), *rp = ecdup(e);
	ect *tadd = etinit(e);
	
	if (hh != NULL)
	{
		if (((kp->x)->leng == 1) && ((kp->x)->nums[0] == 0))
		{
			if ((d->leng == 1) && (d->nums[0] == 0))
			{
				k = bnrnd(psiz); bncopy(k, d); bnfree(k);
				pmul(d, e, dp);
				
				if (o == 1) { bnout("d=", d, "\n"); }
			}
		}
		
		if (o == 1)
		{
			ecout(0, "P=", e, "\n");
			ecout(0, "dP=", dp, "\n\n");
		}
		
		h = bndec(hh);
		pmul(h, e, hp);
		
		if (o == 1) { bnout("h=", h, "\n\n"); }
		
		if (((kp->x)->leng == 1) && ((kp->x)->nums[0] == 0))
		{
			k = bnrnd(psiz);
			pmul(k, e, kp);
			
			if (o == 1) { bnout("k=", k, "\n"); }
			
			bnzero(t); bnmul(hp->x, k, t);
			bnzero(u); bnmul(h, d, u);
			bnadd(t, u, r, 1);
			
			bnfree(k);
		}
		
		if (o == 1)
		{
			ecout(0, "kP=", kp, "\n");
			bnout("r=", r, "\n\n");
		}
		
		pmul(hp->x, kp, ekp);
		pmul(h, dp, hdp);
		padd(ekp, hdp, ekhdp, tadd);
		pmul(r, e, rp);
		
		if ((d->leng == 1) && (d->nums[0] == 0))
		{
			if (o == 1)
			{
				ecout(0, "(ek+hd)P=", ekhdp, "\n==\n");
				ecout(0, "rP=", rp, "\n\n");
			}
		}
		
		if (bncmp(ekhdp->x, rp->x) == 0)
		{
			if (bncmp(ekhdp->y, rp->y) == 0)
			{
				a = 1;
			}
		}
		
		bnfree(h);
	}
	
	bnfree(t); bnfree(u);
	ecfree(hp); ecfree(ekp); ecfree(hdp); ecfree(ekhdp); ecfree(rp);
	etfree(tadd);
	
	return a;
}

/*
ECC ElGamal - Public Encrypt / Private Decrypt

* initialize
- generate secret integer  : d
- publish                  : P, dP

* public encrypt
- generate secret key      : t = (SHA256(pwd) || tmpkey)
- secret unique multiplier : k = rand()
- public key encrypt       : r = k * P        = kP
                           : s = t + (k * dP) = t + kdP = kdP(x + t, y + t)
- encrypt optional message : i = rand()
                           : e = AES256CBC(m, i, t)
- publish                  : [ (r, s) , (i, e) ]

* private decrypt
- private key decrypt      : u = s - (d * r)
                               = (t + kdP) - (d * kP)
                               = kdP(x + t, y + t) - dkP(x, y)
                               = kdP(x - x + t)
                               = t
*/

void ecenc(ecc *e, bnum *d, ecc *dp, char *hh, ecc *kp, ecc *kdp, int o)
{
	int psiz = (e->p)->size;
	bnum *k, *h, *t;
	ecc *dkp;
	
	if (hh != NULL)
	{
		if ((d->leng == 1) && (d->nums[0] == 0))
		{
			k = bnrnd(psiz); bncopy(k, d); bnfree(k); k = NULL;
			pmul(d, e, dp);
		}
		
		if (o == 1)
		{
			ecout(0, "P=", e, "\n");
			ecout(0, "dP=", dp, "\n\n");
		}
		
		h = bndec(hh);
		
		if (((kp->x)->leng == 1) && ((kp->x)->nums[0] == 0))
		{
			if (o == 1) { bnout("h=", h, "\n\n"); }
			
			k = bnrnd(psiz);
			pmul(k, e, kp);
			
			pmul(k, dp, kdp);
			t = kdp->x; kdp->x = bninit(psiz + 1); bncopy(t, kdp->x); bnfree(t);
			bnadd(kdp->x, h, kdp->x, 1);
			
			if (o == 1)
			{
				bnout("k=", k, "\n");
				ecout(0, "kP=", kp, "\n");
				ecout(0, "kdP=", kdp, "\n\n");
			}
			
			bnfree(k);
		}
		
		else
		{
			dkp = ecdup(e);
			pmul(d, kp, dkp);
			t = bninit(psiz); bnsub(kdp->x, dkp->x, t, 1);
			
			if (o == 1)
			{
				bnout("d=", d, "\n");
				ecout(0, "dkP=", dkp, "\n\n");
				bnout("t=", t, "\n\n");
			}
			
			bnfree(t);
			ecfree(dkp);
		}
		
		bnfree(h);
	}
}

int main(int argc, char **argv)
{
	char *a = "486662", *b = "1", *p = "57896044618658097711785492504343953926634992332820282019728792003956564819949";
	char *x = "9", *y = "43114425171068552920764898935933967039370386198203806730763910166200978582548";
	char *n, *m, *z = NULL;
	char hash[256];
	unsigned char msg[16], key[256];
	bnum *d, *r, *s;
	bnum *t, *u, *v, *w;
	ecc *e, *f, *dp, *kp, *kdp;
	
	if (argc > 2) { z = argv[2]; }
	
	t = bndec(p);
	u = bninit(t->size); w = bndec(x); bncopy(w, u); bnfree(w);
	v = bninit(t->size); w = bndec(y); bncopy(w, v); bnfree(w);
	e = ecinit(bndec(a), bndec(b), t, u, v);
	
	if (strcmp(argv[1], "pgen") == 0)
	{
		eccp(e, z);
	}
	
	if (strcmp(argv[1], "pmul") == 0)
	{
		ecdh(e, argv[2], 1);
	}
	
	if (strcmp(argv[1], "ecdh") == 0)
	{
		f = ecdup(e);
		
		n = ecdh(e, NULL, 1);
		m = ecdh(f, NULL, 1);
		
		t = e->x; u = e->y;
		e->x = f->x; e->y = f->y;
		f->x = t; f->y = u;
		
		ecdh(e, n, 1);
		ecdh(f, m, 1);
		
		free(n); free(m);
		ecfree(f);
	}
	
	if (strcmp(argv[1], "psig") == 0)
	{
		d = bninit((e->p)->size);
		dp = ecdup(e); kp = ecdup(e);
		r = bninit((e->p)->size * 5);
		s = bninit((e->p)->size * 5);
		
		printf("Sign:\n\n");
		(kp->x)->leng = 1; (kp->x)->nums[0] = 0;
		(kp->y)->leng = 1; (kp->y)->nums[0] = 0;
		ecsig(e, d, dp, z, kp, r, 1);
		
		printf("Verify:\n\n");
		bnzero(d);
		if (ecsig(e, d, dp, z, kp, r, 1) != 0) { printf("[GOOD]\n"); }
		else { printf("\n[FAILED]\n"); }
		
		bnfree(d); bnfree(r); bnfree(s);
		ecfree(dp); ecfree(kp);
	}
	
	if (strcmp(argv[1], "penc") == 0)
	{
		d = bninit((e->p)->size);
		dp = ecdup(e); kp = ecdup(e); kdp = ecdup(e);
		
		printf("Encrypt:\n\n");
		(kp->x)->leng = 1; (kp->x)->nums[0] = 0;
		(kp->y)->leng = 1; (kp->y)->nums[0] = 0;
		ecenc(e, d, dp, z, kp, kdp, 1);
		
		printf("Decrypt:\n\n");
		ecenc(e, d, dp, z, kp, kdp, 1);
		
		bnfree(d);
		ecfree(dp); ecfree(kp); ecfree(kdp);
	}
	
	if (strcmp(argv[1], "hash") == 0)
	{
		sha256 hobj;
		sha256init(&hobj);
		sha256update(&hobj, (unsigned char *)argv[2], strlen(argv[2]));
		sha256final(&hobj, hash);
		printf("%s\n", hash);
	}
	
	if (strcmp(argv[1], "menc") == 0)
	{
		bzero(key, 256);
		strcpy((char *)key, argv[3]);
		aes256keys(key);
		
		bzero(msg, 16);
		strcpy((char *)msg, argv[2]);
		aes256core(msg, key, 0);
		
		int i;
		for (i = 0; i < 16; ++i) { printf("%02x", msg[i]); }
		printf("\n");
	}
	
	ecfree(e);
	
	return 0;
}

A Basic ECC Crypto C Library