@@ -95,7 +95,7 @@ class encryptContentPlugin(BasePlugin):
9595 ('translations' , config_options .Type (dict , default = {}, required = False )),
9696 ('hash_filenames' , config_options .Type (dict , default = {}, required = False )),
9797 ('kdf_pow' , config_options .Type (int , default = int (4 ))),
98- ('sign_files' , config_options .Type (bool , default = False )),
98+ ('sign_files' , config_options .Type (string_types , default = None )),
9999 ('sign_key' , config_options .Type (string_types , default = 'encryptcontent.key' )),
100100 # legacy features, doesn't exist anymore
101101 )
@@ -124,13 +124,20 @@ def __download_and_check__(self, filename, url, hash):
124124 logger .error ('Error downloading asset "' + filename .name + '" hash mismatch!' )
125125 os ._exit (1 )
126126
127- def __sign_file__ (self , fname , key ):
127+ def __sign_file__ (self , fname , url , key ):
128128 h = SHA512 .new ()
129- with open (fname , "rb" ) as f :
130- for chunk in iter (lambda : f .read (4096 ), b"" ):
131- h .update (chunk )
129+ if fname :
130+ with open (fname , "rb" ) as f :
131+ for chunk in iter (lambda : f .read (4096 ), b"" ):
132+ h .update (chunk )
133+ else :
134+ with urlopen (url ) as response :
135+ h .update (response .read ())
132136 signer = eddsa .new (key , 'rfc8032' )
133- return base64 .b64encode (signer .sign (h )).decode ()
137+ return (
138+ url ,
139+ base64 .b64encode (signer .sign (h )).decode ()
140+ )
134141
135142 def __encrypt_key__ (self , key , password , iterations ):
136143 """ Encrypts key with PBKDF2 and AES-256. """
@@ -414,17 +421,20 @@ def on_config(self, config, **kwargs):
414421 self .setup ['level_keystore' ][level ] = new_entry
415422
416423 if self .config ['sign_files' ]:
417- if not exists (self .config ['sign_key' ]):
418- logger .debug ('Generating signing key and saving to "{file}".' .format (file = str (self .config ['sign_key' ])))
424+ configpath = Path (config ['config_file_path' ]).parents [0 ]
425+ sign_key_path = configpath .joinpath (self .config ['sign_key' ])
426+ if not exists (sign_key_path ):
427+ logger .info ('Generating signing key and saving to "{file}".' .format (file = str (self .config ['sign_key' ])))
419428 key = ECC .generate (curve = 'Ed25519' )
420429 self .setup ['sign_key' ] = key
421- with open (self . config [ 'sign_key' ] ,'wt' ) as f :
430+ with open (sign_key_path ,'wt' ) as f :
422431 f .write (key .export_key (format = 'PEM' ))
423432 else :
424- logger .debug ('Reading signing key from "{file}".' .format (file = str (self .config ['sign_key' ])))
425- with open (self . config [ 'sign_key' ] ,'rt' ) as f :
433+ logger .info ('Reading signing key from "{file}".' .format (file = str (self .config ['sign_key' ])))
434+ with open (sign_key_path ,'rt' ) as f :
426435 key = ECC .import_key (f .read ())
427436 self .setup ['sign_key' ] = key
437+ self .setup ['files_to_sign' ] = []
428438
429439 def on_pre_build (self , config , ** kwargs ):
430440 """
@@ -735,6 +745,12 @@ def on_post_page(self, output_content, page, config, **kwargs):
735745 self .setup ['locations' ][location ] = page .encryptcontent ['key' ]
736746 delattr (page , 'encryptcontent' )
737747
748+ if self .config ['sign_files' ]:
749+ new_entry = {}
750+ new_entry ['file' ] = Path (config .data ["site_dir" ] + "/" + page .file .dest_uri )
751+ new_entry ['url' ] = config .data ["site_url" ] + page .file .url
752+ self .setup ['files_to_sign' ].append (new_entry )
753+
738754 return output_content
739755
740756 def on_post_build (self , config , ** kwargs ):
@@ -749,6 +765,21 @@ def on_post_build(self, config, **kwargs):
749765 with open (decrypt_js_path , "w" ) as file :
750766 file .write (self .__generate_decrypt_js__ ())
751767
768+ if self .config ['sign_files' ]:
769+ new_entry = {}
770+ new_entry ['file' ] = decrypt_js_path
771+ new_entry ['url' ] = config .data ["site_url" ] + '/assets/javascripts/decrypt-contents.js'
772+ self .setup ['files_to_sign' ].append (new_entry )
773+ for jsurl in JS_LIBRARIES :
774+ new_entry = {}
775+ if self .config ['selfhost' ]:
776+ new_entry ['file' ] = Path (config .data ["site_dir" ] + '/assets/javascripts/cryptojs/' + jsurl [0 ].rsplit ('/' ,1 )[1 ])
777+ new_entry ['url' ] = config .data ["site_url" ] + '/assets/javascripts/cryptojs/' + jsurl [0 ].rsplit ('/' ,1 )[1 ]
778+ else :
779+ new_entry ['file' ] = ""
780+ new_entry ['url' ] = "https:" + jsurl [0 ]
781+ self .setup ['files_to_sign' ].append (new_entry )
782+
752783 self .setup ['password_keystore' ].clear ()
753784 self .setup ['obfuscate_keystore' ].clear ()
754785 self .setup ['level_keystore' ].clear ()
@@ -796,3 +827,14 @@ def on_post_build(self, config, **kwargs):
796827 ' Your weakest password only got {spied_on} bits of entropy, if someone watched you while typing'
797828 ' (and a maximum of {secret} bits total)!' .format (spied_on = math .ceil (self .setup ['min_enttropy_spied_on' ]), secret = math .ceil (self .setup ['min_enttropy_secret' ]))
798829 )
830+
831+ if self .config ['sign_files' ]:
832+ signatures = []
833+ for file in self .setup ['files_to_sign' ]:
834+ signatures .append (
835+ self .__sign_file__ (file ['file' ], file ['url' ], self .setup ['sign_key' ])
836+ )
837+ if signatures :
838+ sign_file_path = Path (config .data ["site_dir" ] + '/' + self .config ['sign_files' ])
839+ with open (sign_file_path , "w" ) as file :
840+ file .write (json .dumps (signatures ))
0 commit comments