So how might we a lock down a file for a given amount of time? One method is to get the receiver to perform some work to find the encryption key. For example if we wanted to lock it down for one hour we could take a seed value, and then continually hash it for a given amount of time that we thing the recipient would required to generate the same key. This would then generate the same key, if the sender and recipient share the number of iterations of the hash used. We can then tell the receiver the seed value and the number of iterations they must use in order to compute the key, along with the encrypted message. The receiver must then compute the key and prove their work [cracking puzzle here]:
Time-lock puzzles/Proof of WorkOutlineThe method, though, is not perfect as the cost of the operation will vary with the clock speed of the processor. We will not be able to compute in parallel as the hashing operations must be done one at a time. The other side will still have a cost in the computation. The following is a sample run for a time to compute the key of 0.25 seconds: Message: The quick brown fox Keyseed: 12345 Encryption key: 6CUlrN1BZPz9ytTrKHDGsbLEj20a15stop5S_0ktCMk= Encrypted value: gAAAAABbCdAfteG9dAUdmQgqHoY4hby9moK51-qYTRlYXpO7Ghbev6GqDFsadulgmZvgHVUv6mRwE9SRcbF2-UVnDW_KzJs7GHX9ffcZ-btIH-pKP5ubOSE= Decyption key: 6CUlrN1BZPz9ytTrKHDGsbLEj20a15stop5S_0ktCMk= Decrypted value: The quick brown fox Key time (secs): 0.25 Iterations: 76109 Time to encrypt: 0.724999904633 Time to decrypt: 0.219000101089 And here is some sample code. We use SHA-256 to hash the seed. # https://asecuritysite.com/encryption/pow?Length=10 import base64 from cryptography.fernet import Fernet from datetime import timedelta from time import time from hashlib import sha256 message="hello" keyseed = "12345" timeout=0.5 def generate_by_time(seed, delta): end = time() + delta.total_seconds() h = sha256(seed.encode()).digest() iters = 0 while time() < end: h = sha256(h).digest() iters += 1 return base64.urlsafe_b64encode(h), iters def generate_by_iters(seed, iters): h = sha256(seed.encode()).digest() for x in range(iters): h = sha256(h).digest() return base64.urlsafe_b64encode(h) def encrypt(keyseed, delta, message): key, iterations = generate_by_time(keyseed, delta) encrypted = Fernet(key).encrypt(message.encode()) return iterations, encrypted,key def decrypt(keyseed, iterations, encrypted): key = generate_by_iters(keyseed, iterations) decrypted = Fernet(key).decrypt(encrypted) return decrypted,key print ("Message:\t",message) print ("Keyseed:\t",keyseed) delta = timedelta(seconds=timeout) t1 = time() iters, encrypted,key = encrypt(keyseed, delta, message) print ("\nEncryption key:\t\t",key) print ("Encrypted value:\t",encrypted) t2 = time() decrypted,key = decrypt(keyseed, iters, encrypted) t3 = time() print ("\nDecyption key:\t\t",key) print ("Decrypted value:\t",decrypted) print ("\nKey time (secs):\t", timeout) print ("Iterations:\t\t", iters) print ("\nTime to encrypt:", t2 - t1) print ("Time to decrypt:", t3 - t2) Presentation |