Python and prngd

Stuart D. Gathman stuart at bmsi.com
Sat Nov 9 00:32:33 EST 2002


I am running Python-2.2.2 on AIX.  It is wonderful!  I am also running
the PRNGD (Portable Random Number Generator Daemon) since AIX has no
kernel entropy source.  PRNGD is compatible with EGD - with both, you
can't simply read a socket.  You send commands to the socket and get
responses.

I did a quick search on the web, and didn't find python code to do this.
So, I reinvented the wheel.  It took less than an hour to go over the
prngd source and make a client.  Here is the result for those who may
care.

How should a small, but non trivial piece of code such as this be shared
so that others need not repeat the effort?

import socket
from struct import unpack,pack

class PRNG:
  "Provide access to the Portable Random Number Generator Daemon"

  def __init__(self,sockname="/var/run/egd-pool"):
    self.randfile = socket.socket(socket.AF_UNIX,socket.SOCK_STREAM)
    self.randfile.connect(sockname)

  def _readall(self,n):
    s = self.randfile.recv(n)
    while len(s) < n:
      s = s + self.randfile.recv(n - len(s))
    return s

  def get(self):
    "Return number of available bytes of entropy."
    self.randfile.sendall('\x00')
    return unpack(">i",self._readall(4))[0]

  def read(self,cnt):
    "Return available entropy, up to cnt bytes."
    if cnt > 255: cnt = 255
    self.randfile.sendall(pack("BB",0x01,cnt))
    buf = self._readall(1)
    assert len(buf) == 1
    count = unpack("B",buf)[0]
    buf = self._readall(count)
    assert len(buf) == count, "didn't get all the entropy"
    return buf

  def readall(self,cnt):
    "Return all entropy bytes requested"
    if cnt < 256:
      self.randfile.sendall(pack("BB",0x02,cnt))
      return self._readall(cnt)
    buf = readall(self,255)
    cnt -= len(buf)
    while cnt > 255:
      buf += readall(self,255)
      cnt -= len(buf)
    return buf + readall(self,cnt)

  def getpid(self):
    "Return the process id string of the prngd"
    self.randfile.sendall('\x04')
    buf = self._readall(1)
    assert len(buf) == 1
    count = unpack("B",buf)[0]
    buf = self._readall(count)
    assert len(buf) == count, "didn't get whole PID string"
    return buf

Other comments on the code are welcome.

-- 
	      Stuart D. Gathman <stuart at bmsi.com>
Business Management Systems Inc.  Phone: 703 591-0911 Fax: 703 591-6154
"Confutatis maledictis, flamis acribus addictis" - background song for
a Microsoft sponsored "Where do you want to go from here?" commercial.



More information about the Python-list mailing list