|
| 1 | +Some functions / snippets of code that I think may be very useful to any postgres-user out there... |
| 2 | + |
| 3 | + |
| 4 | +=========================================================================================================================== |
| 5 | +================ |
| 6 | +FUNCTION GET_OTP |
| 7 | +================ |
| 8 | + |
| 9 | +AUTHOR: |
| 10 | +------- |
| 11 | +R. Wilmans-Sangwienwong (2019) |
| 12 | + |
| 13 | +PURPOSE: |
| 14 | +-------- |
| 15 | +Generate (a set of) TOTP, based on the SESSION_USER and the existence of that user in the table 'administratie.login.login' (easily changed to whatever) and |
| 16 | +the corresponding secret key ('administratie.login.secret_key'). |
| 17 | +This can be used for either requesting an OTP or used for checking if a provided OTP matche. |
| 18 | + |
| 19 | +PARAMETERS: |
| 20 | +----------- |
| 21 | +timeframe : The time (in full seconds) before the OTP expires. |
| 22 | + Datatype: INTEGER |
| 23 | + Default: 30 (seconds) |
| 24 | +totp_digits : The nunmber of digits to be used as a TOTP |
| 25 | + Datatype: INTEGER |
| 26 | + Default: 6 |
| 27 | +baa : Before-And-After: extra timeframes calculated in order to account for differences in system-times |
| 28 | + baa => 2 means two timeframes BEFORE current, the current timeframe and two timeframes AFTER the current timeframe |
| 29 | + Datatype: INTEGER |
| 30 | + Default: 0 (so only the current timeframe) |
| 31 | +test_key : The 'secret-key' to use, instead of using the actual sercret_key (as stored in table 'adminstratie.login') |
| 32 | + |
| 33 | +RETURNS: |
| 34 | +-------- |
| 35 | +TEXT[] / Array with strings, with every string representing the TOTP for the requested timeframes. |
| 36 | + |
| 37 | +Example: |
| 38 | +-- --------------------------------------------------------------- |
| 39 | +SELECT get_otp(timeframe => 30, baa=>3); |
| 40 | +-- --------------------------------------------------------------- |
| 41 | +SELECT get_otp(timeframe => 30, baa=>1, test_key => 'JBSWY3DPEHPK3PXP' ); // Works well to test with http://blog.tinisles.com/2011/10/google-authenticator-one-time-password-algorithm-in-javascript/ |
| 42 | +-- -------------------------------------------------------------- |
| 43 | +SELECT '123456' = ANY(get_otp()) |
| 44 | +-- -------------------------------------------------------------- |
| 45 | + |
| 46 | + |
| 47 | +=========================================================================================================================== |
| 48 | +======================= |
| 49 | +FUNCTION GEN_RND_BASE32 |
| 50 | +======================= |
| 51 | + |
| 52 | +AUTHOR: |
| 53 | +------- |
| 54 | +R. Wilmans-Sangwienwong (2019) |
| 55 | + |
| 56 | +PURPOSE: |
| 57 | +-------- |
| 58 | + |
| 59 | +To generate a random string of length [keylength] in base32. That is, only (uppercase) letters |
| 60 | +will be used, as well as digits 2 - 7 (inclusive). |
| 61 | +This may be used to provide a server key for (T)OTP purposes. |
| 62 | + |
| 63 | +PARAMETERS: |
| 64 | +----------- |
| 65 | +keylength : Number of characters the output-string will contain. |
| 66 | + Datatype: INTEGER |
| 67 | + Default 20 |
| 68 | + |
| 69 | +RETURNS: |
| 70 | +-------- |
| 71 | +TEXT / String of length [keylength]. |
| 72 | + |
| 73 | +Example: |
| 74 | +-- --------------------------------------------------------------- |
| 75 | +SELECT gen_rnd_base32(25); |
| 76 | +-- --------------------------------------------------------------- |
| 77 | + |
| 78 | + |
| 79 | +=========================================================================================================================== |
| 80 | +================== |
| 81 | +FUNCTION TRANSPOSE |
| 82 | +================== |
| 83 | + |
| 84 | +PARAMETERS: |
| 85 | +----------- |
| 86 | +ds_in : (qualified) table name that serves as input. |
| 87 | + No Default - REQUIRED |
| 88 | +ds_out : name of the (temporary!) table that will be created containing the output results. |
| 89 | + DEFAULT 'transpose_out' |
| 90 | +by_vars : the column (or set of columns, separated by a comma) that serves as an identifier by which all the value-columns are transposed |
| 91 | + So every unique set of by_vars will result in ONE output-row (but with different columns, depending on 'category_var'). |
| 92 | + No default. |
| 93 | + If no by_vars are given, the IDENTITY columns will be used. If there are none, the FIRST column will be used (first, according to PG) |
| 94 | +category_var: column that contains the 'labels' of the transposed values; the columns in the output will be named conform the values of this column |
| 95 | + If more than one (column name is) given, only the FIRST will be used. |
| 96 | + No default. When empty (/not given) then the prefix will be used. |
| 97 | +prefix : the prefix that will be used if no category-var is given of found. The resulting (transposed) columns will be named '<prefix><rownumber>' |
| 98 | + with rownumber being the n-th row within the by_vars-group. |
| 99 | + Default '_'. Not used when (valid) category_var given. |
| 100 | + |
| 101 | +RETURNS: |
| 102 | +-------- |
| 103 | +BOOLEAN (TRUE/FALSE). TRUE; succes. FALSE; an error has occurred. |
| 104 | + |
| 105 | +Example: |
| 106 | +-- --------------------------------------------------------------- |
| 107 | +DROP TABLE IF EXISTS raoul; |
| 108 | +CREATE TEMPORARY TABLE raoul (rijnr INTEGER, categorie CHARACTER VARYING(5), waarde INTEGER, leeftijd INTEGER); |
| 109 | +INSERT INTO raoul (rijnr, categorie, waarde, leeftijd) |
| 110 | +VALUES (1,'man1', 4,18), |
| 111 | + (1,'man2', 3,44), |
| 112 | + (1,'man3', 2,21), |
| 113 | + (1,'man4', 1,35), |
| 114 | + (2,'man2', 22,29), |
| 115 | + (2,'man3', 23,17); |
| 116 | +-- --------------------------------------------------------------- |
| 117 | +SELECT transpose( ds_in => 'raoul', |
| 118 | + ds_out => 'r_xpose', |
| 119 | + by_vars => 'rijnr', |
| 120 | + category_var => 'categorie'); |
| 121 | +SELECT * FROM r_xpose; |
| 122 | +-- --------------------------------------------------------------- |
| 123 | +SELECT transpose( ds_in => 'raoul', |
| 124 | + category_var => 'categorie'); |
| 125 | +SELECT * FROM transpose_out; |
| 126 | +-- --------------------------------------------------------------- |
| 127 | +SELECT transpose( ds_in => 'raoul', |
| 128 | + by_vars => 'rijnr, categorie'); |
| 129 | +SELECT * FROM transpose_out; |
| 130 | +-- --------------------------------------------------------------- |
| 131 | + |
| 132 | +=========================================================================================================================== |
| 133 | +=================== |
| 134 | +FUNCTION VERIFY_OTP |
| 135 | +=================== |
| 136 | + |
| 137 | +PURPOSE: |
| 138 | +-------- |
| 139 | +Check given TOTP, based on the given login. |
| 140 | + |
| 141 | +PARAMETERS: |
| 142 | +----------- |
| 143 | +for_login : The login as registered in table administratie.login ('login'), to use the corresponding secret key ('secret_key'), |
| 144 | + to calculate TOTP. |
| 145 | + Datatype: TEXT |
| 146 | + Default: '' |
| 147 | +given_totp : The TOTP to verify (given as a text) |
| 148 | + Datatype: TEXT |
| 149 | + Default: '' |
| 150 | +timeframe : The time (in full seconds) before the OTP expires. |
| 151 | + Datatype: INTEGER |
| 152 | + Default: 30 (seconds) |
| 153 | +totp_digits : The nunmber of digits to be used as a TOTP |
| 154 | + Datatype: INTEGER |
| 155 | + Default: 6 |
| 156 | +baa : Before-And-After: extra timeframes calculated in order to account for differences in system-times |
| 157 | + baa => 2 means two timeframes BEFORE current, the current timeframe and two timeframes AFTER the current timeframe |
| 158 | + Datatype: INTEGER |
| 159 | + Default: 1 (so one timeframe before the current timeframe, the current timeframe and one timeframe after the current timeframe) |
| 160 | + |
| 161 | +RETURNS: |
| 162 | +-------- |
| 163 | +BOOLEAN: TRUE if TOTP is verified, FALSE if falsified. |
| 164 | + |
| 165 | +REMARKS: |
| 166 | +-------- |
| 167 | +xxxxx |
| 168 | + |
| 169 | +Example: |
| 170 | +-- --------------------------------------------------------------- |
| 171 | +SELECT verify_otp(for_login => '_84f28fe026190c9b885dc74b63759893', given_totp => '404112') |
| 172 | +-- --------------------------------------------------------------- |
| 173 | + |
| 174 | +=========================================================================================================================== |
| 175 | +====================== |
| 176 | +FUNCTION BASE32_DECODE |
| 177 | +====================== |
| 178 | + |
| 179 | +AUTHOR: |
| 180 | +------- |
| 181 | +R. Wilmans-Sangwienwong (2019) |
| 182 | + |
| 183 | +PURPOSE: |
| 184 | +-------- |
| 185 | + |
| 186 | +To decode the given string (base32-coded!) and return the bytes AS BYTEA. |
| 187 | +This will, conform the useage of Google, return only the number of bytes that are fully defined |
| 188 | +by the input base32 string. Any residual bits (less than 8, thus not 'filling up' to a whole byte) |
| 189 | +will NOT be returned (and thus 'discarded'). |
| 190 | +Future development may see an option to return the 'not fully filled byte' (padded with zeros for the residual bits). |
| 191 | + |
| 192 | +PARAMETERS: |
| 193 | +----------- |
| 194 | +string : A base-32 encoded string |
| 195 | + Datatype: TEXT |
| 196 | + No default |
| 197 | + |
| 198 | +RETURNS: |
| 199 | +-------- |
| 200 | +BYTEA / Bytestring representing all fully-defined bytes of the input-string. |
| 201 | + |
| 202 | +REMARKS: |
| 203 | +-------- |
| 204 | +Any non-base32 characters will be removed prior to decoding the base32 input string. |
| 205 | + |
| 206 | +Example: |
| 207 | +-- --------------------------------------------------------------- |
| 208 | +SELECT base32_decode('ABSWY3DPEHPK3PXA'); |
| 209 | +-- --------------------------------------------------------------- |
0 commit comments