On 23/02/17 13:36, Gerd v. Egidy wrote:
> So I think that this would move the bar for a possible user of paperbackup.py 
> higher than I want to.

Yes, it should be easy to use. In fact, I've sometimes heard the 
complaint that "paperkey is not easy to install and/or use". That's 
really too bad that those people feel that way.

> Ideally it is a tool or combination of tools already deployed widely, like 
> sed 
> and sort I used in paperrestore. This would make the checksums still usable 
> even when the source to paperbackup.py isn't available anymore.

It took me some fiddling... but using CRC RevEng[1] I got a checksum in 
Python that is compatible to POSIX cksum.

The following Python:

>>> from posixcksum import PosixCkSum
>>> from base64 import b64encode
>>> crc, _ = PosixCkSum.sum_whole(bytearray(b'123456789'))
>>> b64encode(crc.to_bytes(4,byteorder='big'))[:4]
b'N3pg'

generates the same checksums as the following Bash code:

$ printf $(printf '%08x' $(echo -n 123456789 | cksum | cut -d' ' -f1) | sed 
's/../\\x\0/g')|base64|cut -b-4
N3pg

This is done with the attached Python code. It is written for 
compactness rather than speed. Just re-implementing the crc function 
would probably be quicker.

HTH,

Peter.

[1] <http://reveng.sourceforge.net/>
-- 
I use the GNU Privacy Guard (GnuPG) in combination with Enigmail.
You can send me encrypted mail if you want some privacy.
My key is available at <http://digitalbrains.com/2012/openpgp-key-peter>
#!/usr/bin/python3

# Copyright (c) 2017 Peter Lebbing <pe...@digitalbrains.com>
# All rights reserved.
#
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions are met:
#
# 1. Redistributions of source code must retain the above copyright notice,
# this list of conditions and the following disclaimer.
#
# 2. Redistributions in binary form must reproduce the above copyright notice,
# this list of conditions and the following disclaimer in the documentation
# and/or other materials provided with the distribution.
#
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
# ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
# LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
# POSSIBILITY OF SUCH DAMAGE.

import binascii

class PosixCkSum(object):


    """Create a POSIX cksum-compliant checksum."""


    def __init__(self):
        """Create new checksumming instance."""
        self.n = 0
        self.crc = 0xffffffff

    def sum(self, bs):
        """Checksum another part of data.

        IMPORTANT: the data in bs is DESTROYED.

        """
        self.bit_reverse(bs)
        self.crc = binascii.crc32(bs, self.crc)
        self.n += len(bs)

    def finish(self):
        """Finish checksum computation and return result.

        After this, the object should no longer be used.

        """
        if not self.n:
            return self.crc, self.n
        bs = bytearray(self.n.to_bytes((self.n.bit_length() + 7) // 8,
                                       byteorder='little'))
        self.bit_reverse(bs)
        self.crc = binascii.crc32(bs, self.crc)
        crcb = bytearray(self.crc.to_bytes(4, byteorder='little'))
        self.bit_reverse(crcb)
        crc = int.from_bytes(crcb, byteorder='big')
        return crc, self.n

    @classmethod
    def sum_whole(cls, bs):
        """Checksum a single piece of data.

        IMPORTANT: the data in bs is DESTROYED.

        """
        c = cls()
        c.sum(bs)
        return c.finish()

    @staticmethod
    def bit_reverse(bs):
        """Reverse the bits in every byte of the argument in-place"""
        for i,b in enumerate(bs):
            r = 0
            t = 0x80
            s = 0x01
            while t:
                if (b & t):
                    r |= s
                t >>= 1;
                s <<= 1;
            bs[i] = r

if __name__ == '__main__':
    # Checksum all files passed as arguments, or stdin if none
    from sys import argv,stdin
    if len(argv) == 1:
            bs = bytearray(stdin.buffer.read())
            crc, n = PosixCkSum.sum_whole(bs)
            print(crc, n)
    else:
        for fn in argv[1:]:
            if fn == '-':
                bs = bytearray(stdin.buffer.read())
            else:
                with open(fn, 'rb') as f:
                    bs = bytearray(f.read())
            crc, n = PosixCkSum.sum_whole(bs)
            print(crc, n, fn)

Attachment: signature.asc
Description: OpenPGP digital signature

_______________________________________________
Gnupg-users mailing list
Gnupg-users@gnupg.org
http://lists.gnupg.org/mailman/listinfo/gnupg-users

Reply via email to