Rev 59 | Rev 63 | Go to most recent revision | Show entire file | Regard whitespace | Details | Blame | Last modification | View Log | RSS feed
Rev 59 | Rev 60 | ||
---|---|---|---|
Line 44... | Line 44... | ||
44 | sp = salt + password |
44 | sp = salt + password |
45 | ps = password + salt |
45 | ps = password + salt |
46 | sps = salt + password + salt |
46 | sps = salt + password + salt |
47 | hmac = HMAC (salt is the key) |
47 | hmac = HMAC (salt is the key) |
48 | 48 | ||
- | 49 | Like most Crypt-hashes, <salt> and <hash> are Radix64 coded |
|
- | 50 | with alphabet './0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz' and no padding. |
|
- | 51 | ||
49 | Link to the online specification: |
52 | Link to the online specification: |
50 | https://oidplus.viathinksoft.com/oidplus/?goto=oid%3A1.3.6.1.4.1.37476.3.0.1.1 |
53 | https://oidplus.viathinksoft.com/oidplus/?goto=oid%3A1.3.6.1.4.1.37476.3.0.1.1 |
51 | 54 | ||
52 | Reference implementation in PHP: |
55 | Reference implementation in PHP: |
53 | https://github.com/danielmarschall/php_utils/blob/master/vts_crypt.inc.php |
56 | https://github.com/danielmarschall/php_utils/blob/master/vts_crypt.inc.php |
54 | 57 | ||
55 | */ |
58 | */ |
56 | 59 | ||
57 | define('OID_MCF_VTS_V1', '1.3.6.1.4.1.37476.3.0.1.1'); // { iso(1) identified-organization(3) dod(6) internet(1) private(4) enterprise(1) 37476 specifications(3) misc(0) modular-crypt-format(1) vts-crypt-v1(1) } |
60 | define('OID_MCF_VTS_V1', '1.3.6.1.4.1.37476.3.0.1.1'); // { iso(1) identified-organization(3) dod(6) internet(1) private(4) enterprise(1) 37476 specifications(3) misc(0) modular-crypt-format(1) vts-crypt-v1(1) } |
58 | 61 | ||
59 | define('BASE64_RFC4648_ALPHABET', '0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz+/='); |
62 | define('BASE64_RFC4648_ALPHABET', '0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz+/'); |
60 | define('BASE64_CRYPT_ALPHABET', './0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz '); |
63 | define('BASE64_CRYPT_ALPHABET', './0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz'); |
61 | 64 | ||
62 | function crypt_radix64_encode($str) { |
65 | function crypt_radix64_encode($str) { |
63 | $x = $str; |
66 | $x = $str; |
64 | $x = base64_encode($x); |
67 | $x = base64_encode($x); |
- | 68 | $x = rtrim($x, '='); |
|
65 | $x = trim(strtr($x, BASE64_RFC4648_ALPHABET, BASE64_CRYPT_ALPHABET)); |
69 | $x = strtr($x, BASE64_RFC4648_ALPHABET, BASE64_CRYPT_ALPHABET); |
66 | return $x; |
70 | return $x; |
67 | } |
71 | } |
68 | 72 | ||
69 | function crypt_radix64_decode($str) { |
73 | function crypt_radix64_decode($str) { |
70 | $x = $str; |
74 | $x = $str; |
71 | $x = trim(strtr($x, BASE64_CRYPT_ALPHABET, BASE64_RFC4648_ALPHABET)); |
75 | $x = strtr($x, BASE64_CRYPT_ALPHABET, BASE64_RFC4648_ALPHABET); |
72 | $x = base64_decode($x); |
76 | $x = base64_decode($x); |
73 | return $x; |
77 | return $x; |
74 | } |
78 | } |
75 | 79 | ||
76 | assert(crypt_radix64_decode(crypt_radix64_encode('hallo'))); |
80 | // assert(crypt_radix64_decode(crypt_radix64_encode('TEST123')) === 'TEST123'); |
77 | 81 | ||
78 | function crypt_modular_format($id, $bin_salt, $bin_hash, $params=null) { |
82 | function crypt_modular_format($id, $bin_salt, $bin_hash, $params=null) { |
79 | // $<id>[$<param>=<value>(,<param>=<value>)*][$<salt>[$<hash>]] |
83 | // $<id>[$<param>=<value>(,<param>=<value>)*][$<salt>[$<hash>]] |
80 | $out = '$'.$id; |
84 | $out = '$'.$id; |
81 | if (!is_null($params)) { |
85 | if (!is_null($params)) { |
Line 164... | Line 168... | ||
164 | return crypt_modular_format(OID_MCF_VTS_V1, $bin_salt, $bin_hash, array('a'=>$algo,'m'=>$mode)); |
168 | return crypt_modular_format(OID_MCF_VTS_V1, $bin_salt, $bin_hash, array('a'=>$algo,'m'=>$mode)); |
165 | } else { |
169 | } else { |
166 | throw new Exception("Invalid VTS crypt version, expect 1."); |
170 | throw new Exception("Invalid VTS crypt version, expect 1."); |
167 | } |
171 | } |
168 | } |
172 | } |
169 | - | ||
170 | function vts_crypt_convert_from_old_oidplus($authkey, $salt) { |
- | |
171 | if (preg_match('@^A1([abcd])#(.+):(.+)$@', $authkey, $m)) { |
- | |
172 | // A1a#hashalgo:X with X being H(salt+password) in hex- or rfc4648-base64-notation |
- | |
173 | // A1b#hashalgo:X with X being H(password+salt) in hex- or rfc4648-base64-notation |
- | |
174 | // A1c#hashalgo:X with X being H(salt+password+salt) in hex- or rfc4648-base64-notation |
- | |
175 | // A1d#hashalgo:X with X being H_HMAC(password,salt) in hex- or rfc4648-base64-notation |
- | |
176 | $mode = ''; // avoid PHPstan warning |
- | |
177 | if ($m[1] == 'a') $mode = 'sp'; |
- | |
178 | else if ($m[1] == 'b') $mode = 'ps'; |
- | |
179 | else if ($m[1] == 'c') $mode = 'sps'; |
- | |
180 | else if ($m[1] == 'd') $mode = 'hmac'; |
- | |
181 | else assert(false); |
- | |
182 | $algo = $m[2]; |
- | |
183 | $bin_salt = $salt; |
- | |
184 | if (($algo == 'sha3-512') || ($algo == 'sha3-384') || ($algo == 'sha512') || ($algo == 'sha384')) { |
- | |
185 | $bin_hash = base64_decode($m[3]); |
- | |
186 | } else { |
- | |
187 | $bin_hash = hex2bin($m[3]); |
- | |
188 | } |
- | |
189 | return crypt_modular_format(OID_MCF_VTS_V1, $bin_salt, $bin_hash, array('a'=>$algo,'m'=>$mode)); |
- | |
190 | } else if (preg_match('@^A2#(.+)$@', $authkey, $m)) { |
- | |
191 | // A2#X with X being sha3(salt+password) in rfc4648-base64-notation |
- | |
192 | $mode = 'sp'; |
- | |
193 | $algo = 'sha3-512'; |
- | |
194 | $bin_salt = $salt; |
- | |
195 | $bin_hash = base64_decode($m[1]); |
- | |
196 | return crypt_modular_format(OID_MCF_VTS_V1, $bin_salt, $bin_hash, array('a'=>$algo,'m'=>$mode)); |
- | |
197 | } else if (preg_match('@^A3#(.+)$@', $authkey, $m)) { |
- | |
198 | // A3#X with X being bcrypt [not VTS hash!] |
- | |
199 | return $m[1]; |
- | |
200 | } else { |
- | |
201 | // Nothing to convert |
- | |
202 | return $authkey; |
- | |
203 | } |
- | |
204 | } |
- |