I saw a request for Koji to use a stronger cryptographic hash function such as 
SHA256 
( https://fedorahosted.org/koji/ticket/119 ) on RPM packages. I took some time 
in reading how the 
RPMTAG_SIGMD5 is calculated and implemented some Python code to hash the same 
RPM data 
using hashlib's SHA256 module. The outputted SHA256 digest can be stored in 
Koji's DB and 
also retrieved/calculated/checked with any new packages that are being 
submitted. 


$ rpm -q --queryformat '%{RPMTAG_SIGMD5}' -p "gcc-4.6.2-1.fc17.1.src.rpm"
c88e96685e7eb3a124a5707b1bc41333
$ python sha2pay.py gcc-4.6.2-1.fc17.1.src.rpm
['c88e96685e7eb3a124a5707b1bc41333', 
'c729d818d5468f8b1147cb70b266992f92f58c9dace218417c7582427d1e5561']


Source code:



import hashlib
import os
import struct
import subprocess
import sys


def sha2pay(fn):
        # http://www.iagora.com/~espel/rpm2cpio
        
        nel = 0
        f = open(fn, "r")
        
        rpm = f.read(96)
        if (len(rpm) != 96):
                #print("error reading lead 96.0")
                return None
        nel += len(rpm)
        
        # http://perldoc.perl.org/functions/pack.html
        # http://docs.python.org/library/struct.html
        
        (magic, major, minor, rest) = struct.unpack(">LBB90s", rpm)
        
        if (magic != 0xedabeedb):
                #print("incorrect lead magic")
                return None
        
        if ((major != 3) and (major != 4)):
                #print("incorrect lead major")
                return None
        
        # http://docs.python.org/library/stdtypes.html
        
        while (1):
                pos = nel
                rpm = f.read(16)
                if (len(rpm) != 16):
                        #print("error reading header 16.0")
                        return None
                nel += len(rpm)
                (smagic, rest) = struct.unpack(">H14s", rpm)
                if ((smagic == 0x1f8b) or (smagic == 0x425a)):
                        break
                if (pos & 0x7):
                        pos += 7
                        pos &= (~0x7)
                        f.seek(pos, 0)
                        nel = pos
                        rpm = f.read(16)
                        if (len(rpm) != 16):
                                #print("error reading header 16.1")
                                return None
                        nel += len(rpm)
                left = (len(rpm) - 16)
                (magic, data, sections, bytes, rest) = struct.unpack(">4L" + 
str(left) + "s", rpm)
                if (magic != 0x8eade801):
                        #print("incorrect header magic")
                        return None
                # beg custom
                f.seek(pos + 16, 0)
                tmp = f.read((16 * sections) + bytes)
                head = (rpm + tmp)
                # end custom
                pos += 16
                pos += (16 * sections)
                pos += bytes
                f.seek(pos, 0)
                nel = pos
        
        if ((smagic != 0x1f8b) and (smagic != 0x425a)):
                #print("unknown compression format")
                return None
        
        while (1):
                tmp = f.read(16384)
                
                if (not tmp):
                        break
                
                rpm += tmp
        
        f.close()
        return [hashlib.md5(head + rpm).hexdigest(), hashlib.sha256(head + 
rpm).hexdigest()]


--
buildsys mailing list
buildsys@lists.fedoraproject.org
https://admin.fedoraproject.org/mailman/listinfo/buildsys

Reply via email to