0

I am trying to have a program sign and then later verify the contents of a file. However, wile the first verification will always return true, once the data is written to files and then loaded again, the verification usually fails, but is sometimes successful.

Even when the code fails, The outputs of the two print signature and print hash.hexdigest() calls are visually identical.

My test code is:

from Crypto.Hash import SHA256
from Crypto.PublicKey import RSA
from Crypto.Signature import PKCS1_PSS
def generate():
    key_file = open("TestPrivateKey")
    private_key = RSA.importKey(key_file)
    public_key = private_key.publickey()

    seed_file = open("Seed")

    plaintext = seed_file.read()

    hash = SHA256.new(plaintext)
    signer = PKCS1_PSS.new(private_key)
    signature =  signer.sign(hash)

    plaintext_file = open("plaintext", 'w')
    plaintext_file.write(plaintext)
    signature_file = open("signature", 'w')
    signature_file.write(signature)
    print signature
    print hash.hexdigest()

    verifier = PKCS1_PSS.new(public_key)

    print verifier.verify(hash, signature)

def verification_test():
    plaintext_file = open("plaintext")
    signature_file = open("signature", 'rb')

    plaintext = plaintext_file.read()
    public_key = RSA.importKey(open("TestPublicKey"))
    signature = signature_file.read()
    print signature

    hash = SHA256.new(plaintext)
    print hash.hexdigest()

    verifier = PKCS1_PSS.new(public_key)
    return verifier.verify(hash, signature)


if __name__ == '__main__':
    generate()
    print verification_test()

Does anyone know what mistake I made? There must be something happening when the signature is written to the file and then read back in, but I can't figure out what it is.

Edit: Before I run this script, I run the initialization functions:

from Crypto.PublicKey import RSA

def create_keys():
    private_key = RSA.generate(4096)
    file = open("TestPrivateKey", 'w')
    file.write(private_key.exportKey())
    file = open("TestPublicKey", 'w')
    file.write(private_key.publickey().exportKey())

def create_seed():
    file = open("Seed", 'w')
    file.write("Test")
Ralin
  • 13
  • 5
  • I notice that you've included **almost** all of a complete working program. I expect that if you add two or three more lines, you'll have a complete working example. Please post a complete working program that demonstrates your error. See http://stackoverflow.com/help/mcve for more information. – Robᵩ Jul 29 '14 at 19:01
  • Sorry, it was already telling me I had too much code. I'll add the rest of the code, but it just fills the `Seed` file with junk, and generates and stores the keys. – Ralin Jul 29 '14 at 19:17
  • What you've pasted so far still won't run. Do you have any `import` statements? – Robᵩ Jul 29 '14 at 19:42
  • Oh, yeah, I import the neccesary modules from PyCrypto. – Ralin Jul 29 '14 at 20:11

1 Answers1

0

I notice two problems with your code.

First, you are writing arbitrary binary data to a file what was opened for text:

signature_file = open("signature", 'w')  #bad
signature_file.write(signature)

should be:

signature_file = open("signature", 'wb')  #good
signature_file.write(signature)

Second, you never close your files. Try this:

with open("signature", 'wb') as signature_file:
    signature_file.write(signature)

and similarly for all of the other open files.


from Crypto.Hash import SHA256
from Crypto.PublicKey import RSA
from Crypto.Signature import PKCS1_PSS
def generate():
    with open("TestPrivateKey") as key_file:
        private_key = RSA.importKey(key_file)
    public_key = private_key.publickey()

    with open("Seed") as seed_file:
        plaintext = seed_file.read()

    hash = SHA256.new(plaintext)
    signer = PKCS1_PSS.new(private_key)
    signature =  signer.sign(hash)

    with open("plaintext", 'w') as plaintext_file:
        plaintext_file.write(plaintext)
    with open("signature", 'wb') as signature_file:
        signature_file.write(signature)
    #print signature
    print hash.hexdigest()

    verifier = PKCS1_PSS.new(public_key)

    print verifier.verify(hash, signature)

def verification_test():
    with open("plaintext") as plaintext_file:
        plaintext = plaintext_file.read()
    with open("signature", 'rb') as signature_file:
        signature = signature_file.read()

    with open("TestPublicKey") as public_key_file:
        public_key = RSA.importKey(public_key_file)
    #print signature

    hash = SHA256.new(plaintext)
    print hash.hexdigest()

    verifier = PKCS1_PSS.new(public_key)
    return verifier.verify(hash, signature)


if __name__ == '__main__':
    generate()
    print verification_test()
Robᵩ
  • 163,533
  • 20
  • 239
  • 308
  • Ok, I changed it to open the file for binary, and now it works. I originally was both writing and reading as a string, but the reader interpreted some of the characters in the string as EOF, so I changed the read to binary, but I didn't change the write. I also added the with statements. – Ralin Jul 29 '14 at 21:08