#!/usr/bin/python

# genkey.py - Generate fake RHEL 5 installation numbers
# Copyright (c) 2007 Jack Neely
# Authors: Jack Neely <jjneely@gmail.com>
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.

import hmac
import sha

# 24 bits
key = 0x0

# The following class taken from ASPN:
# http://aspn.activestate.com/ASPN/Cookbook/Python/Recipe/113799

class BitField(object):

    def __init__(self,value=0):
        self._d = value

    def __getitem__(self, index):
        return (self._d >> index) & 1 

    def __setitem__(self,index,value):
        value    = (value&1L)<<index
        mask     = (1L)<<index
        self._d  = (self._d & ~mask) | value

    def __getslice__(self, start, end):
        mask = 2L**(end - start) -1
        return (self._d >> start) & mask

    def __setslice__(self, start, end, value):
        mask = 2L**(end - start) -1
        value = (value & mask) << start
        mask = mask << start
        self._d = (self._d & ~mask) | value
        return (self._d >> start) & mask

    def __int__(self):
        return self._d

def checksum(regkey):

    keystr = "%06x" % regkey[40:64]
    payloadstr = "%08x" % regkey[0:32]

    hash = hmac.new(keystr, payloadstr, sha)
    sum = hash.hexdigest()[:2]

    return int(sum, 16)

def generateKey(key, options, sockets, virtlimit, type, product):
    """Create an installation number based from the given codes.
       All parameters are int."""

    # Okay we are using python slices here so 0:3 represents bits 0, 1, and 2
    # and does not include/modify bit 3

    regkey = BitField()
    
    # Make the payload
    regkey[18:32] = options
    regkey[14:18] = sockets
    regkey[11:14] = virtlimit
    regkey[9:11]  = type
    regkey[0:9]   = product

    # Tack on the key
    regkey[40:64] = key

    # calculate checksum
    regkey[32:40] = checksum(regkey)

    return "%016x" % int(regkey)

def main():
    print "a Red Hat global desktop key"
    print generateKey(key, 0x1, 0xf, 0xf, 0x2, 0x2)
    print
    print "a client key"
    print generateKey(key, 0x5, 0xf, 0xf, 0x2, 0x1)
    print
    print "a server key"
    print generateKey(key, 0x1, 0xf, 0xf, 0x2, 0x0)
    print
    print "A server key with Cluster"
    print generateKey(key, 0x2, 0xf, 0xf, 0x2, 0x0)
    print
    print "A server key with ClusterStorage"
    print generateKey(key, 0x3, 0xf, 0xf, 0x2, 0x0)
    print
    print "server with HPC"
    print generateKey(key, 0x4, 0xf, 0xf, 0x2, 0x0)
    print
    print "server with Directory"
    print generateKey(key, 0x5, 0xf, 0xf, 0x2, 0x0)
    print
    print "server with SMB"
    print generateKey(key, 0x6, 0xf, 0xf, 0x2, 0x0)


if __name__ == "__main__":
    main()

