1
- import os
2
1
import pkg_resources
3
- import hashlib
4
- import base64
5
2
from pathlib import Path
6
3
from cryptography .exceptions import InvalidSignature
7
- from cryptography .hazmat .backends import default_backend
8
- from cryptography .hazmat .primitives .serialization import load_pem_public_key
9
- from cryptography .hazmat .primitives .asymmetric import padding
10
- from cryptography .hazmat .primitives import hashes
11
-
12
- DJ_PUB_KEY = '''
13
- -----BEGIN PUBLIC KEY-----
14
- MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDUMOo2U7YQ1uOrKU/IreM3AQP2
15
- AXJC3au+S9W+dilxHcJ3e98bRVqrFeOofcGeRPoNc38fiLmLDUiBskJeVrpm29Wo
16
- AkH6yhZWk1o8NvGMhK4DLsJYlsH6tZuOx9NITKzJuOOH6X1I5Ucs7NOSKnmu7g5g
17
- WTT5kCgF5QAe5JN8WQIDAQAB
18
- -----END PUBLIC KEY-----
19
- '''
4
+ from raphael_python_metadata import hash_pkg , verify
20
5
21
6
discovered_plugins = {
22
7
entry_point .module_name : dict (plugon = entry_point .name , verified = False )
25
10
}
26
11
27
12
28
- def hash_pkg (pkgpath ):
29
- refpath = Path (pkgpath ).absolute ().parents [0 ]
30
- details = ''
31
- details = _update_details_dir (pkgpath , refpath , details )
32
- # hash output to prepare for signing
33
- return hashlib .sha1 ('blob {}\0 {}' .format (len (details ), details ).encode ()).hexdigest ()
34
-
35
-
36
- def _update_details_dir (dirpath , refpath , details ):
37
- paths = sorted (Path (dirpath ).absolute ().glob ('*' ))
38
- # walk a directory to collect info
39
- for path in paths :
40
- if 'pycache' not in str (path ):
41
- if os .path .isdir (str (path )):
42
- details = _update_details_dir (path , refpath , details )
43
- else :
44
- details = _update_details_file (path , refpath , details )
45
- return details
46
-
47
-
48
- def _update_details_file (filepath , refpath , details ):
49
- if '.sig' not in str (filepath ):
50
- with open (str (filepath ), 'r' ) as f :
51
- data = f .read ()
52
- # perfrom a SHA1 hash (same as git) that closely matches: git ls-files -s <dirname>
53
- mode = 100644
54
- hash = hashlib .sha1 ('blob {}\0 {}' .format (len (data ),data ).encode ()).hexdigest ()
55
- stage_no = 0
56
- relative_path = str (filepath .relative_to (refpath ))
57
- details = '{}{} {} {}\t {}\n ' .format (details , mode , hash , stage_no , relative_path )
58
- return details
59
-
60
-
61
- def _update_error_stack (module ):
13
+ def _update_error_stack (plugin_name ):
62
14
try :
63
- pkg = pkg_resources .get_distribution (module .__name__ )
64
- signature = pkg .get_metadata ('datajoint.sig' )
65
- pub_key = load_pem_public_key (bytes (DJ_PUB_KEY , 'UTF-8' ), backend = default_backend ())
66
- data = hash_pkg (module .__path__ [0 ])
67
- pub_key .verify (
68
- base64 .b64decode (signature .encode ()),
69
- data .encode (),
70
- padding .PSS (mgf = padding .MGF1 (hashes .SHA256 ()), salt_length = padding .PSS .MAX_LENGTH ),
71
- hashes .SHA256 ())
72
- discovered_plugins [module .__name__ ]['verified' ] = True
73
- print ('DataJoint verified plugin `{}` introduced.' .format (module .__name__ ))
15
+ base_name = 'datajoint'
16
+ base_meta = pkg_resources .get_distribution (base_name )
17
+ plugin_meta = pkg_resources .get_distribution (plugin_name )
18
+
19
+ data = hash_pkg (str (Path (plugin_meta .module_path , plugin_name )))
20
+ signature = plugin_meta .get_metadata ('{}.sig' .format (plugin_name ))
21
+ pubkey_path = str (Path (base_meta .egg_info , '{}.pub' .format (base_name )))
22
+ verify (pubkey_path , data , signature )
23
+ discovered_plugins [plugin_name ]['verified' ] = True
24
+ print ('DataJoint verified plugin `{}` introduced.' .format (plugin_name ))
74
25
except (FileNotFoundError , InvalidSignature ):
75
- print ('Unverified plugin `{}` introduced.' .format (module . __name__ ))
26
+ print ('Unverified plugin `{}` introduced.' .format (plugin_name ))
76
27
77
28
78
29
def override (plugin_type , context , method_list = None ):
@@ -84,7 +35,7 @@ def override(plugin_type, context, method_list=None):
84
35
module = __import__ (module_name )
85
36
module_dict = module .__dict__
86
37
# update error stack (if applicable)
87
- _update_error_stack (module )
38
+ _update_error_stack (module . __name__ )
88
39
# override based on plugon preference
89
40
if method_list is not None :
90
41
new_methods = []
0 commit comments