kmcg3413.net

kmcg3413.net

You can reach me at kmcg3413@gmail.com

This site contains random things that I decided were worthy of being put on the internet.

Contents:

7/6/2014Python 3.x Cross Platform Console Library
6/30/2014Demonstration Of Different I/O Modes On Sockets Using Python
6/30/2014Demonstation In Go Of Sync, Async, And Buffering Communication
6/11/2014ASN.1 Data Python Reading Example
5/29/2014Python RSA Public Private Key Encryption SSH using ssh-keyen
5/25/2014Blocky To Go Live As Beta Soon
5/21/2014Python Public/Private Key Generation And Usage
5/21/2014Operating System Project
5/21/2014Inventory Tracking
5/19/2013Silicon Diode As A Switch
5/19/2013Rough And Dirty IF Mixer
6/08/2013Mason File Synchronization (Linux/Windows)
5/19/2013Inductor Filtering
5/26/2013Python Raw Packet
6/2/2013Python IP/TCP Checksum Calculation
Operating System Development
2008OpenOCD AUDC702X Flash Driver/Module
Dwarf Fortress Adventures
1/30/2014EXAMPLE OF RSA ENCRYPTION/DECRYPTION USING PRE-GENERATED PRIVATE PUBLIC OPENSSH KEY FILES
6/2/2013OpenVZ/Parallels SLL (VENET?) Interface SOCK_RAW AF_PACKET
2/15/2014RSA SSHD Key Generation - Default Size 768-Bit
3/30/2014OSDEV.ORG PAGES AND ARTICLES
5/4/2014Parse Lighttpd Log With Python

Sections:

7/6/2014Python 3.x Cross Platform Console Library
After a bit of work I have come up with a nice light-weight cross platform console library. It currently supports Linux and Windows NT operating systems. If on Linux you must have ncurses installed and have Python compiled with support. I would love to do a version that did not use ncurses but there are some complications in doing so right now.
'''
    Leonard Kevin McGuire Jr 2014 (kmcg3413@gmail.com)

    CrossTerm

    This gives an implementation similar to ncurses and the python curses module. The
    API is totally different, but it does try to provide a minimal cross-platform 
    support for positional printing and colors.

    It also supports cross-process access. This allows you to query information from
    another process through a TCP server.

    * colors still being implemented
'''

import random
import struct
import sys
import math
import sys

from ctypes import *

try:
    import curses
    hasCurses = True
except:
    hasCurses = False

class BufferInfo:
    pass


class CrossTerm:
    def __init__(self, win):
        global hasCurses
        self.win = win
        self.hasCurses = hasCurses
        # if on win32 platform use kernel32 dynamic link library
        if not hasCurses:
            self.hdll = windll.LoadLibrary('kernel32.dll')
            #self.hSetConsoleCursorPosition = CFUNCTYPE(c_int)(('SetConsoleCursorPosition', self.hdll))
            self.hSetConsoleCursorPosition = self.hdll['SetConsoleCursorPosition']
            #self.hGetStdHandle = CFUNCTYPE(c_uint)(('GetStdHandle', self.hdll))
            self.hGetStdHandle = self.hdll['GetStdHandle']
            #self.hWriteConsoleOutputCharacter = CFUNCTYPE(c_uint)(('WriteConsoleOutputCharacterA', self.hdll))
            self.hWriteConsoleOutputCharacter = self.hdll['WriteConsoleOutputCharacterA']
            #self.hGetConsoleScreenBufferInfo = CFUNCTYPE(c_uint)(('GetConsoleScreenBufferInfo', self.hdll))
            self.hGetConsoleScreenBufferInfo = self.hdll['GetConsoleScreenBufferInfo']
            sw, sh = self.getScreenSize()

            # scroll the buffer so we get a new blank space
            # similar to how curses initializes the screen
            for i in range(0, sh):
                print('')
            # get the row index of the top line of our current
            # screen
            binfo = self._getConsoleScreenBufferInfo()
            self.topy = binfo.winY

    '''
        This will set the absolute cursor position.

        * curses did not implement this.. so me either but
          just wanted the code to stay for future reference
          if needed (for the win32 function call)
    '''
    #def setCursorPosition(self, x, y):
    #    if self.hasCurses:
    #        
    #    else:
    #        ch = self.hGetStdHandle(c_int(-11))
    #        self.hSetConsoleCursorPosition(c_uint(ch), c_short(x), c_short(y))

    '''
        Will return current cursor position.
    '''
    def getCursorPosition(self):
        if self.hasCurses:
            return self.win.getyx()
        else:
            ch = self.hGetStdHandle(c_int(-11))
            buf = struct.pack(' 0:
            if len(s) < maxpad:
                s = '%s%s' % (s, ' ' * (maxpad - len(s)))
            else:
                s = s[0:maxpad]

        if self.hasCurses:
            self.win.addstr(y, x, s, attr)
        else:
            y = self.topy + y
            ch = self.hGetStdHandle(c_int(-11))
            s = bytes(s, 'utf8')
            wrote = struct.pack(' self.w * self.h:
            # truncate it
            text = text[0:self.w * self.h]
        rowcnt = int(math.ceil(len(text) / self.w))
        # write it over entire box
        for row in range(0, rowcnt):
            off = row * self.w
            line = text[off:self.w]
            if len(line) < self.w:
                line = '%s%s' % (line, ' ' * (self.w - len(line)))
            self.ct.writeStringAt(self.x, self.y + row, line)


'''
    This provides enhanced and extra features.

    [X] box support
    [ ] tcp server support
'''
class CrossTerm2(CrossTerm):
    def __init__(self, *args):
        super().__init__(*args)
        self.w, self.h = self.getScreenSize()
        self.boxes = []

    '''
        You specify the box width and height and it will
        find a spot to put it.
    '''
    def getBoxAuto(self, w, h, prefix = ''):
        for x in range(0, self.w):
            for y in range(0, self.h):
                box = self.getBox(x, y, w, h, prefix = prefix)
                if box is not None:
                    return box
        # no space big enough for the box
        return None

    '''
        This will create a new box.
    '''
    def getBox(self, x, y, w, h, prefix = ''):
        # look through list of boxes and find place to put
        nx1 = x
        ny1 = y
        nx2 = (x + w) - 1
        ny2 = (y + h) - 1

        # check for overlap
        for box in self.boxes:
            bx1, by1, bx2, by2 = box.getRect()
            bx2 += bx1
            by2 += by1

            if nx1 >= bx1 and nx1 < bx2 and ny1 >= by1 and ny1 < by2:
                if nx2 >= bx1 and nx2 < bx2 and ny2 >= by1 and ny2 < by2:
                    return None
        nbox = CrossTerm2Box(self, x, y, w, h, prefix = prefix)
        # trigger prefix if any
        if len(prefix) > 0:
            nbox.write('')
        self.boxes.append(nbox)
        return nbox

'''
    If using curses it wraps the code path so the terminal
    can be restored when program exits. If not using curses
    it either does an alternative initialization or nothing.
'''
def wrapper(f, *args):
    win = None
    if hasCurses:
        # initial screen
        win = curses.initscr()
        # turn on cbreak
        curses.cbreak()
        # turn off echo
        curses.noecho()
        # turn on terminal keypad
        win.keypad(1)
        # initialize colors
        try:
            curses.start_color()
        except:
            pass

    ct = CrossTerm2(win)
    if True or not hasCurses:
        #
        #            WINDOWS ONLY
        #
        # to keep the programming from accidentally
        # messing the window up by print something
        # to the screen we will direct all output
        # from print statements to a file; curses on
        # linux can handle print statements and do
        # not effect the buffer but we have no good 
        # way to do it on windows platform unless 
        # we created a brand new console window just
        # for our output
        stdout = open('.stdout', 'w')
        ct.stdout = sys.stdout         # save it
        sys.stdout = stdout            # protect it
        ct.stderr = sys.stderr
        sys.stderr = stdout

    try:
        f(ct, *args)
    finally:
        if hasCurses:
            # restore cooked mode
            curses.nocbreak()
            # turns on echo
            curses.echo()
            # disales terminal keypad
            win.keypad(0)
            # restore terminal mode
            curses.endwin()
        ct.stdout.close()
        sys.stdout = ct.stdout
        sys.stderr = ct.stderr
'''
    My testing function.
'''
def main(xc):
    #print('\033[%sA' % y)   # move cursor up
    #print('\033[%sD' % x)   # move cursor left
    #print('\033[%s;%sH%s' % (y + 1, x + 1, s))   # set cursor position
    #writeStringAtPosition(0, 0, 'a world')
    #writeStringAtPosition(0, 1, 'b apple')
    #writeStringAtPosition(0, 2, 'c grape')
    #print('\033[6n')
    #win = curses.initscr()

    xc.clear()

    for a in range(0, 15):
        xc.writeStringAt(10, 2 + a, 'HELLO WORLD', 253)
    #xc.writeStringAt(10, 10, 'HELLO WORLD')
    xc.update()

    while True:
        pass

if __name__ == '__main__':
    wrapper(main)
6/30/2014Demonstration Of Different I/O Modes On Sockets Using Python
See https://github.com/kmcguire3413/Py3SocketsIODemo
6/30/2014Demonstation In Go Of Sync, Async, And Buffering Communication
/*
	Leonard Kevin McGuire Jr (kmcg3413@gmail.com)

	This demonstration shows two very important concepts. 

	(1) It shows the difference in a synchronous request and reply model between
	    two contexts of execution to an asynchronous with latency as a factor. By
	    showing how using an asynchronous model can maximize the communication link
	    throughput utilization.

	(2) It shows the dead lock problem if you blindly shovel data in an asynchrnous
	    model, and also shows the correct way to handle an asynchronous model. It
	    does this by simulation an IPConn object using channels.
*/
package main

import			"fmt"
import			"time"
import rand		"math/rand"

type WorkItem struct {
	stime		time.Time
	work		byte
}

func newWorkItem(work byte) (wi *WorkItem) {
	wi = new(WorkItem)
	wi.work = work
	wi.stime = time.Now()
	return
}

func shovelEntry(in chan *WorkItem, out chan *WorkItem) {
	for {
		// read work item
		wi := <- in
		// wait until its time to send it
		delta := 500000000 - (time.Now().Sub(wi.stime))
		// put 2 seconds delay at minimum 
		if delta > 0 {
			time.Sleep(delta)
		}
		// send work item
		out <- wi
	}
}

// you should notice the important part here is there is
// very little delay in processing making this CPU very
// fast
func serverEntry(in chan *WorkItem, out chan *WorkItem) {
	for {
		// get the work
		wi := <- in
		// do some work
		wi.work = wi.work + 1
		// send the work back
		out <- wi

	}
}

// you should notice a very low throughput which means lower
// link utilization in this demonstration (synchronous)
func clientEntrySync(in chan *WorkItem, out chan *WorkItem) {
	for x := 0; x < 10; {
		// produce some work
		wi := newWorkItem(byte(x))
		x = x + 1
		// send the work
		out <- wi
		// get a reply
		wi = <- in
		// print result
		fmt.Printf("[sync-demo] in:%d\n", wi.work)
	}
}

// you should notice much more throughput which means higher
// link utilization in this demonstration (asynchronous)
func clientEntryAsync(in chan *WorkItem, out chan *WorkItem) {
	var wi		*WorkItem

	for x := 0; x < 100; {
		// create work item
		if wi == nil {
			wi = newWorkItem(byte(x))
			x++
		}

		// determine if we can send a work item
		select {
			case out <- wi:
				wi = nil
			case _wi := <- in:
				fmt.Printf("[async-demo] in:%d\n", _wi.work)
		}
	}
}

// this simulates using an output that has no way of determining
// if it might block on write or read so we have to create two
// other goroutines that are helpers
// 
// ** to simulate this we simply disallow the usage of the select 
//    on the `in` and `out` channels because they represent for 
//     example a net.Conn's Read and Write methods
//
// ** we can do select on our `helperin` and `helperout` becase
//    they represent a true channel which is what we use to work
//    around the potential to block
//
// ** we generate a variable number of work items but we can pretend
//    that they are a single work packet of variable size
//
// ** the maxbuf represents the maximum memory in our machine as a
//    outgoing and incoming application level buffer; OR they represent
//	  a static hard buffer size (instead of being able to expand)
//
// what will happen is we will get stuck trying to send something but
// that will fail because the server's incoming buffer is full and our
// incoming buffer is full causing the server to do an infinite block
// and we are in an infinite block too because we can not read
//
// ** the solution is for us to implement some type of throttling
//    to prevent exhausting all of our memory in the machine represented 
//    by the `helperin` and `helperout` and `maxbuf`
func __helperout(in chan *WorkItem, out chan *WorkItem) {
	// goroutine for writing since IPConn supports concurrent access
	for {
		out <- <- in
	}
}

func __helperin(in chan *WorkItem, out chan *WorkItem) {
	// goroutine for reading since IPConn supports concurrent access
	for {
		in <- <- out
	}
}
func clientEntryAsyncBlocking(in chan *WorkItem, out chan *WorkItem, limit bool) {
	//
	// ** remember we cant select on `in` or `out` because we are
	//    pretending that they do not support that feature as they
	//    are like an IPConn object
	//
	var wi			*WorkItem

	maxbuf := 10
	helperin := make(chan *WorkItem, maxbuf)
	helperout := make(chan *WorkItem, maxbuf)

	go __helperout(helperin, out)
	go __helperin(helperout, in)

	var grp		[]*WorkItem
	var sz		int
	var dosend	bool
	var cycles	int

	if limit {
		cycles = 500
	} else {
		cycles = 1000000
	}

	for x := 0; x < cycles; {
		if grp == nil {
			// to demonstrate we build random length number
			// of work items that must be sent at once 
			sz = rand.Intn(3)
			grp = make([]*WorkItem, sz)
			for y := 0; y < sz; y++ {
				wi := newWorkItem(byte(x))
				grp[y] = wi
			}
			x++
		}

		// this is where we check that our buffer being the
		// `helperin` channel has room and if not we do not
		// produce anymore work but instead wait for it to
		// have room
		if limit {
			if sz > (cap(helperin) - len(helperin)) {
				// do not send anything
				if dosend {
					// we do not send.. this is where we can dead lock
					// at if we go ahead and try to send even though the
					// buffer can not hold all of it
					fmt.Printf("waiting because buffer is too full\n")
				}
				dosend = false
			} else {
				dosend = true
			}
		} else {
			dosend = true
		}

		if dosend {
			// send group
			for y := 0; y < sz; y++ {
				// `helperin` represents our maximum memory in the machine
				//  as a application level buffer.. the internal network
				//  stack buffer for our pretend IPConn is represented by
				//  `maxbuf` in the `main` function
				//
				//  eventually we are going to get stuck here trying to send
				//  and we unable to because the server's input buffer is full
				//  and our input buffer is full but we cant read from it because
				//  we are stuck blocked here
				helperin <- grp[y]
			}
			grp = nil
		}

		// this allows us to determine if we are able to send or recv but
		// we do not keep in check the helperin avalible capacity so we
		// eventually overun it and get stuck
		select {
			case wi = <- helperout:
				fmt.Printf("[async-nolimit-demo] in:%d\n", wi.work)
			default:
		}
		////////
	}
}

func main() {
	maxbuf := 10
	clientout := make(chan *WorkItem, maxbuf)
	clientin := make(chan *WorkItem, maxbuf)
	serverout := make(chan *WorkItem, maxbuf)
	serverin := make(chan *WorkItem, maxbuf)

	// create two goroutines to handle shoveling data between
	go shovelEntry(clientout, serverin)
	go shovelEntry(serverout, clientin)

	// create server goroutine
	go serverEntry(serverin, serverout)

	// demonstration using channels
	clientEntrySync(clientin, clientout)
	clientEntryAsync(clientin, clientout)

	// demonstration about proper usage of buffers by simulaton of IPConn
	clientEntryAsyncBlocking(clientin, clientout, true)
	// demonstration about incorrect usage of buffers by simulation of IPConn 
	clientEntryAsyncBlocking(clientin, clientout, false)
}
6/11/2014ASN.1 Data Python Reading Example

If you are like me you have used a drag net across the internet looking for a simple understandable example of reading data in the ASN.1 format. You have likely seen and tried to read the overly complex technical specifications only to wonder why someone has to make something so complex.. I do not know the answer. The following will read basic ASN.1 data. It tries to error out when it gets to something more complex than it is designed to read such as indefinite length data and data that does not use 7-bit or 16-bit length fields. Such as an 8-bit (if possible) or larger than 16-bit. I used the following resources. I wrote this a while back and had to revisit it because I ran into a problem. I found out my code is working correctly, but here are the resources I found this recent time when searching that helped.

http://luca.ntop.org/Teaching/Appunti/asn1.html
http://en.wikipedia.org/wiki/Abstract_Syntax_Notation_One

	def readASN1Data(data):
		fields = []
		
		data = data[4:]
		ndx = 0
		
		while len(data) > 0:
			type = data[0]
			data = data[1:]
			
			#print('type:%s' % type)
			
			if type & 0x40 == 0x40:
				raise Exception('ASN.1 Entry Used Indefinite Length')
			
			# read the first length
			sz = data[0]
			data = data[1:]
			
			#print('sz:%s' % sz)
			
			# if bit 7 is set then we use more bytes for the length
			if sz & 0x80 == 0x80:
				# get the length of the length field
				c = sz & 0x7F
				# make sure we are not in over our head and
				# if so then let someone know that we are
				if c != 2:
					raise Exception('ASN.1 Entry Used Length File Not 2 Bytes')
				# read the length of the data
				sz = data[0] << 8 | data[1]
				#print('   2sz:%s' % sz)
				# remove the length
				data = data[2:]
			
			# create field
			field = (type, data[0:sz])
			# drop used data
			data = data[sz:]
			
			# add field
			fields.append(field) 
			fields[ndx] = field
			ndx = ndx + 1
		
		return fields
	
5/29/2014Python RSA Public Private Key Encryption SSH using ssh-keyen

This will read a public key file and a non-encrypted private key file generated by ssh-keygen and encrypt and decrypt some data. Also, of use is two functions which convert from base 256 to integer. The toi256 converts from little-endian format, and the toi256r converts from big-endian.

'''
	ssh-keygen -t rsa -b 4096
	ssh-keygen -t rsa -b 8192
'''
import random
import math
import base64
import struct

def __gen_prime(N=10**8, bases=range(2,20000)):
    p = 1
    while any(pow(base, p-1, p) != 1 for base in bases):
        p = random.SystemRandom().randrange(N)
    return p

def __multinv(modulus, value):
    '''Multiplicative inverse in a given modulus

        >>> multinv(191, 138)
        18
        >>> 18 * 138 % 191
        1
		http://en.wikipedia.org/wiki/Extended_Euclidean_algorithm
    '''
    x, lastx = 0, 1
    a, b = modulus, value
    while b:
        a, q, b = b, a // b, a % b
        x, lastx = lastx - q * x, x
    result = (1 - lastx * modulus) // value
    return result + modulus if result < 0 else result

def keygen(N):
    '''Generate public and private keys from primes up to N.

        >>> pubkey, privkey = keygen(2**64)
        >>> msg = 123456789012345
        >>> coded = pow(msg, 65537, pubkey)
        >>> plain = pow(coded, privkey, pubkey)
        >>> assert msg == plain
		http://en.wikipedia.org/wiki/RSA
    '''
    prime1 = __gen_prime(N)
    prime2 = __gen_prime(N)
    totient = (prime1 - 1) * (prime2 - 1)
    return prime1 * prime2, __multinv(totient, 65537)

'''
	This function expects bytes not str.
'''
def toi256(data):
	t = 0
	n = 1
	for b in data:
		b = b
		t = t + (b * n)
		n = n * 256
	return t
	
def toi256r(data):
	t = 0
	n = 1
	i = len(data) - 1
	while i > -1:
		b = data[i]
		t = t + (b * n)
		n = n * 256
		i = i - 1
	return t

def fromi256(i):
	o = []
	m = 1
	while m < i:
		m = m * 256
	if m > i:
		m = divmod(m, 256)[0]
	while i > 0:
		r = divmod(i, m)[0]
		o.insert(0, r)
		i = i - (r * m)
		m = m >> 8
	return bytes(o)
	
def crypt(data, key):
	exp = toi256(key[0])
	pubkey = toi256(key[1])
	
	data = toi256(data)
	
	# value, exponent, modulus
	
	data = pow(data, exp, pubkey)
	return fromi256(data)
	
def decrypt(data, key):
	prikey = toi256(key[0])
	pubkey = toi256(key[1])
	
	data = toi256(data)
	data = pow(data, prikey, pubkey)
	return fromi256(data)
	
def readKeyFile(path):
	fd = open(path, 'r')
	lines = fd.readlines()
	fd.close()
	
	out = []
	for line in lines:
		line = line.strip()
		if line.find(':') < 0 and line.find('-') < 0:
			out.append(line)
	
	out = ''.join(out)
	
	return base64.b64decode(bytes(out, 'utf8'))

def readSSHPublicKey(path):
	'''
		do not ask me.. had lots of trouble digging through openssh
		source.. building it.. producing different results... LOL..
			i just gave up and hacked this together
	'''
	fd = open(path, 'rb')
	data = fd.read()
	fd.close()
	data = data.split(b' ')
	data = data[1]
	
	data = base64.b64decode(data)
	
	sz = struct.unpack_from('>I', data)[0]
	data = data[4:]
	type = data[0:sz]
	data = data[sz:]
	
	sz = struct.unpack_from('>I', data)[0]
	data = data[4:]
	exp = data[0:sz]
	data = data[sz:]
	
	sz = struct.unpack_from('>I', data)[0]
	data = data[4:]
	mod = data[0:sz]
	
	return (exp, mod)
	
def readSSHPrivateKey(path):
	data = readKeyFile(path)
	
	fields = []
	
	data = data[4:]
	ndx = 0
	
	while len(data) > 0:
		type = data[0]
		data = data[1:]
		
		sz = data[0]
		data = data[1:]
		
		if sz == 0x82:
			sz = data[0] << 8 | data[1]
			data = data[2:]
		
		# create field
		field = (type, data[0:sz])
		# drop used data
		data = data[sz:]
		
		# add field
		fields.append(field) 
		fields[ndx] = field
		ndx = ndx + 1
		
	return (fields[3][1], fields[1][1])

	pub = pubcrypt.readSSHPublicKey('id_rsa.pub')
	# this contains the public key and private key
	pri = pubcrypt.readSSHPrivateKey('id_rsa')
	
	# pub[0] == exponent
	# pub[1] == public key
	# pri[0] == public key
	# pri[1] == private key
	
	'''
		Well, this is a big oops. You see I started converting between
		Python large integers and byte form with a little endian format, 
		but SSH keys are stored using a big endian. So here I am just
		converting from big-endian to little-endian.
		
		Now, you may ask WHY?? Well, I *finally* got the code working and
		I am tired of messing with it. So I am leaving it like this and
		hopefully one day I will go back in and fix this by making all
		my functions work with big endian...
		
		Anyway.. for gods sake it finally works!!! 
	'''
	keypub = (pubcrypt.fromi256(pubcrypt.toi256r(pub[0])), pubcrypt.fromi256(pubcrypt.toi256r(pub[1])))
	keypri = (pubcrypt.fromi256(pubcrypt.toi256r(pri[0])), pubcrypt.fromi256(pubcrypt.toi256r(pri[1])))

	data = pubcrypt.crypt(data, keypub)
	data = pubcrypt.decrypt(data, keypri)
	
5/25/2014Blocky To Go Live As Beta Soon

The server IP address is kmcg3413.net and the port is 1874

You can get the client and server code at https://github.com/kmcguire3413/blocky. And, also find more information about Blocky

5/21/2014Python Public/Private Key Generation And Usage
Some of it was copied from various places.
	import random
	import math

	def __gen_prime(N=10**8, bases=range(2,20000)):
		p = 1
		while any(pow(base, p-1, p) != 1 for base in bases):
			p = random.SystemRandom().randrange(N)
		return p

	def __multinv(modulus, value):
		'''Multiplicative inverse in a given modulus

			>>> multinv(191, 138)
			18
			>>> 18 * 138 % 191
			1

		'''
		''' http://en.wikipedia.org/wiki/Extended_Euclidean_algorithm '''
		x, lastx = 0, 1
		a, b = modulus, value
		while b:
			a, q, b = b, a // b, a % b
			x, lastx = lastx - q * x, x
		result = (1 - lastx * modulus) // value
		return result + modulus if result < 0 else result

	def keygen(N):
		'''Generate public and private keys from primes up to N.

			>>> pubkey, privkey = keygen(2**64)
			>>> msg = 123456789012345
			>>> coded = pow(msg, 65537, pubkey)
			>>> plain = pow(coded, privkey, pubkey)
			>>> assert msg == plain

		'''
		''' http://en.wikipedia.org/wiki/RSA '''
		prime1 = __gen_prime(N)
		prime2 = __gen_prime(N)
		totient = (prime1 - 1) * (prime2 - 1)
		return prime1 * prime2, __multinv(totient, 65537)

	def toi256(data):
		t = 0
		n = 1
		for b in data:
			b = ord(b)
			t = t + (b * n)
			n = n * 256
		return t

	def fromi256(i):
		o = []
		m = 1
		while m < i:
			m = m * 256
		if m > i:
			m = divmod(m, 256)[0]
		while i > 0:
			r = divmod(i, m)[0]
			o.insert(0, chr(r))
			i = i - (r * m)
			m = m >> 8
		return ''.join(o)
		
	def crypt(data, pubkey):
		data =toi256(data)
		data = pow(data, 65537, pubkey)
		return fromi256(data)
		
	def decrypt(data, prikey, pubkey):
		data = toi256(data)
		data = pow(data, prikey, pubkey)
		return fromi256(data)
		
	'''
	msg = 'hello'

	pubkey, prikey = keygen(2**64)
	print('pubkey:%s' % pubkey)
	print('prikey:%s' % prikey)

	coded = crypt(msg, pubkey)
	plain = decrypt(coded, prikey, pubkey)
	print(msg)
	print(plain)
	assert(msg == plain)
	exit()
	'''
	
5/21/2014Operating System Project

This is my operating system project called ThinARM which is a micro-processor architecture with an A-SMP style. At the moment tasks, memory management, system calls, address spaces, and inter-process communication are working. I was last working out the userspace libraries, services, and about to start working on userspace drivers/services/servers.

		git clone http://kmcg3413.net/armthin.git/
	
5/21/2014Inventory Tracking

This is a very simple and limited inventory tracking system written with javascript and Python.

		git clone http://kmcg3413.net/itrack.git/
		
		You need to create a file called 'users' in the directory with the following format:
		
		username=password=account=email
		
		For example:
		
		john:be982:store:john32@gmail.com
		mark:m4K3j2:store:mark@gmail.com
		suem:mypass:office1:suem@office.com
		
		To enable the mail feature you need to create a file called 'mailserver' in the directory with the format:
		
		smtp-server:smtp-port:username:password
		
		For example:
		
		smtp.gmail.com=465=kmcg3413@gmail.com=hofyyoqejejnjptv
	

For a demonstration goto kmcg3413.net/itrack and login with demo as the username and password.

It only supports one account per username. So if one person needed access to multiple accounts then they would need multiple usernames. You could improve the code by allowing a comma delimited list for account and have them choosen which one after login. The email is used when stock falls below a limit and will generate an email.

5/19/2013Silicon Diode As A Switch

Using [http://www.sm0vpo.com/data/diode_switching_01.htm] as a reference I was able to recreate the circuit in spice. Here the

Using a silicon diode as a switch. [diode switch schematic]

5/19/2013Rough And Dirty IF Mixer

Here depicted is a FFT on the output of the circuit where a local oscillator frequency of 10khz is mixed with the signal at a frequency of 10khz which produces a 20khz signal.

6/08/2013Mason File Synchronization (Linux/Windows)

This is my project to produce a usable professional grade file synchronization tool that is platform independant (requirement of an JRE (Java Runtime Environment)). So as you can guess it is being written in Java.

You can checkout the repository at http://wk1.kmcg3413.net/mason.repo.

Also a preliminary README.

I would like to also include a GUI, but I am thinking of making that optional therefore you can use just the command line version or if you wish a GUI could be used as a frontend.

5/19/2013Inductor Filtering

Here is a depiction of inductors have varying impedance on an signal of 100khz. The graph is of the current flow through each inductor. As you should see increasing the inductance causes an increase in the impedance (resistance) of the signal. The lowest inductance allows more electrons to flow through and thus more current than the higher inductance coils.

5/26/2013Python Raw Packet

Been working on some a project and needed to craft raw packets in Python: [rawpkt.py].

As an example to generate a simple limited functionality DNS query. The source MAC address and your gateway or target ETH device has to be manually keyed although you could easily grab that from somewhere.

			data = craftDNSQuery(
				srcmac = [0xec, 0x55, 0xf9, 0x7a, 0x54, 0x70], 
				dstmac = [0xa0, 0x21, 0xb7, 0xb2, 0x28, 0xe9], 
				srcaddr = craftIP4Address(192, 168, 1, 114), 
				dstaddr = craftIP4Address(8, 8, 8, 8),
				srcport = 400, dstport = 53, tranid = 0x1234
			)
		

6/2/2013Python IP/TCP Checksum Calculation
	def negatechksum(v):
		mask = (1 << v.bit_lenth()) - 1
		return v ^ mask
	

Break the data you wish to checksum into 16-bit words using big-endian. With big-endian you need to use (data[index] << 8 | data[index + 1]). If you have an odd number of bytes you need to simulate the last byte as 0x00. Now, before you negate you need to add the upper 16-bit to the lower 16-bits like (sum >> 16 + sum) then negate using negatechksum(sum) then store the value into the checksum field using big-endian pkt[0] = s & 0xff and pkt[1] = (s >> 8) & 0xff.

The IP and TCP checksum differ because the TCP checksum has a temporary header called a pesudo header attached to the head of the byte stream. The checsum is then computed over the pesudo header, header, and data yet when the packet is sent only the header and data are transmitted. The pesudo header is dropped. (See the Python source code to have a working example.)

Operating System Development
I have contributed a lot of time to this site. You can get into operating system development here using many languages and platforms. [www.osdev.org] I am known as Pancakes and kmcguire.
2008OpenOCD AUDC702X Flash Driver/Module

The source code for the AUDC702X with OpenOCD. [http://openocd.sourceforge.net/doc/doxygen/html/aduc702x_8c_source.html]

Dwarf Fortress Adventures

My adventures while playing Dwarf Fortress. You can find Dwarf Fortress at [http://www.bay12games.com/dwarves/]. My stuff is located at [DF2Story].

1/30/2014EXAMPLE OF RSA ENCRYPTION/DECRYPTION USING PRE-GENERATED PRIVATE PUBLIC OPENSSH KEY FILES

Hurray! After two weeks I finally got RSA to work. C=M^E%N and M=C^D%N was correct. It took hacking together an improper ASN.1 reader for the private key in OpenSSH format which actually had me stumped until I figured out it was in ASN.1 format, and of course the public key format was much more simple thankfully. But, I encrypted "Hello World" and decrypted it using a 4096-bit key successfully. Code Here

6/2/2013OpenVZ/Parallels SLL (VENET?) Interface SOCK_RAW AF_PACKET
After quite a lot of flustraition dealing with this special network interface I have finally discovered how to open it as a raw socket and craft custom packets. The problem is firstly there is no ethernet frame header instead there is a SLL frame header (linux cooked). Now, inside this header (which you can see by using tcpdump -w or wireshark) is that it has a protocol field. To set this to the correct protocol such as IP you need to create a socket using the third argument such as (AF_PACKET, SOCK_RAW, 0x8) for IP. This will correctly set the protocol field and stop you from having unknown packets when viewing the output using wireshark or tcpdump. In python:
	sock = socket.socket(socket.AF_PACKET, socket.SOCK_RAW, 0x8)
	sock.bind(('venet0', 0))
	
Now, you can craft the raw IP header and send it.
2/15/2014RSA SSHD Key Generation - Default Size 768-Bit
http://www.hermann-uwe.de/blog/creating-32768-bit-rsa-keys-for-fun-and-profit
http://www.slashroot.in/secure-shell-how-does-ssh-work
I think it is likely a very good idea to bump up your RSA key length from 768-bit to at least 4096-bit considering the advances in cracking RSA as of late. I am currently using a 8192-bit key just to be safe. Also keep in mind DSA is limited to 1024-bit. AFAIK, it is used with legacy things, but this is something that should be throughly investigated. I just did not generate any DSA keys which should disable it.
3/30/2014OSDEV.ORG PAGES AND ARTICLES
One of my largest contributions is, Simple Heap Implementation. This details some heap implementations using various major structures for management of memory both large and small.
Arm Overview - Lot of my work on improving this page.
Initializing Display On ARM Integrator-CP - Getting a display adapter initialized.
IRQ, Timer, And PIC On ARM Integrator-CP - Series of pages on getting the basics of working with ARM and the Integrator-CP.
5/4/2014Parse Lighttpd Log With Python
I was working and needed a quick way to parse the Lighttpd log without using regular expressions.
	MONTH_TO_NUM = {
		'Jan':	1,
		'Feb': 	2,
		'Mar':	3,
		'Apr':	4,
		'May':	5,
		'Jun':	6,
		'Jul':	7,
		'Aug':	8,
		'Sep':	9,
		'Oct':	10,
		'Nov':	11,
		'Dec':	12
	}
			
	def parsedate(datestr):
		global MONTH_TO_NUM

		ps = datestr.split('/')
		day = int(ps[0])
		month = MONTH_TO_NUM[ps[1]]
		ps = ps[2]
		ps = ps.split(':')
		year = int(ps[0])
		hour = int(ps[1])
		minute = int(ps[2])
		second = int(ps[3].split(' ')[0])
		return [year, month, day, hour, minute, second]
	def parseLine(line):
		parts = []
		while len(line) > 0:
			if line.find(' ') < 0:
				part = line
				line = ''
			else:
				if line[0] == '[':
					part = line[1:line.find(']')]
					line = line[line.find(']') + 2:]
				elif line[0] == '"':
					part = line[1:line.find('"', 1)]
					line = line[line.find('"', 1) + 2:]
				else:
					part = line[0:line.find(' ')]
					line = line[line.find(' ') + 1:]
				
			parts.append(part)
		
		clientip = parts[0]
		dns = parts[1]
		ident = parts[2]
		date = parsedate(parts[3])
		get = parts[4]
		status = parts[5]
		length = parts[6]
		ref = parts[7]
		agent = parts[8]
		return parts
	
Yeah, its dirty and not very efficent, but it works and its still very fast. Just figured someone might be looking for a quick and dirty way to get the job done and so here it is

This site was generated with Python and written by kmcg3413@gmail.com.