self.log.debug("%s: Valid signs: %s/%s" % (inner_path, valid_signs, signs_required)) return valid_signs >= signs_required else: # Old style signing return CryptBitcoin.verify(sign_content, self.site.address, sign) except Exception, err: self.log.error("Verify sign error: %s" % Debug.formatException(err)) return False else: # Check using sha512 hash file_info = self.getFileInfo(inner_path) if file_info: if "sha512" in file_info: hash_valid = CryptHash.sha512sum(file) == file_info["sha512"] elif "sha1" in file_info: # Backward compatibility hash_valid = CryptHash.sha1sum(file) == file_info["sha1"] else: hash_valid = False if file_info.get("size", 0) != file.tell(): self.log.error( "%s file size does not match %s <> %s, Hash: %s" % (inner_path, file.tell(), file_info.get("size", 0), hash_valid) ) return False return hash_valid else: # File not in content.json self.log.error("File not in content.json: %s" % inner_path) return False def addOptionalFile(self, inner_path):
def signContent(self, privatekey=None): if not self.content: # New site self.log.info( "Site not exits yet, loading default content.json values...") self.content = { "files": {}, "title": "%s - ZeroNet_" % self.address, "sign": "", "modified": 0.0, "description": "", "address": self.address, "ignore": "", "zeronet_version": config.version } # Default content.json self.log.info("Opening site data directory: %s..." % self.directory) hashed_files = {} for root, dirs, files in os.walk(self.directory): for file_name in files: file_path = self.getPath("%s/%s" % (root, file_name)) if file_name == "content.json" or ( self.content["ignore"] and re.match( self.content["ignore"], file_path.replace(self.directory + "/", "")) ): # Dont add content.json and ignore regexp pattern definied in content.json self.log.info("- [SKIPPED] %s" % file_path) else: sha1sum = CryptHash.sha1sum( file_path) # Calculate sha1 sum of file sha512sum = CryptHash.sha512sum( file_path) # Calculate sha512 sum of file inner_path = re.sub("^%s/" % re.escape(self.directory), "", file_path) self.log.info("- %s (SHA512: %s)" % (file_path, sha512sum)) hashed_files[inner_path] = { "sha1": sha1sum, "sha512": sha512sum, "size": os.path.getsize(file_path) } # Generate new content.json self.log.info("Adding timestamp and sha512sums to new content.json...") content = self.content.copy() # Create a copy of current content.json content["address"] = self.address content["files"] = hashed_files # Add files sha512 hash content["modified"] = time.time() # Add timestamp content["zeronet_version"] = config.version # Signer's zeronet version del (content["sign"]) # Delete old sign # Signing content from Crypt import CryptBitcoin self.log.info("Verifying private key...") privatekey_address = CryptBitcoin.privatekeyToAddress(privatekey) if self.address != privatekey_address: return self.log.error( "Private key invalid! Site address: %s, Private key address: %s" % (self.address, privatekey_address)) self.log.info("Signing modified content.json...") sign_content = json.dumps(content, sort_keys=True) sign = CryptBitcoin.sign(sign_content, privatekey) content["sign"] = sign # Saving modified content.json self.log.info("Saving to %s/content.json..." % self.directory) open("%s/content.json" % self.directory, "w").write(json.dumps(content, indent=4, sort_keys=True)) self.log.info("Site signed!") return True
def sign(self, inner_path="content.json", privatekey=None, filewrite=True): content = self.contents.get(inner_path) if not content: # Content not exits yet, load default one self.log.info("File %s not exits yet, loading default values..." % inner_path) content = {"files": {}, "signs": {}} # Default content.json if inner_path == "content.json": # Its the root content.json, add some more fields content["title"] = "%s - ZeroNet_" % self.site.address content["description"] = "" content["signs_required"] = 1 content["ignore"] = "" directory = self.toDir(self.site.getPath(inner_path)) self.log.info("Opening site data directory: %s..." % directory) hashed_files = {} for root, dirs, files in os.walk(directory): for file_name in files: file_path = self.site.getPath("%s/%s" % (root.strip("/"), file_name)) file_inner_path = re.sub(re.escape(directory), "", file_path) if file_name == "content.json" or ( content.get("ignore") and re.match(content["ignore"], file_inner_path) ) or file_name.startswith( "." ): # Ignore content.json, definied regexp and files starting with . self.log.info("- [SKIPPED] %s" % file_inner_path) else: sha512sum = CryptHash.sha512sum( file_path) # Calculate sha512 sum of file self.log.info("- %s (SHA512: %s)" % (file_inner_path, sha512sum)) hashed_files[file_inner_path] = { "sha512": sha512sum, "size": os.path.getsize(file_path) } if inner_path == "content.json": # Backward compatibility to root conten.json hashed_files[file_inner_path][ "sha1"] = CryptHash.sha1sum(file_path) # Generate new content.json self.log.info("Adding timestamp and sha512sums to new content.json...") new_content = content.copy() # Create a copy of current content.json new_content["files"] = hashed_files # Add files sha512 hash new_content["modified"] = time.time() # Add timestamp if inner_path == "content.json": new_content["address"] = self.site.address new_content["zeronet_version"] = config.version new_content["signs_required"] = content.get("signs_required", 1) from Crypt import CryptBitcoin self.log.info("Verifying private key...") privatekey_address = CryptBitcoin.privatekeyToAddress(privatekey) valid_signers = self.getValidSigners(inner_path) if privatekey_address not in valid_signers: return self.log.error( "Private key invalid! Valid signers: %s, Private key address: %s" % (valid_signers, privatekey_address)) self.log.info("Correct %s in valid signers: %s" % (privatekey_address, valid_signers)) if inner_path == "content.json" and privatekey_address == self.site.address: # If signing using the root key sign the valid signers new_content["signers_sign"] = CryptBitcoin.sign( "%s:%s" % (new_content["signs_required"], ",".join(valid_signers)), privatekey) if not new_content["signers_sign"]: self.log.info("Old style address, signers_sign is none") self.log.info("Signing %s..." % inner_path) if "signs" in new_content: del (new_content["signs"]) # Delete old signs if "sign" in new_content: del (new_content["sign"] ) # Delete old sign (backward compatibility) sign_content = json.dumps(new_content, sort_keys=True) sign = CryptBitcoin.sign(sign_content, privatekey) #new_content["signs"] = content.get("signs", {}) # TODO: Multisig if sign: # If signing is successful (not an old address) new_content["signs"] = {} new_content["signs"][privatekey_address] = sign if inner_path == "content.json": # To root content.json add old format sign for backward compatibility oldsign_content = json.dumps(new_content, sort_keys=True) new_content["sign"] = CryptBitcoin.signOld(oldsign_content, privatekey) if filewrite: self.log.info("Saving to %s..." % inner_path) json.dump(new_content, open(self.site.getPath(inner_path), "w"), indent=2, sort_keys=True) self.log.info("File %s signed!" % inner_path) if filewrite: # Written to file return True else: # Return the new content return new_content
) # Dump the json to string to remove whitepsace return CryptBitcoin.verify(sign_content, self.address, sign) except Exception, err: self.log.error("Verify sign error: %s" % Debug.formatException(err)) return False else: # Check using sha1 hash if self.content and inner_path in self.content["files"]: if "sha512" in self.content["files"][ inner_path]: # Use sha512 to verify if possible return CryptHash.sha512sum( file) == self.content["files"][inner_path]["sha512"] else: # Backward compatiblity return CryptHash.sha1sum( file) == self.content["files"][inner_path]["sha1"] else: # File not in content.json self.log.error("File not in content.json: %s" % inner_path) return False # Verify all files sha512sum using content.json def verifyFiles(self, quick_check=False): # Fast = using file size bad_files = [] if not self.content: # No content.json, download it first self.needFile("content.json", update=True) # Force update to fix corrupt file self.loadContent() # Reload content.json for inner_path in self.content["files"].keys(): file_path = self.getPath(inner_path) if not os.path.isfile(file_path):