├── .travis.yml ├── Makefile ├── README.md ├── arg_parser ├── Makefile ├── arg_parser.c ├── arg_parser.h └── arg_parser_example.c ├── config ├── Makefile ├── genpass-example.ini ├── ini.c └── ini.h ├── defaults.md ├── encoders ├── Makefile ├── b10.c ├── b10.h ├── b64.c ├── b64.h ├── base16.c ├── base16.h ├── base91.c ├── base91.h ├── encoders.c ├── encoders.h ├── skey.c ├── skey.h ├── z85.c └── z85.h ├── genpass.c ├── genpass.gif ├── getpass ├── libscrypt ├── LICENSE ├── Makefile ├── README.md ├── b10.c ├── b10.h ├── b64.c ├── b64.h ├── crypto-mcf.c ├── crypto-scrypt-saltgen.c ├── crypto_scrypt-check.c ├── crypto_scrypt-hash.c ├── crypto_scrypt-hexconvert.c ├── crypto_scrypt-hexconvert.h ├── crypto_scrypt-nosse.c ├── libscrypt.h ├── libscrypt.version ├── main.c ├── sha256.c ├── sha256.h ├── skey.c ├── skey.h ├── slowequals.c ├── slowequals.h ├── sysendian.h ├── z85.c └── z85.h ├── man ├── genpass.1 └── getpass.1 ├── poison └── poison.h ├── readpass ├── Makefile ├── readpass.c ├── readpass.h ├── warn.c └── warn.h └── test ├── README.md ├── genpass-mp-input.exp.sh ├── genpass-name-and-mp-input.exp.sh ├── genpass-normal-input.exp.sh ├── genpass-registration-mode.exp.sh ├── genpass-site-and-mp-input.exp.sh ├── genpass-static.db ├── getpass.db └── test.sh /.travis.yml: -------------------------------------------------------------------------------- 1 | before_install: 2 | - sudo apt-get update 3 | #expect is required for testing genpass 4 | #xvfb, xclip and notify* are required for testing getpass 5 | - sudo apt-get install -y build-essential expect xclip notify-osd libnotify-bin 6 | script: make test 7 | -------------------------------------------------------------------------------- /Makefile: -------------------------------------------------------------------------------- 1 | PREFIX ?= /usr/local 2 | LIBDIR ?= $(PREFIX)/lib 3 | INCLUDEDIR ?= $(PREFIX)/include 4 | MAKE_DIR ?= install -d 5 | INSTALL_DATA ?= install 6 | 7 | CC?=gcc 8 | CFLAGS?=-O2 -Wall -g -fno-builtin-memset 9 | LDFLAGS?=-Wl,-z,now -Wl,-z,relro -Wl,-soname,libscrypt.so.0 -Wl,--version-script=libscrypt.version 10 | CFLAGS_EXTRA?=-Wl,-rpath=. 11 | 12 | SHELL=/bin/sh 13 | 14 | all: genpass 15 | 16 | deps: 17 | @for dir in *; do \ 18 | if [ -f $$dir/Makefile ]; then \ 19 | echo "processing $$dir/"; \ 20 | $(MAKE) -C $$dir || exit 1; \ 21 | fi; \ 22 | done; 23 | 24 | genpass: deps genpass.o 25 | $(CC) -o genpass genpass.o arg_parser/arg_parser.o config/ini.o \ 26 | readpass/readpass.o encoders/*.o \ 27 | $(CFLAGS_EXTRA) -L./libscrypt/ -lscrypt 28 | $(CC) -static -o genpass-static genpass.o \ 29 | arg_parser/arg_parser.o config/ini.o readpass/readpass.o \ 30 | encoders/*.o \ 31 | $(CFLAGS_EXTRA) -L./libscrypt/ -lscrypt 32 | 33 | dist: all 34 | strip genpass genpass-static 35 | 36 | clean: 37 | @for dir in *; do \ 38 | if [ -f $$dir/Makefile ]; then \ 39 | echo "processing $$dir/"; \ 40 | $(MAKE) clean -C $$dir; \ 41 | fi; \ 42 | done; 43 | rm -f *.o genpass genpass-static 44 | rm -rf test/*.tmp 45 | 46 | test: all 47 | xvfb-run sh test/test.sh 48 | 49 | .PHONY: test 50 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | ## genpass 2 | 3 | [![Build Status](https://travis-ci.org/javier-lopez/genpass.png?branch=master)](https://travis-ci.org/javier-lopez/genpass) 4 | 5 | A stateless password generator. 6 | 7 |

8 | genpass 9 |

10 | 11 | ## Quick start 12 | 13 | ### Ubuntu based systems (LTS versions) 14 | 15 | 1. Set up the minos archive: 16 | 17 | ``` 18 | $ sudo add-apt-repository ppa:minos-archive/main 19 | ``` 20 | 21 | 2. Install: 22 | 23 | ``` 24 | $ sudo apt-get update && sudo apt-get install genpass 25 | ``` 26 | 27 | ### Other Linux distributions 28 | 29 | 1. Compile from source 30 | 31 | ``` 32 | $ make 33 | ``` 34 | 35 | 2. Copy `genpass` or `genpass-static` to a system wide location or use directly 36 | 37 | ``` 38 | $ cp genpass genpass-static /usr/local/bin/ 39 | ``` 40 | 41 | **Only for the dynamic genpass binary** 42 | 43 | 3. Install `libscrypt` from your prefered source. On Ubuntu/Debian it's named `libscrypt0` 44 | 45 | ``` 46 | $ sudo apt-get install libscrypt0 47 | ``` 48 | 49 | 3. Or use the bundled `./libscrypt/libscrypt.so.0` one. 50 | 51 | ``` 52 | $ sudo cp ./libscrypt/libscrypt.so.0 /usr/lib/ 53 | ``` 54 | 55 | Linux static binaries can also be retrieved with [static-get](https://github.com/minos-org/minos-static), for x86|amd64 platforms 56 | 57 | 1. Fetch static binaries 58 | 59 | ``` 60 | $ sh <(wget -qO- s.minos.io/s) -x genpass 61 | ``` 62 | 63 | 2. Copy `genpass` or `genpass-static` to a system wide location or use directly 64 | 65 | ``` 66 | $ cp genpass-*/genpass genpass-*/genpass-static /usr/local/bin/ 67 | ``` 68 | 69 | ## Usage 70 | 71 | First time usage: 72 | 73 | $ genpass 74 | Name: Guy Mann 75 | Site: github.com 76 | Master password: passwd #it won't be shown 77 | 4?Hs>Jf#r*X9>7rznOS?4L=ysh&X>M/?8F>?^P(hW 78 | 79 | This will prompt you for your name, site and master password. The first time it's executed it will take a relative long time (a couple of minutes) to get back. It'll create a cache key and will save it to `~/.genpass-cache`, then it will combine it with the master password and the site string to generate the final password. The cache key file should be guarded with moderate caution. If it gets leaked possible attackers may have an easier time guessing your master password (although it still will be considerably harder than average brute force attacks). 80 | 81 | General use 82 | 83 | $ genpass [options] [site] 84 | 85 | Because `genpass` hashes your (master password + url + name), you can use it to retrieve (regenerate) your passwords on any computer where it's installed. 86 | 87 | It's recommended to defined cost, length and other parameters explicitly, default values will change between versions as computers get updated on CPU/RAM. 88 | 89 | Default values for version `2016.10.30` are: 90 | 91 | Parameter | Value 92 | --------------------- | ------------- 93 | Cache cost (Scrypt N) | 2^20 94 | Cost (Scrypt N) | 2^14 95 | Scrypt r | 8 bits 96 | Scrypt p | 16 bits 97 | Key length | 32 bytes, 256 bits 98 | Encoding | z85 99 | 100 | Past default values are listed in the [defaults.md](https://github.com/javier-lopez/genpass/blob/master/defaults.md) file. 101 | 102 | In addition, you can setup a configuration file using the `--config` option. An example is provided here: [genpass-example.ini](https://github.com/javier-lopez/genpass/blob/master/config/genpass-example.ini). 103 | 104 | ## Scheme 105 | 106 | The [scheme](https://www.cs.utexas.edu/~bwaters/publications/papers/www2005.pdf) uses two levels of hash computations (although with the -1 parameter it can use only one). The first level is executed once when a user begins to use a new machine for the first time. This computation is parameterized to take a relatively long time (around 60 seconds on this implementation) and its result are cached for future password calculations by the same user. The next level is used to compute site-specific passwords. It takes as input the calculation produced from the first level as well as the name of the site or account for which the user is interested, the computation time is parameterized to be fast (around .1 seconds in our implementation). 107 | 108 | Typical attackers (with access to a generated password but without a master password nor a cache key) will need to spend 60.1 seconds on average per try and will have little room for parallelization, legitimate users on the other hand will require 0.1s after the initial cache key is calculated. This way the scheme strives for the best balance between security and usability. 109 | 110 | The algorithm has been updated to use a key derivation function specifically designed to be computationally intensive on CPU, RAM and custom hardware attacks, [scrypt](http://www.tarsnap.com/scrypt/scrypt.pdf). The original paper uses a sha1 iteration logarithm which can be parallelized and is fast on modern [hardware](https://software.intel.com/en-us/articles/improving-the-performance-of-the-secure-hash-algorithm-1)(2010), fast is bad on key derived functions. 111 | -------------------------------------------------------------------------------- /arg_parser/Makefile: -------------------------------------------------------------------------------- 1 | CC?=gcc 2 | CFLAGS?=-O2 -Wall -g 3 | LDFLAGS?= 4 | CFLAGS_EXTRA?=-Wl,-rpath=. 5 | 6 | all: arg_parser_example 7 | 8 | OBJS= arg_parser.o 9 | 10 | arg_parser_example: arg_parser.o 11 | $(CC) -Wall -static -o arg_parser_example arg_parser_example.c arg_parser.o $(CFLAGS_EXTRA) -L. 12 | 13 | clean: 14 | rm -f *.o arg_parser_example 15 | -------------------------------------------------------------------------------- /arg_parser/arg_parser.c: -------------------------------------------------------------------------------- 1 | /* Arg_parser - POSIX/GNU command line argument parser. (C version) 2 | Copyright (C) 2006-2015 Antonio Diaz Diaz. 3 | 4 | This library is free software: you can redistribute it and/or modify 5 | it under the terms of the GNU General Public License as published by 6 | the Free Software Foundation, either version 2 of the License, or 7 | (at your option) any later version. 8 | 9 | This library is distributed in the hope that it will be useful, 10 | but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | GNU General Public License for more details. 13 | 14 | You should have received a copy of the GNU General Public License 15 | along with this library. If not, see . 16 | 17 | As a special exception, you may use this file as part of a free 18 | software library without restriction. Specifically, if other files 19 | instantiate templates or use macros or inline functions from this 20 | file, or you compile this file and link it with other files to 21 | produce an executable, this file does not by itself cause the 22 | resulting executable to be covered by the GNU General Public 23 | License. This exception does not however invalidate any other 24 | reasons why the executable file might be covered by the GNU General 25 | Public License. 26 | */ 27 | 28 | #include 29 | #include 30 | 31 | #include "arg_parser.h" 32 | 33 | 34 | /* assure at least a minimum size for buffer 'buf' */ 35 | static void * ap_resize_buffer( void * buf, const int min_size ) 36 | { 37 | if( buf ) buf = realloc( buf, min_size ); 38 | else buf = malloc( min_size ); 39 | return buf; 40 | } 41 | 42 | 43 | static char push_back_record( struct Arg_parser * const ap, 44 | const int code, const char * const argument ) 45 | { 46 | const int len = strlen( argument ); 47 | struct ap_Record * p; 48 | void * tmp = ap_resize_buffer( ap->data, 49 | ( ap->data_size + 1 ) * sizeof (struct ap_Record) ); 50 | if( !tmp ) return 0; 51 | ap->data = (struct ap_Record *)tmp; 52 | p = &(ap->data[ap->data_size]); 53 | p->code = code; 54 | p->argument = 0; 55 | tmp = ap_resize_buffer( p->argument, len + 1 ); 56 | if( !tmp ) return 0; 57 | p->argument = (char *)tmp; 58 | strncpy( p->argument, argument, len + 1 ); 59 | ++ap->data_size; 60 | return 1; 61 | } 62 | 63 | 64 | static char add_error( struct Arg_parser * const ap, const char * const msg ) 65 | { 66 | const int len = strlen( msg ); 67 | void * tmp = ap_resize_buffer( ap->error, ap->error_size + len + 1 ); 68 | if( !tmp ) return 0; 69 | ap->error = (char *)tmp; 70 | strncpy( ap->error + ap->error_size, msg, len + 1 ); 71 | ap->error_size += len; 72 | return 1; 73 | } 74 | 75 | 76 | static void free_data( struct Arg_parser * const ap ) 77 | { 78 | int i; 79 | for( i = 0; i < ap->data_size; ++i ) free( ap->data[i].argument ); 80 | if( ap->data ) { free( ap->data ); ap->data = 0; } 81 | ap->data_size = 0; 82 | } 83 | 84 | 85 | static char parse_long_option( struct Arg_parser * const ap, 86 | const char * const opt, const char * const arg, 87 | const struct ap_Option options[], 88 | int * const argindp ) 89 | { 90 | unsigned len; 91 | int index = -1, i; 92 | char exact = 0, ambig = 0; 93 | 94 | for( len = 0; opt[len+2] && opt[len+2] != '='; ++len ) ; 95 | 96 | /* Test all long options for either exact match or abbreviated matches. */ 97 | for( i = 0; options[i].code != 0; ++i ) 98 | if( options[i].name && strncmp( options[i].name, &opt[2], len ) == 0 ) 99 | { 100 | if( strlen( options[i].name ) == len ) /* Exact match found */ 101 | { index = i; exact = 1; break; } 102 | else if( index < 0 ) index = i; /* First nonexact match found */ 103 | else if( options[index].code != options[i].code || 104 | options[index].has_arg != options[i].has_arg ) 105 | ambig = 1; /* Second or later nonexact match found */ 106 | } 107 | 108 | if( ambig && !exact ) 109 | { 110 | add_error( ap, "option '" ); add_error( ap, opt ); 111 | add_error( ap, "' is ambiguous" ); 112 | return 1; 113 | } 114 | 115 | if( index < 0 ) /* nothing found */ 116 | { 117 | add_error( ap, "unrecognized option '" ); add_error( ap, opt ); 118 | add_error( ap, "'" ); 119 | return 1; 120 | } 121 | 122 | ++*argindp; 123 | 124 | if( opt[len+2] ) /* '--=' syntax */ 125 | { 126 | if( options[index].has_arg == ap_no ) 127 | { 128 | add_error( ap, "option '--" ); add_error( ap, options[index].name ); 129 | add_error( ap, "' doesn't allow an argument" ); 130 | return 1; 131 | } 132 | if( options[index].has_arg == ap_yes && !opt[len+3] ) 133 | { 134 | add_error( ap, "option '--" ); add_error( ap, options[index].name ); 135 | add_error( ap, "' requires an argument" ); 136 | return 1; 137 | } 138 | return push_back_record( ap, options[index].code, &opt[len+3] ); 139 | } 140 | 141 | if( options[index].has_arg == ap_yes ) 142 | { 143 | if( !arg || !arg[0] ) 144 | { 145 | add_error( ap, "option '--" ); add_error( ap, options[index].name ); 146 | add_error( ap, "' requires an argument" ); 147 | return 1; 148 | } 149 | ++*argindp; 150 | return push_back_record( ap, options[index].code, arg ); 151 | } 152 | 153 | return push_back_record( ap, options[index].code, "" ); 154 | } 155 | 156 | 157 | static char parse_short_option( struct Arg_parser * const ap, 158 | const char * const opt, const char * const arg, 159 | const struct ap_Option options[], 160 | int * const argindp ) 161 | { 162 | int cind = 1; /* character index in opt */ 163 | 164 | while( cind > 0 ) 165 | { 166 | int index = -1, i; 167 | const unsigned char code = opt[cind]; 168 | char code_str[2]; 169 | code_str[0] = code; code_str[1] = 0; 170 | 171 | if( code != 0 ) 172 | for( i = 0; options[i].code; ++i ) 173 | if( code == options[i].code ) 174 | { index = i; break; } 175 | 176 | if( index < 0 ) 177 | { 178 | add_error( ap, "invalid option -- '" ); add_error( ap, code_str ); 179 | add_error( ap, "'" ); 180 | return 1; 181 | } 182 | 183 | if( opt[++cind] == 0 ) { ++*argindp; cind = 0; } /* opt finished */ 184 | 185 | if( options[index].has_arg != ap_no && cind > 0 && opt[cind] ) 186 | { 187 | if( !push_back_record( ap, code, &opt[cind] ) ) return 0; 188 | ++*argindp; cind = 0; 189 | } 190 | else if( options[index].has_arg == ap_yes ) 191 | { 192 | if( !arg || !arg[0] ) 193 | { 194 | add_error( ap, "option '-" ); add_error( ap, code_str); 195 | add_error( ap, "' requires an argument" ); 196 | return 1; 197 | } 198 | ++*argindp; cind = 0; 199 | if( !push_back_record( ap, code, arg ) ) return 0; 200 | } 201 | else if( !push_back_record( ap, code, "" ) ) return 0; 202 | } 203 | return 1; 204 | } 205 | 206 | 207 | char ap_init( struct Arg_parser * const ap, 208 | const int argc, const char * const argv[], 209 | const struct ap_Option options[], const char in_order ) 210 | { 211 | const char ** non_options = 0; /* skipped non-options */ 212 | int non_options_size = 0; /* number of skipped non-options */ 213 | int argind = 1; /* index in argv */ 214 | int i; 215 | 216 | ap->data = 0; 217 | ap->error = 0; 218 | ap->data_size = 0; 219 | ap->error_size = 0; 220 | if( argc < 2 || !argv || !options ) return 1; 221 | 222 | while( argind < argc ) 223 | { 224 | const unsigned char ch1 = argv[argind][0]; 225 | const unsigned char ch2 = ch1 ? argv[argind][1] : 0; 226 | 227 | if( ch1 == '-' && ch2 ) /* we found an option */ 228 | { 229 | const char * const opt = argv[argind]; 230 | const char * const arg = ( argind + 1 < argc ) ? argv[argind+1] : 0; 231 | if( ch2 == '-' ) 232 | { 233 | if( !argv[argind][2] ) { ++argind; break; } /* we found "--" */ 234 | else if( !parse_long_option( ap, opt, arg, options, &argind ) ) return 0; 235 | } 236 | else if( !parse_short_option( ap, opt, arg, options, &argind ) ) return 0; 237 | if( ap->error ) break; 238 | } 239 | else 240 | { 241 | if( !in_order ) 242 | { 243 | void * tmp = ap_resize_buffer( non_options, 244 | ( non_options_size + 1 ) * sizeof *non_options ); 245 | if( !tmp ) return 0; 246 | non_options = (const char **)tmp; 247 | non_options[non_options_size++] = argv[argind++]; 248 | } 249 | else if( !push_back_record( ap, 0, argv[argind++] ) ) return 0; 250 | } 251 | } 252 | if( ap->error ) free_data( ap ); 253 | else 254 | { 255 | for( i = 0; i < non_options_size; ++i ) 256 | if( !push_back_record( ap, 0, non_options[i] ) ) return 0; 257 | while( argind < argc ) 258 | if( !push_back_record( ap, 0, argv[argind++] ) ) return 0; 259 | } 260 | if( non_options ) free( non_options ); 261 | return 1; 262 | } 263 | 264 | 265 | void ap_free( struct Arg_parser * const ap ) 266 | { 267 | free_data( ap ); 268 | if( ap->error ) { free( ap->error ); ap->error = 0; } 269 | ap->error_size = 0; 270 | } 271 | 272 | 273 | const char * ap_error( const struct Arg_parser * const ap ) 274 | { return ap->error; } 275 | 276 | 277 | int ap_arguments( const struct Arg_parser * const ap ) 278 | { return ap->data_size; } 279 | 280 | 281 | int ap_code( const struct Arg_parser * const ap, const int i ) 282 | { 283 | if( i >= 0 && i < ap_arguments( ap ) ) return ap->data[i].code; 284 | else return 0; 285 | } 286 | 287 | 288 | const char * ap_argument( const struct Arg_parser * const ap, const int i ) 289 | { 290 | if( i >= 0 && i < ap_arguments( ap ) ) return ap->data[i].argument; 291 | else return ""; 292 | } 293 | -------------------------------------------------------------------------------- /arg_parser/arg_parser.h: -------------------------------------------------------------------------------- 1 | /* Arg_parser - POSIX/GNU command line argument parser. (C version) 2 | Copyright (C) 2006-2015 Antonio Diaz Diaz. 3 | 4 | This library is free software: you can redistribute it and/or modify 5 | it under the terms of the GNU General Public License as published by 6 | the Free Software Foundation, either version 2 of the License, or 7 | (at your option) any later version. 8 | 9 | This library is distributed in the hope that it will be useful, 10 | but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | GNU General Public License for more details. 13 | 14 | You should have received a copy of the GNU General Public License 15 | along with this library. If not, see . 16 | 17 | As a special exception, you may use this file as part of a free 18 | software library without restriction. Specifically, if other files 19 | instantiate templates or use macros or inline functions from this 20 | file, or you compile this file and link it with other files to 21 | produce an executable, this file does not by itself cause the 22 | resulting executable to be covered by the GNU General Public 23 | License. This exception does not however invalidate any other 24 | reasons why the executable file might be covered by the GNU General 25 | Public License. 26 | */ 27 | 28 | /* Arg_parser reads the arguments in 'argv' and creates a number of 29 | option codes, option arguments and non-option arguments. 30 | 31 | In case of error, 'ap_error' returns a non-null pointer to an error 32 | message. 33 | 34 | 'options' is an array of 'struct ap_Option' terminated by an element 35 | containing a code which is zero. A null name means a short-only 36 | option. A code value outside the unsigned char range means a 37 | long-only option. 38 | 39 | Arg_parser normally makes it appear as if all the option arguments 40 | were specified before all the non-option arguments for the purposes 41 | of parsing, even if the user of your program intermixed option and 42 | non-option arguments. If you want the arguments in the exact order 43 | the user typed them, call 'ap_init' with 'in_order' = true. 44 | 45 | The argument '--' terminates all options; any following arguments are 46 | treated as non-option arguments, even if they begin with a hyphen. 47 | 48 | The syntax for optional option arguments is '-' 49 | (without whitespace), or '--='. 50 | */ 51 | 52 | #ifdef __cplusplus 53 | extern "C" { 54 | #endif 55 | 56 | enum ap_Has_arg { ap_no, ap_yes, ap_maybe }; 57 | 58 | struct ap_Option 59 | { 60 | int code; /* Short option letter or code ( code != 0 ) */ 61 | const char * name; /* Long option name (maybe null) */ 62 | enum ap_Has_arg has_arg; 63 | }; 64 | 65 | 66 | struct ap_Record 67 | { 68 | int code; 69 | char * argument; 70 | }; 71 | 72 | 73 | struct Arg_parser 74 | { 75 | struct ap_Record * data; 76 | char * error; 77 | int data_size; 78 | int error_size; 79 | }; 80 | 81 | 82 | char ap_init( struct Arg_parser * const ap, 83 | const int argc, const char * const argv[], 84 | const struct ap_Option options[], const char in_order ); 85 | 86 | void ap_free( struct Arg_parser * const ap ); 87 | 88 | const char * ap_error( const struct Arg_parser * const ap ); 89 | 90 | /* The number of arguments parsed (may be different from argc) */ 91 | int ap_arguments( const struct Arg_parser * const ap ); 92 | 93 | /* If ap_code( i ) is 0, ap_argument( i ) is a non-option. 94 | Else ap_argument( i ) is the option's argument (or empty). */ 95 | int ap_code( const struct Arg_parser * const ap, const int i ); 96 | 97 | const char * ap_argument( const struct Arg_parser * const ap, const int i ); 98 | 99 | #ifdef __cplusplus 100 | } 101 | #endif 102 | -------------------------------------------------------------------------------- /arg_parser/arg_parser_example.c: -------------------------------------------------------------------------------- 1 | /* Exit status: 0 for a normal exit, 1 for environmental problems 2 | (file not found, invalid flags, I/O errors, etc), 2 to indicate a 3 | corrupt or invalid input file, 3 for an internal consistency error 4 | (eg, bug) which caused arg_parser to panic. 5 | */ 6 | 7 | #include 8 | #include 9 | #include 10 | 11 | #include "arg_parser.h" 12 | 13 | 14 | static const char * const Program_name = "Arg_parser"; 15 | static const char * const program_name = "arg_parser"; 16 | static const char * const program_year = "2015"; 17 | static const char * invocation_name = 0; 18 | 19 | 20 | void show_help( const char verbose ) 21 | { 22 | printf( "%s - POSIX/GNU command line argument parser. (C version)\n", Program_name ); 23 | printf( "See the source file 'cmain.c' to learn how to use %s in\n", Program_name ); 24 | printf( "your own programs.\n" 25 | "\nUsage: %s [options]\n", invocation_name ); 26 | printf( "\nOptions:\n" 27 | " -h, --help display this help and exit\n" 28 | " -V, --version output version information and exit\n" 29 | " -a, --append example of option with no argument\n" 30 | " -b, --block= example of option with required argument\n" 31 | " -c, --casual[=] example of option with optional argument\n" 32 | " -o example of short only option\n" 33 | " --orphan example of long only option\n" 34 | " -q, --quiet quiet operation\n" 35 | " -u, --uncaught example of intentional bug\n" 36 | " -v, --verbose verbose operation\n" ); 37 | if( verbose ) 38 | { 39 | printf( " -H, --hidden example of hidden option (shown with -v -h)\n" ); 40 | } 41 | printf( "\nReport bugs to arg-parser-bug@nongnu.org\n" 42 | "Arg_parser home page: http://www.nongnu.org/arg-parser/arg_parser.html\n" ); 43 | } 44 | 45 | 46 | void show_version() 47 | { 48 | printf( "%s \n", program_name ); 49 | printf( "Copyright (C) %s Antonio Diaz Diaz.\n", program_year ); 50 | printf( "License GPLv2+: GNU GPL version 2 or later \n" 51 | "This is free software: you are free to change and redistribute it.\n" 52 | "There is NO WARRANTY, to the extent permitted by law.\n" ); 53 | } 54 | 55 | 56 | void show_error( const char * const msg, const int errcode, const char help ) 57 | { 58 | if( msg && msg[0] ) 59 | { 60 | fprintf( stderr, "%s: %s", program_name, msg ); 61 | if( errcode > 0 ) 62 | fprintf( stderr, ": %s.", strerror( errcode ) ); 63 | fprintf( stderr, "\n" ); 64 | } 65 | if( help ) 66 | fprintf( stderr, "Try '%s --help' for more information.\n", 67 | invocation_name ); 68 | } 69 | 70 | 71 | void internal_error( const char * const msg ) 72 | { 73 | fprintf( stderr, "%s: internal error: %s\n", program_name, msg ); 74 | exit( 3 ); 75 | } 76 | 77 | 78 | const char * optname( const int code, const struct ap_Option options[] ) 79 | { 80 | static char buf[2] = "?"; 81 | int i; 82 | 83 | if( code != 0 ) 84 | for( i = 0; options[i].code; ++i ) 85 | if( code == options[i].code ) 86 | { if( options[i].name ) return options[i].name; else break; } 87 | if( code > 0 && code < 256 ) buf[0] = code; else buf[0] = '?'; 88 | return buf; 89 | } 90 | 91 | 92 | int main( const int argc, const char * const argv[] ) 93 | { 94 | char verbose = 0; 95 | const struct ap_Option options[] = 96 | { 97 | { 'a', "append", ap_no }, 98 | { 'b', "block", ap_yes }, 99 | { 'c', "casual", ap_maybe }, 100 | { 'h', "help", ap_no }, 101 | { 'H', "hidden", ap_no }, 102 | { 'o', 0, ap_yes }, 103 | { 'q', "quiet", ap_no }, 104 | { 'u', "uncaught", ap_no }, 105 | { 'v', "verbose", ap_no }, 106 | { 'V', "version", ap_no }, 107 | { 256, "orphan", ap_no }, 108 | { 0, 0, ap_no } }; 109 | 110 | struct Arg_parser parser; 111 | int argind; 112 | invocation_name = argv[0]; 113 | 114 | if( !ap_init( &parser, argc, argv, options, 0 ) ) 115 | { show_error( "Not enough memory.", 0, 0 ); return 1; } 116 | if( ap_error( &parser ) ) /* bad option */ 117 | { show_error( ap_error( &parser ), 0, 1 ); return 1; } 118 | 119 | for( argind = 0; argind < ap_arguments( &parser ); ++argind ) 120 | { 121 | const int code = ap_code( &parser, argind ); 122 | if( !code ) break; /* no more options */ 123 | switch( code ) 124 | { 125 | case 'a': break; /* example, do nothing */ 126 | case 'b': break; /* example, do nothing */ 127 | case 'c': break; /* example, do nothing */ 128 | case 'h': show_help( verbose ); return 0; 129 | case 'H': break; /* example, do nothing */ 130 | case 'o': break; /* example, do nothing */ 131 | case 'q': verbose = 0; break; 132 | /* case 'u': break; */ /* intentionally not caught */ 133 | case 'v': verbose = 1; break; 134 | case 'V': show_version(); return 0; 135 | case 256: break; /* example, do nothing */ 136 | default : internal_error( "uncaught option." ); 137 | } 138 | } /* end process options */ 139 | 140 | for( argind = 0; argind < ap_arguments( &parser ); ++argind ) 141 | { 142 | const int code = ap_code( &parser, argind ); 143 | const char * const arg = ap_argument( &parser, argind ); 144 | if( code ) /* option */ 145 | { 146 | const char * const name = optname( code, options ); 147 | if( !name[1] ) 148 | printf( "option '-%c'", name[0] ); 149 | else 150 | printf( "option '--%s'", name ); 151 | if( arg[0] ) 152 | printf( " with argument '%s'", arg ); 153 | } 154 | else /* non-option */ 155 | printf( "non-option argument '%s'", arg ); 156 | printf( "\n" ); 157 | } 158 | 159 | if( !ap_arguments( &parser ) ) printf( "Hello, world!\n" ); 160 | 161 | return 0; 162 | } 163 | -------------------------------------------------------------------------------- /config/Makefile: -------------------------------------------------------------------------------- 1 | CC?=gcc 2 | CFLAGS?=-O2 -Wall -g 3 | LDFLAGS?= 4 | CFLAGS_EXTRA?=-Wl,-rpath=. 5 | 6 | all: ini 7 | 8 | OBJS= ini.o 9 | 10 | ini: ini.o 11 | $(CC) -Wall -static -c ini.c $(CFLAGS_EXTRA) -L. 12 | 13 | clean: 14 | rm -f *.o 15 | -------------------------------------------------------------------------------- /config/genpass-example.ini: -------------------------------------------------------------------------------- 1 | ;This is a sample genpass configuration file. 2 | ; 3 | ;Even if the parameters are ommited then it will either take input 4 | ;from command line or default value will be assigned. (i.e it will 5 | ;proceed normally) 6 | 7 | [user] ; User Information 8 | name = "John Doe" ; name 9 | site = github.com ; site login 10 | 11 | [general] ; Genpass configuration 12 | cache_file = ~/.genpass-cache ; cache key file path 13 | keylen = 32 ; key length in bytes, "32" by default 14 | cache_cost = 20 ; cpu/memory cost for cache key, "20" by default 15 | cost = 14 ; cpu/memory cost for cache key, "14" by default 16 | scrypt_r = 8 ; block size, "8" by default (advanced) 17 | scrypt_p = 16 ; block size, "16" by default (advanced) 18 | encoding = z85 ; password encoding output, "z85" by default. 19 | ; supported values: dec|hex|base64|base91|z85|skey 20 | -------------------------------------------------------------------------------- /config/ini.c: -------------------------------------------------------------------------------- 1 | /* inih -- simple .INI file parser 2 | 3 | inih is released under the New BSD license (see LICENSE.txt). Go to the project 4 | home page for more info: 5 | 6 | https://github.com/benhoyt/inih 7 | 8 | */ 9 | 10 | #if defined(_MSC_VER) && !defined(_CRT_SECURE_NO_WARNINGS) 11 | #define _CRT_SECURE_NO_WARNINGS 12 | #endif 13 | 14 | #include 15 | #include 16 | #include 17 | 18 | #include "ini.h" 19 | 20 | #if !INI_USE_STACK 21 | #include 22 | #endif 23 | 24 | #define MAX_SECTION 50 25 | #define MAX_NAME 50 26 | 27 | /* Strip whitespace chars off end of given string, in place. Return s. */ 28 | static char* rstrip(char* s) 29 | { 30 | char* p = s + strlen(s); 31 | while (p > s && isspace((unsigned char)(*--p))) 32 | *p = '\0'; 33 | return s; 34 | } 35 | 36 | /* Return pointer to first non-whitespace char in given string. */ 37 | static char* lskip(const char* s) 38 | { 39 | while (*s && isspace((unsigned char)(*s))) 40 | s++; 41 | return (char*)s; 42 | } 43 | 44 | /* Return pointer to first char (of chars) or inline comment in given string, 45 | or pointer to null at end of string if neither found. Inline comment must 46 | be prefixed by a whitespace character to register as a comment. */ 47 | static char* find_chars_or_comment(const char* s, const char* chars) 48 | { 49 | #if INI_ALLOW_INLINE_COMMENTS 50 | int was_space = 0; 51 | while (*s && (!chars || !strchr(chars, *s)) && 52 | !(was_space && strchr(INI_INLINE_COMMENT_PREFIXES, *s))) { 53 | was_space = isspace((unsigned char)(*s)); 54 | s++; 55 | } 56 | #else 57 | while (*s && (!chars || !strchr(chars, *s))) { 58 | s++; 59 | } 60 | #endif 61 | return (char*)s; 62 | } 63 | 64 | /* Version of strncpy that ensures dest (size bytes) is null-terminated. */ 65 | static char* strncpy0(char* dest, const char* src, size_t size) 66 | { 67 | strncpy(dest, src, size); 68 | dest[size - 1] = '\0'; 69 | return dest; 70 | } 71 | 72 | /* See documentation in header file. */ 73 | int ini_parse_stream(ini_reader reader, void* stream, ini_handler handler, 74 | void* user) 75 | { 76 | /* Uses a fair bit of stack (use heap instead if you need to) */ 77 | #if INI_USE_STACK 78 | char line[INI_MAX_LINE]; 79 | #else 80 | char* line; 81 | #endif 82 | char section[MAX_SECTION] = ""; 83 | char prev_name[MAX_NAME] = ""; 84 | 85 | char* start; 86 | char* end; 87 | char* name; 88 | char* value; 89 | int lineno = 0; 90 | int error = 0; 91 | 92 | #if !INI_USE_STACK 93 | line = (char*)malloc(INI_MAX_LINE); 94 | if (!line) { 95 | return -2; 96 | } 97 | #endif 98 | 99 | /* Scan through stream line by line */ 100 | while (reader(line, INI_MAX_LINE, stream) != NULL) { 101 | lineno++; 102 | 103 | start = line; 104 | #if INI_ALLOW_BOM 105 | if (lineno == 1 && (unsigned char)start[0] == 0xEF && 106 | (unsigned char)start[1] == 0xBB && 107 | (unsigned char)start[2] == 0xBF) { 108 | start += 3; 109 | } 110 | #endif 111 | start = lskip(rstrip(start)); 112 | 113 | if (*start == ';' || *start == '#') { 114 | /* Per Python configparser, allow both ; and # comments at the 115 | start of a line */ 116 | } 117 | #if INI_ALLOW_MULTILINE 118 | else if (*prev_name && *start && start > line) { 119 | /* Non-blank line with leading whitespace, treat as continuation 120 | of previous name's value (as per Python configparser). */ 121 | if (!handler(user, section, prev_name, start) && !error) 122 | error = lineno; 123 | } 124 | #endif 125 | else if (*start == '[') { 126 | /* A "[section]" line */ 127 | end = find_chars_or_comment(start + 1, "]"); 128 | if (*end == ']') { 129 | *end = '\0'; 130 | strncpy0(section, start + 1, sizeof(section)); 131 | *prev_name = '\0'; 132 | } 133 | else if (!error) { 134 | /* No ']' found on section line */ 135 | error = lineno; 136 | } 137 | } 138 | else if (*start) { 139 | /* Not a comment, must be a name[=:]value pair */ 140 | end = find_chars_or_comment(start, "=:"); 141 | if (*end == '=' || *end == ':') { 142 | *end = '\0'; 143 | name = rstrip(start); 144 | value = lskip(end + 1); 145 | #if INI_ALLOW_INLINE_COMMENTS 146 | end = find_chars_or_comment(value, NULL); 147 | if (*end) 148 | *end = '\0'; 149 | #endif 150 | rstrip(value); 151 | 152 | /* Valid name[=:]value pair found, call handler */ 153 | strncpy0(prev_name, name, sizeof(prev_name)); 154 | if (!handler(user, section, name, value) && !error) 155 | error = lineno; 156 | } 157 | else if (!error) { 158 | /* No '=' or ':' found on name[=:]value line */ 159 | error = lineno; 160 | } 161 | } 162 | 163 | #if INI_STOP_ON_FIRST_ERROR 164 | if (error) 165 | break; 166 | #endif 167 | } 168 | 169 | #if !INI_USE_STACK 170 | free(line); 171 | #endif 172 | 173 | return error; 174 | } 175 | 176 | /* See documentation in header file. */ 177 | int ini_parse_file(FILE* file, ini_handler handler, void* user) 178 | { 179 | return ini_parse_stream((ini_reader)fgets, file, handler, user); 180 | } 181 | 182 | /* See documentation in header file. */ 183 | int ini_parse(const char* filename, ini_handler handler, void* user) 184 | { 185 | FILE* file; 186 | int error; 187 | 188 | file = fopen(filename, "r"); 189 | if (!file) 190 | return -1; 191 | error = ini_parse_file(file, handler, user); 192 | fclose(file); 193 | return error; 194 | } 195 | -------------------------------------------------------------------------------- /config/ini.h: -------------------------------------------------------------------------------- 1 | /* inih -- simple .INI file parser 2 | 3 | inih is released under the New BSD license (see LICENSE.txt). Go to the project 4 | home page for more info: 5 | 6 | https://github.com/benhoyt/inih 7 | 8 | */ 9 | 10 | #ifndef __INI_H__ 11 | #define __INI_H__ 12 | 13 | /* Make this header file easier to include in C++ code */ 14 | #ifdef __cplusplus 15 | extern "C" { 16 | #endif 17 | 18 | #include 19 | 20 | /* Typedef for prototype of handler function. */ 21 | typedef int (*ini_handler)(void* user, const char* section, 22 | const char* name, const char* value); 23 | 24 | /* Typedef for prototype of fgets-style reader function. */ 25 | typedef char* (*ini_reader)(char* str, int num, void* stream); 26 | 27 | /* Parse given INI-style file. May have [section]s, name=value pairs 28 | (whitespace stripped), and comments starting with ';' (semicolon). Section 29 | is "" if name=value pair parsed before any section heading. name:value 30 | pairs are also supported as a concession to Python's configparser. 31 | 32 | For each name=value pair parsed, call handler function with given user 33 | pointer as well as section, name, and value (data only valid for duration 34 | of handler call). Handler should return nonzero on success, zero on error. 35 | 36 | Returns 0 on success, line number of first error on parse error (doesn't 37 | stop on first error), -1 on file open error, or -2 on memory allocation 38 | error (only when INI_USE_STACK is zero). 39 | */ 40 | int ini_parse(const char* filename, ini_handler handler, void* user); 41 | 42 | /* Same as ini_parse(), but takes a FILE* instead of filename. This doesn't 43 | close the file when it's finished -- the caller must do that. */ 44 | int ini_parse_file(FILE* file, ini_handler handler, void* user); 45 | 46 | /* Same as ini_parse(), but takes an ini_reader function pointer instead of 47 | filename. Used for implementing custom or string-based I/O. */ 48 | int ini_parse_stream(ini_reader reader, void* stream, ini_handler handler, 49 | void* user); 50 | 51 | /* Nonzero to allow multi-line value parsing, in the style of Python's 52 | configparser. If allowed, ini_parse() will call the handler with the same 53 | name for each subsequent line parsed. */ 54 | #ifndef INI_ALLOW_MULTILINE 55 | #define INI_ALLOW_MULTILINE 1 56 | #endif 57 | 58 | /* Nonzero to allow a UTF-8 BOM sequence (0xEF 0xBB 0xBF) at the start of 59 | the file. See http://code.google.com/p/inih/issues/detail?id=21 */ 60 | #ifndef INI_ALLOW_BOM 61 | #define INI_ALLOW_BOM 1 62 | #endif 63 | 64 | /* Nonzero to allow inline comments (with valid inline comment characters 65 | specified by INI_INLINE_COMMENT_PREFIXES). Set to 0 to turn off and match 66 | Python 3.2+ configparser behaviour. */ 67 | #ifndef INI_ALLOW_INLINE_COMMENTS 68 | #define INI_ALLOW_INLINE_COMMENTS 1 69 | #endif 70 | #ifndef INI_INLINE_COMMENT_PREFIXES 71 | #define INI_INLINE_COMMENT_PREFIXES ";" 72 | #endif 73 | 74 | /* Nonzero to use stack, zero to use heap (malloc/free). */ 75 | #ifndef INI_USE_STACK 76 | #define INI_USE_STACK 1 77 | #endif 78 | 79 | /* Stop parsing on first error (default is to keep parsing). */ 80 | #ifndef INI_STOP_ON_FIRST_ERROR 81 | #define INI_STOP_ON_FIRST_ERROR 0 82 | #endif 83 | 84 | /* Maximum line length for any line in INI file. */ 85 | #ifndef INI_MAX_LINE 86 | #define INI_MAX_LINE 200 87 | #endif 88 | 89 | #ifdef __cplusplus 90 | } 91 | #endif 92 | 93 | #endif /* __INI_H__ */ 94 | -------------------------------------------------------------------------------- /defaults.md: -------------------------------------------------------------------------------- 1 | Default values for version `2016.10.30`: 2 | ---------------------------------------- 3 | 4 | Parameter | Value 5 | --------------------- | ------------- 6 | Cache cost (Scrypt N) | 2^20 7 | Cost (Scrypt N) | 2^14 8 | Scrypt r | 8 bits 9 | Scrypt p | 16 bits 10 | Key length | 32 bytes, 256 bits 11 | Encoding | z85 12 | 13 | ####IMPORTANT 14 | Due to bug https://github.com/javier-lopez/genpass/issues/2 passwords generated with older versions than `2016.10.30` will require to be updated them. 15 | 16 | Default values for version `2016.05.04`: 17 | ---------------------------------------- 18 | 19 | Parameter | Value 20 | --------------------- | ------------- 21 | Cache cost (Scrypt N) | 2^20 22 | Cost (Scrypt N) | 2^14 23 | Scrypt r | 8 bits 24 | Scrypt p | 16 bits 25 | Key length | 32 bytes, 256 bits 26 | Encoding | z85 27 | 28 | Default values for version `2016.01.01`: 29 | ---------------------------------------- 30 | 31 | Parameter | Value 32 | --------------------- | ------------- 33 | Cache cost (Scrypt N) | 2^20 34 | Cost (Scrypt N) | 2^10 35 | Scrypt r | 8 bits 36 | Scrypt p | 16 bits 37 | Key length | 32 bytes, 256 bits 38 | Encoding | z85 39 | -------------------------------------------------------------------------------- /encoders/Makefile: -------------------------------------------------------------------------------- 1 | all: *.c 2 | $(CC) $(LDFLAGS) -I. -I../libscrypt/ -c $^ 3 | 4 | clean: 5 | rm *.o -------------------------------------------------------------------------------- /encoders/b10.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | 8 | #include "crypto_scrypt-hexconvert.h" 9 | 10 | int libscrypt_b10_encode(src, srclength, target, targsize) 11 | unsigned char const *src; 12 | size_t srclength; 13 | char *target; 14 | size_t targsize; 15 | { 16 | size_t i; 17 | int len = 0; 18 | 19 | if (!src || srclength < 1 || targsize < (srclength * 2 + 1)) 20 | return -1; 21 | 22 | memset(target, 0, targsize); 23 | 24 | for(i=0; i<=(srclength-1); i++) 25 | { 26 | /* snprintf(target, srclength,"%s...", target....) has undefined results 27 | * and can't be used. Using offests like this makes snprintf 28 | * nontrivial. we therefore have use inescure sprintf() and 29 | * lengths checked elsewhere (start of function) */ 30 | /*@ -bufferoverflowhigh @*/ 31 | len += sprintf(target+len, "%02u", (unsigned int) src[i]); 32 | } 33 | 34 | return 0; 35 | 36 | /*if (libscrypt_hex_encode(src, srclength, target, targsize) == -1) return -1;*/ 37 | /*char *p;*/ 38 | /*errno = 0;*/ 39 | /*unsigned long int b10 = strtoul(target,&p,16);*/ 40 | 41 | /*if (p == target) //no digits found*/ 42 | /*return -1;*/ 43 | /*else if ((b10 == LONG_MIN || b10 == ULONG_MAX) && errno == ERANGE)*/ 44 | /*//value out of range*/ 45 | /*return -1;*/ 46 | /*else*/ 47 | /*snprintf(target, targsize, "%ld", b10);*/ 48 | 49 | /*return 0;*/ 50 | } 51 | -------------------------------------------------------------------------------- /encoders/b10.h: -------------------------------------------------------------------------------- 1 | int libscrypt_b10_encode(unsigned char const *src, size_t srclength, 2 | /*@out@*/ char *target, size_t targetsize); 3 | -------------------------------------------------------------------------------- /encoders/b64.c: -------------------------------------------------------------------------------- 1 | /*Base64 encode/decode functions from OpenBSD (src/lib/libc/net/base64.c).*/ 2 | 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | 9 | #include "b64.h" 10 | 11 | static const char Base64Compliant[] = 12 | "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"; 13 | static const char Pad64Compliant = '='; 14 | 15 | static const char Base64[] = 16 | "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789$_"; 17 | static const char Pad64 = '\0'; 18 | 19 | /* (From RFC1521 and draft-ietf-dnssec-secext-03.txt) 20 | The following encoding technique is taken from RFC 1521 by Borenstein 21 | and Freed. It is reproduced here in a slightly edited form for 22 | convenience. 23 | 24 | A 65-character subset of US-ASCII is used, enabling 6 bits to be 25 | represented per printable character. (The extra 65th character, "=", 26 | is used to signify a special processing function.) 27 | 28 | The encoding process represents 24-bit groups of input bits as output 29 | strings of 4 encoded characters. Proceeding from left to right, a 30 | 24-bit input group is formed by concatenating 3 8-bit input groups. 31 | These 24 bits are then treated as 4 concatenated 6-bit groups, each 32 | of which is translated into a single digit in the base64 alphabet. 33 | 34 | Each 6-bit group is used as an index into an array of 64 printable 35 | characters. The character referenced by the index is placed in the 36 | output string. 37 | 38 | Table 1: The Base64 Alphabet 39 | 40 | Value Encoding Value Encoding Value Encoding Value Encoding 41 | 0 A 17 R 34 i 51 z 42 | 1 B 18 S 35 j 52 0 43 | 2 C 19 T 36 k 53 1 44 | 3 D 20 U 37 l 54 2 45 | 4 E 21 V 38 m 55 3 46 | 5 F 22 W 39 n 56 4 47 | 6 G 23 X 40 o 57 5 48 | 7 H 24 Y 41 p 58 6 49 | 8 I 25 Z 42 q 59 7 50 | 9 J 26 a 43 r 60 8 51 | 10 K 27 b 44 s 61 9 52 | 11 L 28 c 45 t 62 + 53 | 12 M 29 d 46 u 63 / 54 | 13 N 30 e 47 v 55 | 14 O 31 f 48 w (pad) = 56 | 15 P 32 g 49 x 57 | 16 Q 33 h 50 y 58 | 59 | Special processing is performed if fewer than 24 bits are available 60 | at the end of the data being encoded. A full encoding quantum is 61 | always completed at the end of a quantity. When fewer than 24 input 62 | bits are available in an input group, zero bits are added (on the 63 | right) to form an integral number of 6-bit groups. Padding at the 64 | end of the data is performed using the '=' character. 65 | 66 | Since all base64 input is an integral number of octets, only the 67 | ------------------------------------------------- 68 | following cases can arise: 69 | 70 | (1) the final quantum of encoding input is an integral 71 | multiple of 24 bits; here, the final unit of encoded 72 | output will be an integral multiple of 4 characters 73 | with no "=" padding, 74 | (2) the final quantum of encoding input is exactly 8 bits; 75 | here, the final unit of encoded output will be two 76 | characters followed by two "=" padding characters, or 77 | (3) the final quantum of encoding input is exactly 16 bits; 78 | here, the final unit of encoded output will be three 79 | characters followed by one "=" padding character. 80 | */ 81 | 82 | int 83 | libscrypt_b64_encode(src, srclength, target, targsize) 84 | unsigned char const *src; 85 | size_t srclength; 86 | char *target; 87 | size_t targsize; 88 | { 89 | size_t datalength = 0; 90 | unsigned char input[3]; 91 | unsigned char output[4]; 92 | unsigned int i; 93 | 94 | memset(target, 0, targsize); 95 | 96 | while (2 < srclength) { 97 | input[0] = *src++; 98 | input[1] = *src++; 99 | input[2] = *src++; 100 | srclength -= 3; 101 | 102 | output[0] = input[0] >> 2; 103 | output[1] = ((input[0] & 0x03) << 4) + (input[1] >> 4); 104 | output[2] = ((input[1] & 0x0f) << 2) + (input[2] >> 6); 105 | output[3] = input[2] & 0x3f; 106 | 107 | if (datalength + 4 > targsize) 108 | return (-1); 109 | target[datalength++] = Base64[output[0]]; 110 | target[datalength++] = Base64[output[1]]; 111 | target[datalength++] = Base64[output[2]]; 112 | target[datalength++] = Base64[output[3]]; 113 | } 114 | 115 | /* Now we worry about padding. */ 116 | if (0 != srclength) { 117 | /* Get what's left. */ 118 | input[0] = input[1] = input[2] = '\0'; 119 | for (i = 0; i < srclength; i++) 120 | input[i] = *src++; 121 | 122 | output[0] = input[0] >> 2; 123 | output[1] = ((input[0] & 0x03) << 4) + (input[1] >> 4); 124 | output[2] = ((input[1] & 0x0f) << 2) + (input[2] >> 6); 125 | 126 | if (datalength + 4 > targsize) 127 | return (-1); 128 | target[datalength++] = Base64[output[0]]; 129 | target[datalength++] = Base64[output[1]]; 130 | if (srclength == 1) 131 | target[datalength++] = Pad64; 132 | else 133 | target[datalength++] = Base64[output[2]]; 134 | target[datalength++] = Pad64; 135 | } 136 | if (datalength >= targsize) 137 | return (-1); 138 | target[datalength] = '\0'; /* Returned value doesn't count \0. */ 139 | return (int)(datalength); 140 | } 141 | 142 | int 143 | libscrypt_b64_encode_compliant(src, srclength, target, targsize) 144 | unsigned char const *src; 145 | size_t srclength; 146 | char *target; 147 | size_t targsize; 148 | { 149 | size_t datalength = 0; 150 | unsigned char input[3]; 151 | unsigned char output[4]; 152 | unsigned int i; 153 | 154 | memset(target, 0, targsize); 155 | 156 | while (2 < srclength) { 157 | input[0] = *src++; 158 | input[1] = *src++; 159 | input[2] = *src++; 160 | srclength -= 3; 161 | 162 | output[0] = input[0] >> 2; 163 | output[1] = ((input[0] & 0x03) << 4) + (input[1] >> 4); 164 | output[2] = ((input[1] & 0x0f) << 2) + (input[2] >> 6); 165 | output[3] = input[2] & 0x3f; 166 | 167 | if (datalength + 4 > targsize) 168 | return (-1); 169 | target[datalength++] = Base64Compliant[output[0]]; 170 | target[datalength++] = Base64Compliant[output[1]]; 171 | target[datalength++] = Base64Compliant[output[2]]; 172 | target[datalength++] = Base64Compliant[output[3]]; 173 | } 174 | 175 | /* Now we worry about padding. */ 176 | if (0 != srclength) { 177 | /* Get what's left. */ 178 | input[0] = input[1] = input[2] = '\0'; 179 | for (i = 0; i < srclength; i++) 180 | input[i] = *src++; 181 | 182 | output[0] = input[0] >> 2; 183 | output[1] = ((input[0] & 0x03) << 4) + (input[1] >> 4); 184 | output[2] = ((input[1] & 0x0f) << 2) + (input[2] >> 6); 185 | 186 | if (datalength + 4 > targsize) 187 | return (-1); 188 | target[datalength++] = Base64Compliant[output[0]]; 189 | target[datalength++] = Base64Compliant[output[1]]; 190 | if (srclength == 1) 191 | target[datalength++] = Pad64Compliant; 192 | else 193 | target[datalength++] = Base64Compliant[output[2]]; 194 | target[datalength++] = Pad64Compliant; 195 | } 196 | if (datalength >= targsize) 197 | return (-1); 198 | target[datalength] = '\0'; /* Returned value doesn't count \0. */ 199 | return (int)(datalength); 200 | } 201 | 202 | /* skips all whitespace anywhere. 203 | converts characters, four at a time, starting at (or after) 204 | src from base - 64 numbers into three 8 bit bytes in the target area. 205 | it returns the number of data bytes stored at the target, or -1 on error. 206 | */ 207 | 208 | int 209 | libscrypt_b64_decode_compliant(src, target, targsize) 210 | char const *src; 211 | unsigned char *target; 212 | size_t targsize; 213 | { 214 | int state, ch; 215 | unsigned int tarindex; 216 | unsigned char nextbyte; 217 | char *pos; 218 | 219 | state = 0; 220 | tarindex = 0; 221 | 222 | while ((ch = (unsigned char)*src++) != '\0') { 223 | if (isspace(ch)) /* Skip whitespace anywhere. */ 224 | continue; 225 | 226 | if (ch == Pad64Compliant) 227 | break; 228 | 229 | pos = strchr(Base64Compliant, ch); 230 | if (pos == 0) /* A non-base64 character. */ 231 | return (-1); 232 | 233 | switch (state) { 234 | case 0: 235 | if (target) { 236 | if (tarindex >= targsize) 237 | return (-1); 238 | target[tarindex] = (pos - Base64Compliant) << 2; 239 | } 240 | state = 1; 241 | break; 242 | case 1: 243 | if (target) { 244 | if (tarindex >= targsize) 245 | return (-1); 246 | target[tarindex] |= (pos - Base64Compliant) >> 4; 247 | nextbyte = ((pos - Base64Compliant) & 0x0f) << 4; 248 | if (tarindex + 1 < targsize) 249 | target[tarindex+1] = nextbyte; 250 | else if (nextbyte) 251 | return (-1); 252 | } 253 | tarindex++; 254 | state = 2; 255 | break; 256 | case 2: 257 | if (target) { 258 | if (tarindex >= targsize) 259 | return (-1); 260 | target[tarindex] |= (pos - Base64Compliant) >> 2; 261 | nextbyte = ((pos - Base64Compliant) & 0x03) << 6; 262 | if (tarindex + 1 < targsize) 263 | target[tarindex+1] = nextbyte; 264 | else if (nextbyte) 265 | return (-1); 266 | } 267 | tarindex++; 268 | state = 3; 269 | break; 270 | case 3: 271 | if (target) { 272 | if (tarindex >= targsize) 273 | return (-1); 274 | target[tarindex] |= (pos - Base64Compliant); 275 | } 276 | tarindex++; 277 | state = 0; 278 | break; 279 | } 280 | } 281 | 282 | /* 283 | * We are done decoding Base-64 chars. Let's see if we ended 284 | * on a byte boundary, and/or with erroneous trailing characters. 285 | */ 286 | 287 | if (ch == Pad64Compliant) { /* We got a pad char. */ 288 | ch = (unsigned char)*src++; /* Skip it, get next. */ 289 | switch (state) { 290 | case 0: /* Invalid = in first position */ 291 | case 1: /* Invalid = in second position */ 292 | return (-1); 293 | 294 | case 2: /* Valid, means one byte of info */ 295 | /* Skip any number of spaces. */ 296 | for (; ch != '\0'; ch = (unsigned char)*src++) 297 | if (!isspace(ch)) 298 | break; 299 | /* Make sure there is another trailing = sign. */ 300 | if (ch != Pad64Compliant) 301 | return (-1); 302 | ch = (unsigned char)*src++; /* Skip the = */ 303 | /* Fall through to "single trailing =" case. */ 304 | /* FALLTHROUGH */ 305 | 306 | case 3: /* Valid, means two bytes of info */ 307 | /* 308 | * We know this char is an =. Is there anything but 309 | * whitespace after it? 310 | */ 311 | for (; ch != '\0'; ch = (unsigned char)*src++) 312 | if (!isspace(ch)) 313 | return (-1); 314 | 315 | /* 316 | * Now make sure for cases 2 and 3 that the "extra" 317 | * bits that slopped past the last full byte were 318 | * zeros. If we don't check them, they become a 319 | * subliminal channel. 320 | */ 321 | if (target && tarindex < targsize && 322 | target[tarindex] != 0) 323 | return (-1); 324 | } 325 | } else { 326 | /* 327 | * We ended by seeing the end of the string. Make sure we 328 | * have no partial bytes lying around. 329 | */ 330 | if (state != 0) 331 | return (-1); 332 | } 333 | 334 | return (tarindex); 335 | } 336 | -------------------------------------------------------------------------------- /encoders/b64.h: -------------------------------------------------------------------------------- 1 | /* BASE64 libraries used internally - should not need to be packaged */ 2 | #include 3 | #define b64_encode_len(A) ((A+2)/3 * 4 + 1) 4 | #define b64_decode_len(A) (A / 4 * 3 + 2) 5 | 6 | //modified version, $_ instead of +/ and without '=' padding, optimized 7 | //for generating passwords 8 | int libscrypt_b64_encode(unsigned char const *src, size_t srclength, 9 | /*@out@*/ char *target, size_t targetsize); 10 | 11 | int libscrypt_b64_encode_compliant(unsigned char const *src, size_t srclength, 12 | /*@out@*/ char *target, size_t targetsize); 13 | int libscrypt_b64_decode_compliant(char const *src, 14 | /*@out@*/ unsigned char *target, size_t targetsize); 15 | -------------------------------------------------------------------------------- /encoders/base16.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | 6 | /* The hexconvert function is only used to test reference vectors against 7 | * known answers. The contents of this file are therefore a component 8 | * to assist with test harnesses only 9 | */ 10 | 11 | int libscrypt_hexconvert(const unsigned char * buf, size_t s, char *outbuf, size_t obs) 12 | { 13 | size_t i; 14 | int len = 0; 15 | 16 | if (!buf || s < 1 || obs < (s * 2 + 1)) 17 | return 0; 18 | 19 | memset(outbuf, 0, obs); 20 | 21 | for(i=0; i<=(s-1); i++) 22 | { 23 | /* snprintf(outbuf, s,"%s...", outbuf....) has undefined results 24 | * and can't be used. Using offests like this makes snprintf 25 | * nontrivial. we therefore have use inescure sprintf() and 26 | * lengths checked elsewhere (start of function) */ 27 | /*@ -bufferoverflowhigh @*/ 28 | len += sprintf(outbuf+len, "%02x", (unsigned int) buf[i]); 29 | } 30 | 31 | return 1; 32 | } 33 | 34 | int libscrypt_hex_encode(const unsigned char * buf, size_t s, char *outbuf, size_t obs) 35 | { 36 | return libscrypt_hexconvert(buf, s, outbuf, obs); 37 | } 38 | -------------------------------------------------------------------------------- /encoders/base16.h: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | /** 5 | * Converts a binary string to a hex representation of that string 6 | * outbuf must have size of at least buf * 2 + 1. 7 | */ 8 | int libscrypt_hexconvert(const unsigned char * buf, size_t s, char *outbuf, size_t obs); 9 | int libscrypt_hex_encode(const unsigned char * buf, size_t s, char *outbuf, size_t obs); 10 | -------------------------------------------------------------------------------- /encoders/base91.c: -------------------------------------------------------------------------------- 1 | /* 2 | * basE91 encoding/decoding routines 3 | * 4 | * Copyright (c) 2000-2006 Joachim Henke 5 | * All rights reserved. 6 | * 7 | * Redistribution and use in source and binary forms, with or without 8 | * modification, are permitted provided that the following conditions are met: 9 | * 10 | * - Redistributions of source code must retain the above copyright notice, 11 | * this list of conditions and the following disclaimer. 12 | * - Redistributions in binary form must reproduce the above copyright notice, 13 | * this list of conditions and the following disclaimer in the documentation 14 | * and/or other materials provided with the distribution. 15 | * - Neither the name of Joachim Henke nor the names of his contributors may 16 | * be used to endorse or promote products derived from this software without 17 | * specific prior written permission. 18 | * 19 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 20 | * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 21 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 22 | * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE 23 | * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 24 | * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 25 | * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 26 | * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 27 | * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 28 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 29 | * POSSIBILITY OF SUCH DAMAGE. 30 | */ 31 | 32 | #include "base91.h" 33 | 34 | const unsigned char enctab[91] = { 35 | 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 36 | 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z', 37 | 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 38 | 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z', 39 | '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '!', '#', '$', 40 | '%', '&', '(', ')', '*', '+', ',', '.', '/', ':', ';', '<', '=', 41 | '>', '?', '@', '[', ']', '^', '_', '`', '{', '|', '}', '~', '"' 42 | }; 43 | const unsigned char dectab[256] = { 44 | 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 45 | 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 46 | 91, 62, 90, 63, 64, 65, 66, 91, 67, 68, 69, 70, 71, 91, 72, 73, 47 | 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 74, 75, 76, 77, 78, 79, 48 | 80, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 49 | 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 81, 91, 82, 83, 84, 50 | 85, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 51 | 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 86, 87, 88, 89, 91, 52 | 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 53 | 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 54 | 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 55 | 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 56 | 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 57 | 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 58 | 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 59 | 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91 60 | }; 61 | 62 | void basE91_init(struct basE91 *b) 63 | { 64 | b->queue = 0; 65 | b->nbits = 0; 66 | b->val = -1; 67 | } 68 | 69 | size_t basE91_encode(struct basE91 *b, const void *i, size_t len, void *o) 70 | { 71 | const unsigned char *ib = i; 72 | unsigned char *ob = o; 73 | size_t n = 0; 74 | 75 | while (len--) { 76 | b->queue |= *ib++ << b->nbits; 77 | b->nbits += 8; 78 | if (b->nbits > 13) { /* enough bits in queue */ 79 | unsigned int val = b->queue & 8191; 80 | 81 | if (val > 88) { 82 | b->queue >>= 13; 83 | b->nbits -= 13; 84 | } else { /* we can take 14 bits */ 85 | val = b->queue & 16383; 86 | b->queue >>= 14; 87 | b->nbits -= 14; 88 | } 89 | ob[n++] = enctab[val % 91]; 90 | ob[n++] = enctab[val / 91]; 91 | } 92 | } 93 | 94 | return n; 95 | } 96 | 97 | /* process remaining bits from bit queue; write up to 2 bytes */ 98 | 99 | size_t basE91_encode_end(struct basE91 *b, void *o) 100 | { 101 | unsigned char *ob = o; 102 | size_t n = 0; 103 | 104 | if (b->nbits) { 105 | ob[n++] = enctab[b->queue % 91]; 106 | if (b->nbits > 7 || b->queue > 90) 107 | ob[n++] = enctab[b->queue / 91]; 108 | } 109 | b->queue = 0; 110 | b->nbits = 0; 111 | b->val = -1; 112 | 113 | return n; 114 | } 115 | 116 | size_t basE91_decode(struct basE91 *b, const void *i, size_t len, void *o) 117 | { 118 | const unsigned char *ib = i; 119 | unsigned char *ob = o; 120 | size_t n = 0; 121 | unsigned int d; 122 | 123 | while (len--) { 124 | d = dectab[*ib++]; 125 | if (d == 91) 126 | continue; /* ignore non-alphabet chars */ 127 | if (b->val == -1) 128 | b->val = d; /* start next value */ 129 | else { 130 | b->val += d * 91; 131 | b->queue |= b->val << b->nbits; 132 | b->nbits += (b->val & 8191) > 88 ? 13 : 14; 133 | do { 134 | ob[n++] = b->queue; 135 | b->queue >>= 8; 136 | b->nbits -= 8; 137 | } while (b->nbits > 7); 138 | b->val = -1; /* mark value complete */ 139 | } 140 | } 141 | 142 | return n; 143 | } 144 | 145 | /* process remaining bits; write at most 1 byte */ 146 | 147 | size_t basE91_decode_end(struct basE91 *b, void *o) 148 | { 149 | unsigned char *ob = o; 150 | size_t n = 0; 151 | 152 | if (b->val != -1) 153 | ob[n++] = b->queue | b->val << b->nbits; 154 | b->queue = 0; 155 | b->nbits = 0; 156 | b->val = -1; 157 | 158 | return n; 159 | } 160 | -------------------------------------------------------------------------------- /encoders/base91.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2000-2006 Joachim Henke 3 | * 4 | * For conditions of distribution and use, see copyright notice in base91.c 5 | */ 6 | 7 | #ifndef BASE91_H 8 | #define BASE91_H 1 9 | 10 | #include 11 | 12 | struct basE91 { 13 | unsigned long queue; 14 | unsigned int nbits; 15 | int val; 16 | }; 17 | 18 | void basE91_init(struct basE91 *); 19 | 20 | size_t basE91_encode(struct basE91 *, const void *, size_t, void *); 21 | 22 | size_t basE91_encode_end(struct basE91 *, void *); 23 | 24 | size_t basE91_decode(struct basE91 *, const void *, size_t, void *); 25 | 26 | size_t basE91_decode_end(struct basE91 *, void *); 27 | 28 | #endif /* base91.h */ 29 | -------------------------------------------------------------------------------- /encoders/encoders.c: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | #include "encoders.h" 4 | 5 | int base91_glue_encode(unsigned char const *src, size_t srclength, 6 | void *target, size_t targsize) { 7 | static struct basE91 b91; 8 | size_t s; 9 | int total_size = 0; 10 | 11 | // zero the output buffer 12 | memset(target,'\0',targsize); 13 | 14 | // setup the base91 struct 15 | basE91_init(&b91); 16 | 17 | // encode most of it and keep the size 18 | s = basE91_encode(&b91, src, srclength, target); 19 | total_size += s; 20 | 21 | // pickup anything left and keep the size 22 | s = basE91_encode_end(&b91, (void*)(target+s)); 23 | total_size += s; 24 | 25 | // return the total size 26 | return total_size; 27 | } -------------------------------------------------------------------------------- /encoders/encoders.h: -------------------------------------------------------------------------------- 1 | #ifndef _ENCODERS_H_ 2 | #define _ENCODERS_H_ 3 | 4 | #include "b10.h" 5 | #include "b64.h" 6 | #include "base91.h" 7 | #include "base16.h" 8 | #include "skey.h" 9 | #include "z85.h" 10 | 11 | /* encode stuff using basE91 internal functions */ 12 | int base91_glue_encode(unsigned char const *src, size_t srclength, 13 | void *target, size_t targsize); 14 | 15 | #endif -------------------------------------------------------------------------------- /encoders/skey.h: -------------------------------------------------------------------------------- 1 | int libscrypt_skey_encode(unsigned char const *src, size_t srclength, 2 | /*@out@*/ char *target, size_t targetsize); 3 | -------------------------------------------------------------------------------- /encoders/z85.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2013 Stanislav Artemkin . 3 | * 4 | * Redistribution and use in source and binary forms, with or without 5 | * modification, are permitted provided that the following conditions are 6 | * met: 7 | * 8 | * * Redistributions of source code must retain the above copyright 9 | * notice, this list of conditions and the following disclaimer. 10 | * * Redistributions in binary form must reproduce the above 11 | * copyright notice, this list of conditions and the following disclaimer 12 | * in the documentation and/or other materials provided with the 13 | * distribution. 14 | * 15 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 16 | * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 17 | * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 18 | * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 19 | * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 20 | * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 21 | * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 22 | * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 23 | * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 24 | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 25 | * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 26 | * 27 | * Implementation of 32/Z85 specification (http://rfc.zeromq.org/spec:32/Z85) 28 | * Source repository: http://github.com/artemkin/z85 29 | */ 30 | 31 | #include 32 | #include 33 | #include 34 | 35 | #include "z85.h" 36 | 37 | typedef unsigned int uint32_t; 38 | typedef unsigned char byte; 39 | 40 | // make sure uint32_t is 32-bit 41 | typedef char Z85_uint32_t_static_assert[(sizeof(uint32_t) * CHAR_BIT == 32) * 2 - 1]; 42 | 43 | #define DIV85_MAGIC 3233857729ULL 44 | // make sure magic constant is 64-bit 45 | typedef char Z85_div85_magic_static_assert[(sizeof(DIV85_MAGIC) * CHAR_BIT == 64) * 2 - 1]; 46 | 47 | #define DIV85(number) ((uint32_t)((DIV85_MAGIC * number) >> 32) >> 6) 48 | 49 | static const char* base85 = 50 | { 51 | "0123456789" 52 | "abcdefghij" 53 | "klmnopqrst" 54 | "uvwxyzABCD" 55 | "EFGHIJKLMN" 56 | "OPQRSTUVWX" 57 | "YZ.-:+=^!/" 58 | "*?&<>()[]{" 59 | "}@%$#" 60 | }; 61 | 62 | static byte base256[] = 63 | { 64 | 0x00, 0x44, 0x00, 0x54, 0x53, 0x52, 0x48, 0x00, 65 | 0x4B, 0x4C, 0x46, 0x41, 0x00, 0x3F, 0x3E, 0x45, 66 | 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 67 | 0x08, 0x09, 0x40, 0x00, 0x49, 0x42, 0x4A, 0x47, 68 | 0x51, 0x24, 0x25, 0x26, 0x27, 0x28, 0x29, 0x2A, 69 | 0x2B, 0x2C, 0x2D, 0x2E, 0x2F, 0x30, 0x31, 0x32, 70 | 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x3A, 71 | 0x3B, 0x3C, 0x3D, 0x4D, 0x00, 0x4E, 0x43, 0x00, 72 | 0x00, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F, 0x10, 73 | 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 74 | 0x19, 0x1A, 0x1B, 0x1C, 0x1D, 0x1E, 0x1F, 0x20, 75 | 0x21, 0x22, 0x23, 0x4F, 0x00, 0x50, 0x00, 0x00 76 | }; 77 | 78 | int libscrypt_z85_encode(src, srclength, target, targsize) 79 | unsigned char const *src; 80 | size_t srclength; 81 | char *target; 82 | size_t targsize; 83 | { 84 | size_t datalength = 0; 85 | memset(target, 0, targsize); 86 | 87 | if (targsize < (Z85_encode_with_padding_bound(srclength) + 1)) { 88 | return (-1); //not enough space for output 89 | } 90 | 91 | //encode the input buffer, padding it if necessary 92 | datalength = Z85_encode_with_padding((const char * )src, target, srclength); 93 | if ( datalength == 0) 94 | return (-1); //something went wrong 95 | 96 | target[datalength] = '\0'; // write null terminating char 97 | return datalength; 98 | } 99 | 100 | int libscrypt_z85_decode(src, target, targsize) 101 | char const *src; 102 | unsigned char *target; 103 | size_t targsize; 104 | { 105 | size_t datalength = 0; 106 | if (targsize < (Z85_decode_with_padding_bound(src, strlen(src)) + 1)) { 107 | return (-1); //not enough space for output 108 | } 109 | 110 | //decode the input buffer, padding it if necessary 111 | datalength = Z85_decode_with_padding(src, (char *) target, strlen(src)); 112 | if ( datalength == 0) 113 | return (-1); //something went wrong 114 | 115 | target[datalength] = '\0'; // write null terminating char 116 | return datalength; 117 | } 118 | 119 | char* Z85_encode_unsafe(const char* source, const char* sourceEnd, char* dest) 120 | { 121 | byte* src = (byte*)source; 122 | byte* end = (byte*)sourceEnd; 123 | byte* dst = (byte*)dest; 124 | uint32_t value; 125 | uint32_t value2; 126 | 127 | for (; src != end; src += 4, dst += 5) 128 | { 129 | // unpack big-endian frame 130 | value = (src[0] << 24) | (src[1] << 16) | (src[2] << 8) | src[3]; 131 | 132 | value2 = DIV85(value); dst[4] = base85[value - value2 * 85]; value = value2; 133 | value2 = DIV85(value); dst[3] = base85[value - value2 * 85]; value = value2; 134 | value2 = DIV85(value); dst[2] = base85[value - value2 * 85]; value = value2; 135 | value2 = DIV85(value); dst[1] = base85[value - value2 * 85]; 136 | dst[0] = base85[value2]; 137 | } 138 | 139 | return (char*)dst; 140 | } 141 | 142 | char* Z85_decode_unsafe(const char* source, const char* sourceEnd, char* dest) 143 | { 144 | byte* src = (byte*)source; 145 | byte* end = (byte*)sourceEnd; 146 | byte* dst = (byte*)dest; 147 | uint32_t value; 148 | 149 | for (; src != end; src += 5, dst += 4) 150 | { 151 | value = base256[(src[0] - 32) & 127]; 152 | value = value * 85 + base256[(src[1] - 32) & 127]; 153 | value = value * 85 + base256[(src[2] - 32) & 127]; 154 | value = value * 85 + base256[(src[3] - 32) & 127]; 155 | value = value * 85 + base256[(src[4] - 32) & 127]; 156 | 157 | // pack big-endian frame 158 | dst[0] = value >> 24; 159 | dst[1] = (byte)(value >> 16); 160 | dst[2] = (byte)(value >> 8); 161 | dst[3] = (byte)(value); 162 | } 163 | 164 | return (char*)dst; 165 | } 166 | 167 | size_t Z85_encode_bound(size_t size) 168 | { 169 | return size * 5 / 4; 170 | } 171 | 172 | size_t Z85_decode_bound(size_t size) 173 | { 174 | return size * 4 / 5; 175 | } 176 | 177 | size_t Z85_encode(const char* source, char* dest, size_t inputSize) 178 | { 179 | if (!source || !dest || inputSize % 4) 180 | { 181 | assert(!"wrong source, destination or input size"); 182 | return 0; 183 | } 184 | 185 | return Z85_encode_unsafe(source, source + inputSize, dest) - dest; 186 | } 187 | 188 | size_t Z85_decode(const char* source, char* dest, size_t inputSize) 189 | { 190 | if (!source || !dest || inputSize % 5) 191 | { 192 | assert(!"wrong source, destination or input size"); 193 | return 0; 194 | } 195 | 196 | return Z85_decode_unsafe(source, source + inputSize, dest) - dest; 197 | } 198 | 199 | size_t Z85_encode_with_padding_bound(size_t size) 200 | { 201 | if (size == 0) return 0; 202 | size = Z85_encode_bound(size); 203 | return size + (5 - size % 5) % 5 + 1; 204 | } 205 | 206 | size_t Z85_decode_with_padding_bound(const char* source, size_t size) 207 | { 208 | if (size == 0 || !source || (byte)(source[0] - '0' - 1) > 3) return 0; 209 | return Z85_decode_bound(size - 1) - 4 + (source[0] - '0'); 210 | } 211 | 212 | size_t Z85_encode_with_padding(const char* source, char* dest, size_t inputSize) 213 | { 214 | size_t tailBytes = inputSize % 4; 215 | char tailBuf[4] = { 0 }; 216 | char* dst = dest; 217 | const char* end = source + inputSize - tailBytes; 218 | 219 | assert(source && dest); 220 | 221 | // zero length string is not padded 222 | if (!source || !dest || inputSize == 0) 223 | { 224 | return 0; 225 | } 226 | 227 | (dst++)[0] = (tailBytes == 0 ? '4' : '0' + (char)tailBytes); // write tail bytes count 228 | dst = Z85_encode_unsafe(source, end, dst); // write body 229 | 230 | // write tail 231 | switch (tailBytes) 232 | { 233 | case 3: 234 | tailBuf[2] = end[2]; 235 | case 2: 236 | tailBuf[1] = end[1]; 237 | case 1: 238 | tailBuf[0] = end[0]; 239 | dst = Z85_encode_unsafe(tailBuf, tailBuf + 4, dst); 240 | } 241 | 242 | return dst - dest; 243 | } 244 | 245 | size_t Z85_decode_with_padding(const char* source, char* dest, size_t inputSize) 246 | { 247 | char* dst = dest; 248 | size_t tailBytes; 249 | char tailBuf[4] = { 0 }; 250 | const char* end = source + inputSize; 251 | 252 | assert(source && dest && (inputSize == 0 || (inputSize - 1) % 5 == 0)); 253 | 254 | // zero length string is not padded 255 | if (!source || !dest || inputSize == 0 || (inputSize - 1) % 5) 256 | { 257 | return 0; 258 | } 259 | 260 | tailBytes = (source++)[0] - '0'; // possible values: 1, 2, 3 or 4 261 | if (tailBytes - 1 > 3) 262 | { 263 | assert(!"wrong tail bytes count"); 264 | return 0; 265 | } 266 | 267 | end -= 5; 268 | if (source != end) 269 | { 270 | // decode body 271 | dst = Z85_decode_unsafe(source, end, dst); 272 | } 273 | 274 | // decode last 5 bytes chunk 275 | Z85_decode_unsafe(end, end + 5, tailBuf); 276 | 277 | switch (tailBytes) 278 | { 279 | case 4: 280 | dst[3] = tailBuf[3]; 281 | case 3: 282 | dst[2] = tailBuf[2]; 283 | case 2: 284 | dst[1] = tailBuf[1]; 285 | case 1: 286 | dst[0] = tailBuf[0]; 287 | } 288 | 289 | return dst - dest + tailBytes; 290 | } 291 | -------------------------------------------------------------------------------- /encoders/z85.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2013 Stanislav Artemkin . 3 | * 4 | * Redistribution and use in source and binary forms, with or without 5 | * modification, are permitted provided that the following conditions are 6 | * met: 7 | * 8 | * * Redistributions of source code must retain the above copyright 9 | * notice, this list of conditions and the following disclaimer. 10 | * * Redistributions in binary form must reproduce the above 11 | * copyright notice, this list of conditions and the following disclaimer 12 | * in the documentation and/or other materials provided with the 13 | * distribution. 14 | * 15 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 16 | * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 17 | * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 18 | * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 19 | * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 20 | * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 21 | * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 22 | * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 23 | * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 24 | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 25 | * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 26 | * 27 | * Implementation of 32/Z85 specification (http://rfc.zeromq.org/spec:32/Z85) 28 | * Source repository: http://github.com/artemkin/z85 29 | */ 30 | 31 | #pragma once 32 | 33 | #include 34 | 35 | #if defined (__cplusplus) 36 | extern "C" { 37 | #endif 38 | 39 | /******************************************************************************* 40 | * libscrypt wrappers * 41 | *******************************************************************************/ 42 | int libscrypt_z85_encode(unsigned char const *src, size_t srclength, 43 | /*@out@*/ char *target, size_t targetsize); 44 | int libscrypt_z85_decode(char const *src, 45 | /*@out@*/ unsigned char *target, size_t targetsize); 46 | 47 | /******************************************************************************* 48 | * ZeroMQ Base-85 encoding/decoding functions with custom padding * 49 | *******************************************************************************/ 50 | 51 | /** 52 | * @brief Encodes 'inputSize' bytes from 'source' into 'dest'. 53 | * If 'inputSize' is not divisible by 4 with no remainder, 'source' is padded. 54 | * Destination buffer must be already allocated. Use Z85_encode_with_padding_bound() to 55 | * evaluate size of the destination buffer. 56 | * 57 | * @param source in, input buffer (binary string to be encoded) 58 | * @param dest out, destination buffer 59 | * @param inputSize in, number of bytes to be encoded 60 | * @return number of printable symbols written into 'dest' or 0 if something goes wrong 61 | */ 62 | size_t Z85_encode_with_padding(const char* source, char* dest, size_t inputSize); 63 | 64 | /** 65 | * @brief Decodes 'inputSize' printable symbols from 'source' into 'dest', 66 | * encoded with Z85_encode_with_padding(). 67 | * Destination buffer must be already allocated. Use Z85_decode_with_padding_bound() to 68 | * evaluate size of the destination buffer. 69 | * 70 | * @param source in, input buffer (printable string to be decoded) 71 | * @param dest out, destination buffer 72 | * @param inputSize in, number of symbols to be decoded 73 | * @return number of bytes written into 'dest' or 0 if something goes wrong 74 | */ 75 | size_t Z85_decode_with_padding(const char* source, char* dest, size_t inputSize); 76 | 77 | /** 78 | * @brief Evaluates a size of output buffer needed to encode 'size' bytes 79 | * into string of printable symbols using Z85_encode_with_padding(). 80 | * 81 | * @param size in, number of bytes to be encoded 82 | * @return minimal size of output buffer in bytes 83 | */ 84 | size_t Z85_encode_with_padding_bound(size_t size); 85 | 86 | /** 87 | * @brief Evaluates a size of output buffer needed to decode 'size' symbols 88 | * into binary string using Z85_decode_with_padding(). 89 | * 90 | * @param source in, input buffer (first symbol is read from 'source' to evaluate padding) 91 | * @param size in, number of symbols to be decoded 92 | * @return minimal size of output buffer in bytes 93 | */ 94 | size_t Z85_decode_with_padding_bound(const char* source, size_t size); 95 | 96 | 97 | 98 | /******************************************************************************* 99 | * ZeroMQ Base-85 encoding/decoding functions (specification compliant) * 100 | *******************************************************************************/ 101 | 102 | /** 103 | * @brief Encodes 'inputSize' bytes from 'source' into 'dest'. 104 | * If 'inputSize' is not divisible by 4 with no remainder, 0 is retured. 105 | * Destination buffer must be already allocated. Use Z85_encode_bound() to 106 | * evaluate size of the destination buffer. 107 | * 108 | * @param source in, input buffer (binary string to be encoded) 109 | * @param dest out, destination buffer 110 | * @param inputSize in, number of bytes to be encoded 111 | * @return number of printable symbols written into 'dest' or 0 if something goes wrong 112 | */ 113 | size_t Z85_encode(const char* source, char* dest, size_t inputSize); 114 | 115 | /** 116 | * @brief Decodes 'inputSize' printable symbols from 'source' into 'dest'. 117 | * If 'inputSize' is not divisible by 5 with no remainder, 0 is returned. 118 | * Destination buffer must be already allocated. Use Z85_decode_bound() to 119 | * evaluate size of the destination buffer. 120 | * 121 | * @param source in, input buffer (printable string to be decoded) 122 | * @param dest out, destination buffer 123 | * @param inputSize in, number of symbols to be decoded 124 | * @return number of bytes written into 'dest' or 0 if something goes wrong 125 | */ 126 | size_t Z85_decode(const char* source, char* dest, size_t inputSize); 127 | 128 | /** 129 | * @brief Evaluates a size of output buffer needed to encode 'size' bytes 130 | * into string of printable symbols using Z85_encode(). 131 | * 132 | * @param size in, number of bytes to be encoded 133 | * @return minimal size of output buffer in bytes 134 | */ 135 | size_t Z85_encode_bound(size_t size); 136 | 137 | /** 138 | * @brief Evaluates a size of output buffer needed to decode 'size' symbols 139 | * into binary string using Z85_decode(). 140 | * 141 | * @param size in, number of symbols to be decoded 142 | * @return minimal size of output buffer in bytes 143 | */ 144 | size_t Z85_decode_bound(size_t size); 145 | 146 | 147 | 148 | /******************************************************************************* 149 | * ZeroMQ Base-85 unsafe encoding/decoding functions (specification compliant) * 150 | *******************************************************************************/ 151 | 152 | /** 153 | * @brief Encodes bytes from [source;sourceEnd) range into 'dest'. 154 | * It can be used for implementation of your own padding scheme. 155 | * Preconditions: 156 | * - (sourceEnd - source) % 4 == 0 157 | * - destination buffer must be already allocated 158 | * 159 | * @param source in, begin of input buffer 160 | * @param sourceEnd in, end of input buffer (not included) 161 | * @param dest out, output buffer 162 | * @return a pointer immediately after last symbol written into the 'dest' 163 | */ 164 | char* Z85_encode_unsafe(const char* source, const char* sourceEnd, char* dest); 165 | 166 | /** 167 | * @brief Decodes symbols from [source;sourceEnd) range into 'dest'. 168 | * It can be used for implementation of your own padding scheme. 169 | * Preconditions: 170 | * - (sourceEnd - source) % 5 == 0 171 | * - destination buffer must be already allocated 172 | * 173 | * @param source in, begin of input buffer 174 | * @param sourceEnd in, end of input buffer (not included) 175 | * @param dest out, output buffer 176 | * @return a pointer immediately after last byte written into the 'dest' 177 | */ 178 | char* Z85_decode_unsafe(const char* source, const char* sourceEnd, char* dest); 179 | 180 | #if defined (__cplusplus) 181 | } 182 | #endif 183 | 184 | -------------------------------------------------------------------------------- /genpass.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/javier-lopez/genpass/955b1d578e17632579d6c75b2b6a2417a0b51c41/genpass.gif -------------------------------------------------------------------------------- /libscrypt/LICENSE: -------------------------------------------------------------------------------- 1 | Copyright (c) 2013, Joshua Small 2 | All rights reserved. 3 | 4 | Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: 5 | Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. 6 | Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. 7 | 8 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 9 | 10 | -------------------------------------------------------------------------------- /libscrypt/Makefile: -------------------------------------------------------------------------------- 1 | PREFIX ?= /usr/local 2 | LIBDIR ?= $(PREFIX)/lib 3 | INCLUDEDIR ?= $(PREFIX)/include 4 | MAKE_DIR ?= install -d 5 | INSTALL_DATA ?= install 6 | 7 | CC?=gcc 8 | CFLAGS=-O2 -Wall -g -D_FORTIFY_SOURCE=2 -fstack-protector -fPIC 9 | LDFLAGS=-Wl,-z,now -Wl,-z,relro -Wl,-soname,libscrypt.so.0 -Wl,--version-script=libscrypt.version 10 | CFLAGS_EXTRA=-Wl,-rpath=. 11 | 12 | all: reference 13 | 14 | OBJS= crypto_scrypt-nosse.o sha256.o crypto-mcf.o b64.o z85.o b10.o skey.o crypto-scrypt-saltgen.o crypto_scrypt-check.o crypto_scrypt-hash.o slowequals.o 15 | 16 | libscrypt.so.0: $(OBJS) 17 | $(CC) $(LDFLAGS) -shared -o libscrypt.so.0 $(OBJS) -lm -lc 18 | ar rcs libscrypt.a $(OBJS) 19 | 20 | reference: libscrypt.so.0 main.o crypto_scrypt-hexconvert.o 21 | ln -s -f libscrypt.so.0 libscrypt.so 22 | $(CC) -Wall -o reference main.o b64.o z85.o b10.o skey.o crypto_scrypt-hexconvert.o $(CFLAGS_EXTRA) -L. -lscrypt 23 | $(CC) -Wall -static -o reference-static main.o b64.o z85.o b10.o skey.o crypto_scrypt-hexconvert.o $(CFLAGS_EXTRA) -L. -lscrypt 24 | 25 | clean: 26 | rm -f *.o reference* libscrypt.so* libscrypt.a endian.h 27 | 28 | check: all 29 | ./reference 30 | 31 | devtest: 32 | splint crypto_scrypt-hexconvert.c 33 | splint crypto-mcf.c crypto_scrypt-check.c crypto_scrypt-hash.c -unrecog 34 | splint crypto-scrypt-saltgen.c +posixlib -compdef 35 | valgrind ./reference 36 | 37 | asan: main.c 38 | clang -O1 -g -fsanitize=address -fno-omit-frame-pointer *.c -o asantest 39 | ./asantest 40 | scan-build clang -O1 -g -fsanitize=undefined -fno-omit-frame-pointer *.c -o asantest 41 | ./asantest 42 | rm -f asantest 43 | 44 | install: libscrypt.so.0 45 | $(MAKE_DIR) $(DESTDIR) $(DESTDIR)$(PREFIX) $(DESTDIR)$(LIBDIR) $(DESTDIR)$(INCLUDEDIR) 46 | $(INSTALL_DATA) -pm 0755 libscrypt.so.0 $(DESTDIR)$(LIBDIR) 47 | cd $(DESTDIR)$(LIBDIR) && ln -s -f libscrypt.so.0 $(DESTDIR)$(LIBDIR)/libscrypt.so 48 | $(INSTALL_DATA) -pm 0644 libscrypt.h $(DESTDIR)$(INCLUDEDIR) 49 | 50 | install-osx: libscrypt.so.0 51 | $(MAKE_DIR) $(DESTDIR) $(DESTDIR)$(PREFIX) $(DESTDIR)$(LIBDIR) $(DESTDIR)$(INCLUDEDIR) 52 | $(INSTALL_DATA) -pm 0755 libscrypt.so.0 $(DESTDIR)$(LIBDIR)/libscrypt.0.dylib 53 | cd $(DESTDIR)$(LIBDIR) && install_name_tool -id $(DESTDIR)$(LIBDIR)/libscrypt.0.dylib $(DESTDIR)$(LIBDIR)/libscrypt.0.dylib 54 | cd $(DESTDIR)$(LIBDIR) && ln -s -f libscrypt.0.dylib $(DESTDIR)$(LIBDIR)/libscrypt.dylib 55 | $(INSTALL_DATA) -pm 0644 libscrypt.h $(DESTDIR)$(INCLUDEDIR) 56 | 57 | install-static: libscrypt.a 58 | $(INSTALL_DATA) -pm 0644 libscrypt.a $(DESTDIR)$(LIBDIR) 59 | -------------------------------------------------------------------------------- /libscrypt/README.md: -------------------------------------------------------------------------------- 1 | libscrypt 2 | ========= 3 | Linux scrypt shared library. 4 | 5 | Full credit to algorithm designer and example code from Colin Percival here: 6 | http://www.tarsnap.com/scrypt.html 7 | 8 | Utilises BASE64 encoding library from ISC. 9 | 10 | Official project page, including stable tarballs found here: 11 | http://www.lolware.net/libscrypt.html 12 | 13 | Simple hashing interface 14 | 15 | The (reference) internal hashing function can be directly called as follows: 16 | 17 | int libscrypt_scrypt(const uint8_t *passwd, size_t passwdlen, 18 | const uint8_t *salt, size_t saltlen, uint64_t N, uint32_t r, 19 | uint32_t p, /*@out@*/ uint8_t *buf, size_t buflen); 20 | 21 | Libscrypt's easier to use interface wraps this up to deal with the salt and produce BASE64 output as so: 22 | 23 | int libscrypt_hash(char *dst, char *passphrase, uint32_t N, uint8_t r, uint8_t p); 24 | 25 | Sane constants have been created for N, r and p so you can create a hash like this: 26 | 27 | libscrypt_hash(outbuf, "My cats's breath smells like cat food", SCRYPT_N, SCRYPT_r, SCRYPT_p); 28 | 29 | This function sets errno as required for any error conditions. 30 | 31 | Output stored in "outbuf" is stored in a standardised MCF form, which means includes the randomly created, 128 bit salt, all N, r and p values, and a BASE64 encoded version of the hash. The entire MCF can be stored in a database, and compared for use as below: 32 | 33 | retval = libscrypt_check(mcf, "pleasefailme"); 34 | retval < 0 error 35 | retval = 0 password incorrect 36 | retval > 0 pass 37 | 38 | mcf should be defined as at least SCRYPT_MCF_LEN in size. 39 | 40 | Note that libscrypt_check needs to modify the mcf string and will not return it 41 | to the original state. Pass it a copy if you need to keep the original mcf. 42 | 43 | A number of internal functions are exposed, and users wishing to create more complex use cases should consult the header file, which is aimed at documenting the API fully. 44 | 45 | The test reference is also aimed at providing a well documented use case. 46 | Building 47 | -------- 48 | make 49 | make check 50 | Check the Makefile for advice on linking against your application. 51 | 52 | OSX 53 | ----- 54 | Please compile and install with: 55 | 56 | make LDFLAGS= CFLAGS_EXTRA= 57 | make install-osx 58 | 59 | 60 | BUGS 61 | ---- 62 | SCRYPT_* constants are probably a little high for something like a Raspberry pi. Using '1' as SCRYPT_p is acceptable from a security and performance standpoint if needed. 63 | Experiments were performed with using memset() to zero out passwords as they were checked. This often caused issues with calling applications where the password based have been passed as a const*. We highly recommend implementing your own zeroing function the moment this library is called. 64 | 65 | There is apparently an issue when used on Samsung (and perhaps Android in general) devices. See [this issue](https://github.com/technion/libscrypt/issues/39) for more information. 66 | 67 | Notes on Code Development 68 | ------------------------ 69 | 70 | Code is now declared "stable", the master branch will always be "stable" and development will be done on branches. 71 | The reference machines are Fedora, CentOS, FreeBSD and Raspbian, and the code is expected to compile and run on all of these before being moved to stable branch. 72 | Full transparancy on the regular application of thorough testing can be found by reviewing recent test harness results here: 73 | http://www.lolware.net/libscrypttesting.txt 74 | 75 | Please, no more pull requests for Windows compatibility. If it's important to you - fork the project. I have no intention of pulling an OpenSSL and becoming a maze of ifdefs for platforms I don't even have a build environment for. 76 | 77 | I utilise Facebook's "infer" static analyser, in addition to clang's analyzer. Command to run is: 78 | 79 | infer -- make 80 | 81 | Contact 82 | ------- 83 | I can be contacted at: technion@lolware.net 84 | 85 | If required, my GPG key can be found at: https://lolware.net/technion-GPG-KEY 86 | 87 | Future releases will have the Git tag signed. 88 | 89 | 90 | Changenotes 91 | ----------- 92 | v1.1a: Single Makefile line change. I wouldn't ordinarily tag this as a new "release", but the purpose here is to assist with packaging in distributions. 93 | 94 | v1.12: The static library is built, but no longer installed by default. You can install it with "make install-static". This is because static libraries are not typically bundled in packages. 95 | 96 | v1.13: Minor packaging related update 97 | 98 | v1.15: Replaced the b64 libraries with more portable one from ISC. Now tested and verified on a wider variety of architectures. Note, libscrypt_b64_encrypt was originally an exported function. This is no longer the case as it is considered an internal function only. 99 | 100 | v1.18: God damnit Apple 101 | 102 | v1.19: Code safety cleanups. Now running Coverity. 103 | 104 | v1.20: Bigfixes involving large N values, return values on error 105 | 106 | 107 | Coverity Scan Build Status 109 | 110 | -------------------------------------------------------------------------------- /libscrypt/b10.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | 8 | #include "crypto_scrypt-hexconvert.h" 9 | 10 | int libscrypt_b10_encode(src, srclength, target, targsize) 11 | unsigned char const *src; 12 | size_t srclength; 13 | char *target; 14 | size_t targsize; 15 | { 16 | size_t i; 17 | int len = 0; 18 | 19 | if (!src || srclength < 1 || targsize < (srclength * 2 + 1)) 20 | return -1; 21 | 22 | memset(target, 0, targsize); 23 | 24 | for(i=0; i<=(srclength-1); i++) 25 | { 26 | /* snprintf(target, srclength,"%s...", target....) has undefined results 27 | * and can't be used. Using offests like this makes snprintf 28 | * nontrivial. we therefore have use inescure sprintf() and 29 | * lengths checked elsewhere (start of function) */ 30 | /*@ -bufferoverflowhigh @*/ 31 | len += sprintf(target+len, "%02u", (unsigned int) src[i]); 32 | } 33 | 34 | return 0; 35 | 36 | /*if (libscrypt_hex_encode(src, srclength, target, targsize) == -1) return -1;*/ 37 | /*char *p;*/ 38 | /*errno = 0;*/ 39 | /*unsigned long int b10 = strtoul(target,&p,16);*/ 40 | 41 | /*if (p == target) //no digits found*/ 42 | /*return -1;*/ 43 | /*else if ((b10 == LONG_MIN || b10 == ULONG_MAX) && errno == ERANGE)*/ 44 | /*//value out of range*/ 45 | /*return -1;*/ 46 | /*else*/ 47 | /*snprintf(target, targsize, "%ld", b10);*/ 48 | 49 | /*return 0;*/ 50 | } 51 | -------------------------------------------------------------------------------- /libscrypt/b10.h: -------------------------------------------------------------------------------- 1 | int libscrypt_b10_encode(unsigned char const *src, size_t srclength, 2 | /*@out@*/ char *target, size_t targetsize); 3 | -------------------------------------------------------------------------------- /libscrypt/b64.c: -------------------------------------------------------------------------------- 1 | /*Base64 encode/decode functions from OpenBSD (src/lib/libc/net/base64.c).*/ 2 | 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | 9 | #include "b64.h" 10 | 11 | static const char Base64Compliant[] = 12 | "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"; 13 | static const char Pad64Compliant = '='; 14 | 15 | static const char Base64[] = 16 | "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789$_"; 17 | static const char Pad64 = '\0'; 18 | 19 | /* (From RFC1521 and draft-ietf-dnssec-secext-03.txt) 20 | The following encoding technique is taken from RFC 1521 by Borenstein 21 | and Freed. It is reproduced here in a slightly edited form for 22 | convenience. 23 | 24 | A 65-character subset of US-ASCII is used, enabling 6 bits to be 25 | represented per printable character. (The extra 65th character, "=", 26 | is used to signify a special processing function.) 27 | 28 | The encoding process represents 24-bit groups of input bits as output 29 | strings of 4 encoded characters. Proceeding from left to right, a 30 | 24-bit input group is formed by concatenating 3 8-bit input groups. 31 | These 24 bits are then treated as 4 concatenated 6-bit groups, each 32 | of which is translated into a single digit in the base64 alphabet. 33 | 34 | Each 6-bit group is used as an index into an array of 64 printable 35 | characters. The character referenced by the index is placed in the 36 | output string. 37 | 38 | Table 1: The Base64 Alphabet 39 | 40 | Value Encoding Value Encoding Value Encoding Value Encoding 41 | 0 A 17 R 34 i 51 z 42 | 1 B 18 S 35 j 52 0 43 | 2 C 19 T 36 k 53 1 44 | 3 D 20 U 37 l 54 2 45 | 4 E 21 V 38 m 55 3 46 | 5 F 22 W 39 n 56 4 47 | 6 G 23 X 40 o 57 5 48 | 7 H 24 Y 41 p 58 6 49 | 8 I 25 Z 42 q 59 7 50 | 9 J 26 a 43 r 60 8 51 | 10 K 27 b 44 s 61 9 52 | 11 L 28 c 45 t 62 + 53 | 12 M 29 d 46 u 63 / 54 | 13 N 30 e 47 v 55 | 14 O 31 f 48 w (pad) = 56 | 15 P 32 g 49 x 57 | 16 Q 33 h 50 y 58 | 59 | Special processing is performed if fewer than 24 bits are available 60 | at the end of the data being encoded. A full encoding quantum is 61 | always completed at the end of a quantity. When fewer than 24 input 62 | bits are available in an input group, zero bits are added (on the 63 | right) to form an integral number of 6-bit groups. Padding at the 64 | end of the data is performed using the '=' character. 65 | 66 | Since all base64 input is an integral number of octets, only the 67 | ------------------------------------------------- 68 | following cases can arise: 69 | 70 | (1) the final quantum of encoding input is an integral 71 | multiple of 24 bits; here, the final unit of encoded 72 | output will be an integral multiple of 4 characters 73 | with no "=" padding, 74 | (2) the final quantum of encoding input is exactly 8 bits; 75 | here, the final unit of encoded output will be two 76 | characters followed by two "=" padding characters, or 77 | (3) the final quantum of encoding input is exactly 16 bits; 78 | here, the final unit of encoded output will be three 79 | characters followed by one "=" padding character. 80 | */ 81 | 82 | int 83 | libscrypt_b64_encode(src, srclength, target, targsize) 84 | unsigned char const *src; 85 | size_t srclength; 86 | char *target; 87 | size_t targsize; 88 | { 89 | size_t datalength = 0; 90 | unsigned char input[3]; 91 | unsigned char output[4]; 92 | unsigned int i; 93 | 94 | memset(target, 0, targsize); 95 | 96 | while (2 < srclength) { 97 | input[0] = *src++; 98 | input[1] = *src++; 99 | input[2] = *src++; 100 | srclength -= 3; 101 | 102 | output[0] = input[0] >> 2; 103 | output[1] = ((input[0] & 0x03) << 4) + (input[1] >> 4); 104 | output[2] = ((input[1] & 0x0f) << 2) + (input[2] >> 6); 105 | output[3] = input[2] & 0x3f; 106 | 107 | if (datalength + 4 > targsize) 108 | return (-1); 109 | target[datalength++] = Base64[output[0]]; 110 | target[datalength++] = Base64[output[1]]; 111 | target[datalength++] = Base64[output[2]]; 112 | target[datalength++] = Base64[output[3]]; 113 | } 114 | 115 | /* Now we worry about padding. */ 116 | if (0 != srclength) { 117 | /* Get what's left. */ 118 | input[0] = input[1] = input[2] = '\0'; 119 | for (i = 0; i < srclength; i++) 120 | input[i] = *src++; 121 | 122 | output[0] = input[0] >> 2; 123 | output[1] = ((input[0] & 0x03) << 4) + (input[1] >> 4); 124 | output[2] = ((input[1] & 0x0f) << 2) + (input[2] >> 6); 125 | 126 | if (datalength + 4 > targsize) 127 | return (-1); 128 | target[datalength++] = Base64[output[0]]; 129 | target[datalength++] = Base64[output[1]]; 130 | if (srclength == 1) 131 | target[datalength++] = Pad64; 132 | else 133 | target[datalength++] = Base64[output[2]]; 134 | target[datalength++] = Pad64; 135 | } 136 | if (datalength >= targsize) 137 | return (-1); 138 | target[datalength] = '\0'; /* Returned value doesn't count \0. */ 139 | return (int)(datalength); 140 | } 141 | 142 | int 143 | libscrypt_b64_encode_compliant(src, srclength, target, targsize) 144 | unsigned char const *src; 145 | size_t srclength; 146 | char *target; 147 | size_t targsize; 148 | { 149 | size_t datalength = 0; 150 | unsigned char input[3]; 151 | unsigned char output[4]; 152 | unsigned int i; 153 | 154 | memset(target, 0, targsize); 155 | 156 | while (2 < srclength) { 157 | input[0] = *src++; 158 | input[1] = *src++; 159 | input[2] = *src++; 160 | srclength -= 3; 161 | 162 | output[0] = input[0] >> 2; 163 | output[1] = ((input[0] & 0x03) << 4) + (input[1] >> 4); 164 | output[2] = ((input[1] & 0x0f) << 2) + (input[2] >> 6); 165 | output[3] = input[2] & 0x3f; 166 | 167 | if (datalength + 4 > targsize) 168 | return (-1); 169 | target[datalength++] = Base64Compliant[output[0]]; 170 | target[datalength++] = Base64Compliant[output[1]]; 171 | target[datalength++] = Base64Compliant[output[2]]; 172 | target[datalength++] = Base64Compliant[output[3]]; 173 | } 174 | 175 | /* Now we worry about padding. */ 176 | if (0 != srclength) { 177 | /* Get what's left. */ 178 | input[0] = input[1] = input[2] = '\0'; 179 | for (i = 0; i < srclength; i++) 180 | input[i] = *src++; 181 | 182 | output[0] = input[0] >> 2; 183 | output[1] = ((input[0] & 0x03) << 4) + (input[1] >> 4); 184 | output[2] = ((input[1] & 0x0f) << 2) + (input[2] >> 6); 185 | 186 | if (datalength + 4 > targsize) 187 | return (-1); 188 | target[datalength++] = Base64Compliant[output[0]]; 189 | target[datalength++] = Base64Compliant[output[1]]; 190 | if (srclength == 1) 191 | target[datalength++] = Pad64Compliant; 192 | else 193 | target[datalength++] = Base64Compliant[output[2]]; 194 | target[datalength++] = Pad64Compliant; 195 | } 196 | if (datalength >= targsize) 197 | return (-1); 198 | target[datalength] = '\0'; /* Returned value doesn't count \0. */ 199 | return (int)(datalength); 200 | } 201 | 202 | /* skips all whitespace anywhere. 203 | converts characters, four at a time, starting at (or after) 204 | src from base - 64 numbers into three 8 bit bytes in the target area. 205 | it returns the number of data bytes stored at the target, or -1 on error. 206 | */ 207 | 208 | int 209 | libscrypt_b64_decode_compliant(src, target, targsize) 210 | char const *src; 211 | unsigned char *target; 212 | size_t targsize; 213 | { 214 | int state, ch; 215 | unsigned int tarindex; 216 | unsigned char nextbyte; 217 | char *pos; 218 | 219 | state = 0; 220 | tarindex = 0; 221 | 222 | while ((ch = (unsigned char)*src++) != '\0') { 223 | if (isspace(ch)) /* Skip whitespace anywhere. */ 224 | continue; 225 | 226 | if (ch == Pad64Compliant) 227 | break; 228 | 229 | pos = strchr(Base64Compliant, ch); 230 | if (pos == 0) /* A non-base64 character. */ 231 | return (-1); 232 | 233 | switch (state) { 234 | case 0: 235 | if (target) { 236 | if (tarindex >= targsize) 237 | return (-1); 238 | target[tarindex] = (pos - Base64Compliant) << 2; 239 | } 240 | state = 1; 241 | break; 242 | case 1: 243 | if (target) { 244 | if (tarindex >= targsize) 245 | return (-1); 246 | target[tarindex] |= (pos - Base64Compliant) >> 4; 247 | nextbyte = ((pos - Base64Compliant) & 0x0f) << 4; 248 | if (tarindex + 1 < targsize) 249 | target[tarindex+1] = nextbyte; 250 | else if (nextbyte) 251 | return (-1); 252 | } 253 | tarindex++; 254 | state = 2; 255 | break; 256 | case 2: 257 | if (target) { 258 | if (tarindex >= targsize) 259 | return (-1); 260 | target[tarindex] |= (pos - Base64Compliant) >> 2; 261 | nextbyte = ((pos - Base64Compliant) & 0x03) << 6; 262 | if (tarindex + 1 < targsize) 263 | target[tarindex+1] = nextbyte; 264 | else if (nextbyte) 265 | return (-1); 266 | } 267 | tarindex++; 268 | state = 3; 269 | break; 270 | case 3: 271 | if (target) { 272 | if (tarindex >= targsize) 273 | return (-1); 274 | target[tarindex] |= (pos - Base64Compliant); 275 | } 276 | tarindex++; 277 | state = 0; 278 | break; 279 | } 280 | } 281 | 282 | /* 283 | * We are done decoding Base-64 chars. Let's see if we ended 284 | * on a byte boundary, and/or with erroneous trailing characters. 285 | */ 286 | 287 | if (ch == Pad64Compliant) { /* We got a pad char. */ 288 | ch = (unsigned char)*src++; /* Skip it, get next. */ 289 | switch (state) { 290 | case 0: /* Invalid = in first position */ 291 | case 1: /* Invalid = in second position */ 292 | return (-1); 293 | 294 | case 2: /* Valid, means one byte of info */ 295 | /* Skip any number of spaces. */ 296 | for (; ch != '\0'; ch = (unsigned char)*src++) 297 | if (!isspace(ch)) 298 | break; 299 | /* Make sure there is another trailing = sign. */ 300 | if (ch != Pad64Compliant) 301 | return (-1); 302 | ch = (unsigned char)*src++; /* Skip the = */ 303 | /* Fall through to "single trailing =" case. */ 304 | /* FALLTHROUGH */ 305 | 306 | case 3: /* Valid, means two bytes of info */ 307 | /* 308 | * We know this char is an =. Is there anything but 309 | * whitespace after it? 310 | */ 311 | for (; ch != '\0'; ch = (unsigned char)*src++) 312 | if (!isspace(ch)) 313 | return (-1); 314 | 315 | /* 316 | * Now make sure for cases 2 and 3 that the "extra" 317 | * bits that slopped past the last full byte were 318 | * zeros. If we don't check them, they become a 319 | * subliminal channel. 320 | */ 321 | if (target && tarindex < targsize && 322 | target[tarindex] != 0) 323 | return (-1); 324 | } 325 | } else { 326 | /* 327 | * We ended by seeing the end of the string. Make sure we 328 | * have no partial bytes lying around. 329 | */ 330 | if (state != 0) 331 | return (-1); 332 | } 333 | 334 | return (tarindex); 335 | } 336 | -------------------------------------------------------------------------------- /libscrypt/b64.h: -------------------------------------------------------------------------------- 1 | /* BASE64 libraries used internally - should not need to be packaged */ 2 | #include 3 | #define b64_encode_len(A) ((A+2)/3 * 4 + 1) 4 | #define b64_decode_len(A) (A / 4 * 3 + 2) 5 | 6 | //modified version, $_ instead of +/ and without '=' padding, optimized 7 | //for generating passwords 8 | int libscrypt_b64_encode(unsigned char const *src, size_t srclength, 9 | /*@out@*/ char *target, size_t targetsize); 10 | 11 | int libscrypt_b64_encode_compliant(unsigned char const *src, size_t srclength, 12 | /*@out@*/ char *target, size_t targetsize); 13 | int libscrypt_b64_decode_compliant(char const *src, 14 | /*@out@*/ unsigned char *target, size_t targetsize); 15 | -------------------------------------------------------------------------------- /libscrypt/crypto-mcf.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | 9 | #ifndef S_SPLINT_S /* Including this here triggers a known bug in splint */ 10 | #include 11 | #endif 12 | 13 | #include "libscrypt.h" 14 | 15 | /* ilog2 for powers of two */ 16 | static uint32_t scrypt_ilog2(uint32_t n) 17 | { 18 | #ifndef S_SPLINT_S 19 | 20 | /* Check for a valid power of two */ 21 | if (n < 2 || (n & (n - 1))) 22 | return -1; 23 | #endif 24 | uint32_t t = 1; 25 | while (((uint32_t)1 << t) < n) 26 | { 27 | if(t > SCRYPT_SAFE_N) 28 | return (uint32_t) -1; /* Check for insanity */ 29 | t++; 30 | } 31 | 32 | return t; 33 | } 34 | 35 | #ifdef _MSC_VER 36 | #define SNPRINTF _snprintf 37 | #else 38 | #define SNPRINTF snprintf 39 | #endif 40 | 41 | int libscrypt_mcf(uint32_t N, uint32_t r, uint32_t p, const char *salt, 42 | const char *hash, char *mcf) 43 | { 44 | 45 | uint32_t t, params; 46 | int s; 47 | 48 | if(!mcf || !hash) 49 | return 0; 50 | /* Although larger values of r, p are valid in scrypt, this mcf format 51 | * limits to 8 bits. If your number is larger, current computers will 52 | * struggle 53 | */ 54 | if(r > (uint8_t)(-1) || p > (uint8_t)(-1)) 55 | return 0; 56 | 57 | t = scrypt_ilog2(N); 58 | if (t < 1) 59 | return 0; 60 | 61 | params = (r << 8) + p; 62 | params += (uint32_t)t << 16; 63 | 64 | /* Using snprintf - not checking for overflows. We've already 65 | * determined that mcf should be defined as at least SCRYPT_MCF_LEN 66 | * in length 67 | */ 68 | s = SNPRINTF(mcf, SCRYPT_MCF_LEN, SCRYPT_MCF_ID "$%06x$%s$%s", (unsigned int)params, salt, hash); 69 | if (s >= SCRYPT_MCF_LEN) 70 | return 0; 71 | 72 | return 1; 73 | } 74 | -------------------------------------------------------------------------------- /libscrypt/crypto-scrypt-saltgen.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | 7 | #ifndef S_SPLINT_S /* Including this here triggers a known bug in splint */ 8 | #include 9 | #endif 10 | 11 | #define RNGDEV "/dev/urandom" 12 | 13 | int libscrypt_salt_gen(uint8_t *salt, size_t len) 14 | { 15 | unsigned char buf[len]; 16 | size_t data_read = 0; 17 | int urandom = open(RNGDEV, O_RDONLY); 18 | 19 | if (urandom < 0) 20 | { 21 | return -1; 22 | } 23 | 24 | while (data_read < len) { 25 | ssize_t result = read(urandom, buf + data_read, len - data_read); 26 | 27 | if (result < 0) 28 | { 29 | if (errno == EINTR || errno == EAGAIN) { 30 | continue; 31 | } 32 | 33 | else { 34 | (void)close(urandom); 35 | return -1; 36 | } 37 | } 38 | 39 | data_read += result; 40 | } 41 | 42 | /* Failures on close() shouldn't occur with O_RDONLY */ 43 | (void)close(urandom); 44 | 45 | memcpy(salt, buf, len); 46 | 47 | return 0; 48 | } 49 | -------------------------------------------------------------------------------- /libscrypt/crypto_scrypt-check.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | 6 | #include "b64.h" 7 | #include "slowequals.h" 8 | #include "libscrypt.h" 9 | 10 | #ifdef _WIN32 11 | /* On windows, strtok uses a thread-local static variable in strtok to 12 | * make strtok thread-safe. It also neglects to provide a strtok_r. */ 13 | #define strtok_r(str, val, saveptr) strtok((str), (val)) 14 | #endif 15 | 16 | int libscrypt_check(char *mcf, const char *password) 17 | { 18 | /* Return values: 19 | * <0 error 20 | * == 0 password incorrect 21 | * >0 correct password 22 | */ 23 | 24 | #ifndef _WIN32 25 | char *saveptr = NULL; 26 | #endif 27 | uint32_t params; 28 | uint64_t N; 29 | uint8_t r, p; 30 | int retval; 31 | uint8_t hashbuf[64]; 32 | char outbuf[128]; 33 | uint8_t salt[32]; 34 | char *tok; 35 | 36 | if(mcf == NULL) 37 | { 38 | return -1; 39 | } 40 | 41 | if(memcmp(mcf, SCRYPT_MCF_ID, 3) != 0) 42 | { 43 | /* Only version 0 supported */ 44 | return -1; 45 | } 46 | 47 | tok = strtok_r(mcf, "$", &saveptr); 48 | if ( !tok ) 49 | return -1; 50 | 51 | tok = strtok_r(NULL, "$", &saveptr); 52 | 53 | if ( !tok ) 54 | return -1; 55 | 56 | params = (uint32_t)strtoul(tok, NULL, 16); 57 | if ( params == 0 ) 58 | return -1; 59 | 60 | tok = strtok_r(NULL, "$", &saveptr); 61 | 62 | if ( !tok ) 63 | return -1; 64 | 65 | p = params & 0xff; 66 | r = (params >> 8) & 0xff; 67 | N = params >> 16; 68 | 69 | if (N > SCRYPT_SAFE_N) 70 | return -1; 71 | 72 | N = (uint64_t)1 << N; 73 | 74 | /* Useful debugging: 75 | printf("We've obtained salt 'N' r p of '%s' %d %d %d\n", tok, N,r,p); 76 | */ 77 | 78 | memset(salt, 0, sizeof(salt)); /* Keeps splint happy */ 79 | retval = libscrypt_b64_decode_compliant(tok, (unsigned char*)salt, sizeof(salt)); 80 | if (retval < 1) 81 | return -1; 82 | 83 | retval = libscrypt_scrypt((uint8_t*)password, strlen(password), salt, 84 | (uint32_t)retval, N, r, p, hashbuf, sizeof(hashbuf)); 85 | 86 | if (retval != 0) 87 | return -1; 88 | 89 | retval = libscrypt_b64_encode_compliant((unsigned char*)hashbuf, sizeof(hashbuf), 90 | outbuf, sizeof(outbuf)); 91 | 92 | if (retval == 0) 93 | return -1; 94 | 95 | tok = strtok_r(NULL, "$", &saveptr); 96 | 97 | if ( !tok ) 98 | return -1; 99 | 100 | if(slow_equals(tok, outbuf) == 0) 101 | return 0; 102 | 103 | return 1; /* This is the "else" condition */ 104 | } 105 | 106 | -------------------------------------------------------------------------------- /libscrypt/crypto_scrypt-hash.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | 6 | #include "b64.h" 7 | #include "libscrypt.h" 8 | 9 | int libscrypt_hash(char *dst, const char *passphrase, uint32_t N, uint8_t r, 10 | uint8_t p) 11 | { 12 | 13 | int retval; 14 | uint8_t salt[SCRYPT_SALT_LEN]; 15 | uint8_t hashbuf[SCRYPT_HASH_LEN]; 16 | char outbuf[256]; 17 | char saltbuf[256]; 18 | 19 | if(libscrypt_salt_gen(salt, SCRYPT_SALT_LEN) == -1) 20 | { 21 | return 0; 22 | } 23 | 24 | retval = libscrypt_scrypt((const uint8_t*)passphrase, strlen(passphrase), 25 | (uint8_t*)salt, SCRYPT_SALT_LEN, N, r, p, hashbuf, sizeof(hashbuf)); 26 | if(retval == -1) 27 | return 0; 28 | 29 | retval = libscrypt_b64_encode_compliant((unsigned char*)hashbuf, sizeof(hashbuf), 30 | outbuf, sizeof(outbuf)); 31 | if(retval == -1) 32 | return 0; 33 | 34 | retval = libscrypt_b64_encode_compliant((unsigned char *)salt, sizeof(salt), 35 | saltbuf, sizeof(saltbuf)); 36 | if(retval == -1) 37 | return 0; 38 | 39 | retval = libscrypt_mcf(N, r, p, saltbuf, outbuf, dst); 40 | if(retval != 1) 41 | return 0; 42 | 43 | return 1; 44 | } 45 | -------------------------------------------------------------------------------- /libscrypt/crypto_scrypt-hexconvert.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | 6 | /* The hexconvert function is only used to test reference vectors against 7 | * known answers. The contents of this file are therefore a component 8 | * to assist with test harnesses only 9 | */ 10 | 11 | int libscrypt_hexconvert(const unsigned char * buf, size_t s, char *outbuf, size_t obs) 12 | { 13 | size_t i; 14 | int len = 0; 15 | 16 | if (!buf || s < 1 || obs < (s * 2 + 1)) 17 | return 0; 18 | 19 | memset(outbuf, 0, obs); 20 | 21 | for(i=0; i<=(s-1); i++) 22 | { 23 | /* snprintf(outbuf, s,"%s...", outbuf....) has undefined results 24 | * and can't be used. Using offests like this makes snprintf 25 | * nontrivial. we therefore have use inescure sprintf() and 26 | * lengths checked elsewhere (start of function) */ 27 | /*@ -bufferoverflowhigh @*/ 28 | len += sprintf(outbuf+len, "%02x", (unsigned int) buf[i]); 29 | } 30 | 31 | return 1; 32 | } 33 | 34 | int libscrypt_hex_encode(const unsigned char * buf, size_t s, char *outbuf, size_t obs) 35 | { 36 | return libscrypt_hexconvert(buf, s, outbuf, obs); 37 | } 38 | -------------------------------------------------------------------------------- /libscrypt/crypto_scrypt-hexconvert.h: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | /** 5 | * Converts a binary string to a hex representation of that string 6 | * outbuf must have size of at least buf * 2 + 1. 7 | */ 8 | int libscrypt_hexconvert(const unsigned char * buf, size_t s, char *outbuf, size_t obs); 9 | int libscrypt_hex_encode(const unsigned char * buf, size_t s, char *outbuf, size_t obs); 10 | -------------------------------------------------------------------------------- /libscrypt/crypto_scrypt-nosse.c: -------------------------------------------------------------------------------- 1 | /*- 2 | * Copyright 2009 Colin Percival 3 | * All rights reserved. 4 | * 5 | * Redistribution and use in source and binary forms, with or without 6 | * modification, are permitted provided that the following conditions 7 | * are met: 8 | * 1. Redistributions of source code must retain the above copyright 9 | * notice, this list of conditions and the following disclaimer. 10 | * 2. Redistributions in binary form must reproduce the above copyright 11 | * notice, this list of conditions and the following disclaimer in the 12 | * documentation and/or other materials provided with the distribution. 13 | * 14 | * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 15 | * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 16 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 17 | * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 18 | * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 19 | * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 20 | * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 21 | * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 22 | * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 23 | * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 24 | * SUCH DAMAGE. 25 | * 26 | * This file was originally written by Colin Percival as part of the Tarsnap 27 | * online backup system. 28 | */ 29 | 30 | #include 31 | #ifndef _WIN32 32 | #include 33 | #endif 34 | #include 35 | #include 36 | #include 37 | #include 38 | 39 | #include "sha256.h" 40 | #include "sysendian.h" 41 | 42 | #include "libscrypt.h" 43 | 44 | static void blkcpy(void *, void *, size_t); 45 | static void blkxor(void *, void *, size_t); 46 | static void salsa20_8(uint32_t[16]); 47 | static void blockmix_salsa8(uint32_t *, uint32_t *, uint32_t *, size_t); 48 | static uint64_t integerify(void *, size_t); 49 | static void smix(uint8_t *, size_t, uint64_t, uint32_t *, uint32_t *); 50 | 51 | static void 52 | blkcpy(void * dest, void * src, size_t len) 53 | { 54 | size_t * D = dest; 55 | size_t * S = src; 56 | size_t L = len / sizeof(size_t); 57 | size_t i; 58 | 59 | for (i = 0; i < L; i++) 60 | D[i] = S[i]; 61 | } 62 | 63 | static void 64 | blkxor(void * dest, void * src, size_t len) 65 | { 66 | size_t * D = dest; 67 | size_t * S = src; 68 | size_t L = len / sizeof(size_t); 69 | size_t i; 70 | 71 | for (i = 0; i < L; i++) 72 | D[i] ^= S[i]; 73 | } 74 | 75 | /** 76 | * salsa20_8(B): 77 | * Apply the salsa20/8 core to the provided block. 78 | */ 79 | static void 80 | salsa20_8(uint32_t B[16]) 81 | { 82 | uint32_t x[16]; 83 | size_t i; 84 | 85 | blkcpy(x, B, 64); 86 | for (i = 0; i < 8; i += 2) { 87 | #define R(a,b) (((a) << (b)) | ((a) >> (32 - (b)))) 88 | /* Operate on columns. */ 89 | x[ 4] ^= R(x[ 0]+x[12], 7); x[ 8] ^= R(x[ 4]+x[ 0], 9); 90 | x[12] ^= R(x[ 8]+x[ 4],13); x[ 0] ^= R(x[12]+x[ 8],18); 91 | 92 | x[ 9] ^= R(x[ 5]+x[ 1], 7); x[13] ^= R(x[ 9]+x[ 5], 9); 93 | x[ 1] ^= R(x[13]+x[ 9],13); x[ 5] ^= R(x[ 1]+x[13],18); 94 | 95 | x[14] ^= R(x[10]+x[ 6], 7); x[ 2] ^= R(x[14]+x[10], 9); 96 | x[ 6] ^= R(x[ 2]+x[14],13); x[10] ^= R(x[ 6]+x[ 2],18); 97 | 98 | x[ 3] ^= R(x[15]+x[11], 7); x[ 7] ^= R(x[ 3]+x[15], 9); 99 | x[11] ^= R(x[ 7]+x[ 3],13); x[15] ^= R(x[11]+x[ 7],18); 100 | 101 | /* Operate on rows. */ 102 | x[ 1] ^= R(x[ 0]+x[ 3], 7); x[ 2] ^= R(x[ 1]+x[ 0], 9); 103 | x[ 3] ^= R(x[ 2]+x[ 1],13); x[ 0] ^= R(x[ 3]+x[ 2],18); 104 | 105 | x[ 6] ^= R(x[ 5]+x[ 4], 7); x[ 7] ^= R(x[ 6]+x[ 5], 9); 106 | x[ 4] ^= R(x[ 7]+x[ 6],13); x[ 5] ^= R(x[ 4]+x[ 7],18); 107 | 108 | x[11] ^= R(x[10]+x[ 9], 7); x[ 8] ^= R(x[11]+x[10], 9); 109 | x[ 9] ^= R(x[ 8]+x[11],13); x[10] ^= R(x[ 9]+x[ 8],18); 110 | 111 | x[12] ^= R(x[15]+x[14], 7); x[13] ^= R(x[12]+x[15], 9); 112 | x[14] ^= R(x[13]+x[12],13); x[15] ^= R(x[14]+x[13],18); 113 | #undef R 114 | } 115 | for (i = 0; i < 16; i++) 116 | B[i] += x[i]; 117 | } 118 | 119 | /** 120 | * blockmix_salsa8(Bin, Bout, X, r): 121 | * Compute Bout = BlockMix_{salsa20/8, r}(Bin). The input Bin must be 128r 122 | * bytes in length; the output Bout must also be the same size. The 123 | * temporary space X must be 64 bytes. 124 | */ 125 | static void 126 | blockmix_salsa8(uint32_t * Bin, uint32_t * Bout, uint32_t * X, size_t r) 127 | { 128 | size_t i; 129 | 130 | /* 1: X <-- B_{2r - 1} */ 131 | blkcpy(X, &Bin[(2 * r - 1) * 16], 64); 132 | 133 | /* 2: for i = 0 to 2r - 1 do */ 134 | for (i = 0; i < 2 * r; i += 2) { 135 | /* 3: X <-- H(X \xor B_i) */ 136 | blkxor(X, &Bin[i * 16], 64); 137 | salsa20_8(X); 138 | 139 | /* 4: Y_i <-- X */ 140 | /* 6: B' <-- (Y_0, Y_2 ... Y_{2r-2}, Y_1, Y_3 ... Y_{2r-1}) */ 141 | blkcpy(&Bout[i * 8], X, 64); 142 | 143 | /* 3: X <-- H(X \xor B_i) */ 144 | blkxor(X, &Bin[i * 16 + 16], 64); 145 | salsa20_8(X); 146 | 147 | /* 4: Y_i <-- X */ 148 | /* 6: B' <-- (Y_0, Y_2 ... Y_{2r-2}, Y_1, Y_3 ... Y_{2r-1}) */ 149 | blkcpy(&Bout[i * 8 + r * 16], X, 64); 150 | } 151 | } 152 | 153 | /** 154 | * integerify(B, r): 155 | * Return the result of parsing B_{2r-1} as a little-endian integer. 156 | */ 157 | static uint64_t 158 | integerify(void * B, size_t r) 159 | { 160 | uint32_t * X = (void *)((uintptr_t)(B) + (2 * r - 1) * 64); 161 | 162 | return (((uint64_t)(X[1]) << 32) + X[0]); 163 | } 164 | 165 | /** 166 | * smix(B, r, N, V, XY): 167 | * Compute B = SMix_r(B, N). The input B must be 128r bytes in length; 168 | * the temporary storage V must be 128rN bytes in length; the temporary 169 | * storage XY must be 256r + 64 bytes in length. The value N must be a 170 | * power of 2 greater than 1. The arrays B, V, and XY must be aligned to a 171 | * multiple of 64 bytes. 172 | */ 173 | static void 174 | smix(uint8_t * B, size_t r, uint64_t N, uint32_t * V, uint32_t * XY) 175 | { 176 | uint32_t * X = XY; 177 | uint32_t * Y = &XY[32 * r]; 178 | uint32_t * Z = &XY[64 * r]; 179 | uint64_t i; 180 | uint64_t j; 181 | size_t k; 182 | 183 | /* 1: X <-- B */ 184 | for (k = 0; k < 32 * r; k++) 185 | X[k] = le32dec(&B[4 * k]); 186 | 187 | /* 2: for i = 0 to N - 1 do */ 188 | for (i = 0; i < N; i += 2) { 189 | /* 3: V_i <-- X */ 190 | blkcpy(&V[i * (32 * r)], X, 128 * r); 191 | 192 | /* 4: X <-- H(X) */ 193 | blockmix_salsa8(X, Y, Z, r); 194 | 195 | /* 3: V_i <-- X */ 196 | blkcpy(&V[(i + 1) * (32 * r)], Y, 128 * r); 197 | 198 | /* 4: X <-- H(X) */ 199 | blockmix_salsa8(Y, X, Z, r); 200 | } 201 | 202 | /* 6: for i = 0 to N - 1 do */ 203 | for (i = 0; i < N; i += 2) { 204 | /* 7: j <-- Integerify(X) mod N */ 205 | j = integerify(X, r) & (N - 1); 206 | 207 | /* 8: X <-- H(X \xor V_j) */ 208 | blkxor(X, &V[j * (32 * r)], 128 * r); 209 | blockmix_salsa8(X, Y, Z, r); 210 | 211 | /* 7: j <-- Integerify(X) mod N */ 212 | j = integerify(Y, r) & (N - 1); 213 | 214 | /* 8: X <-- H(X \xor V_j) */ 215 | blkxor(Y, &V[j * (32 * r)], 128 * r); 216 | blockmix_salsa8(Y, X, Z, r); 217 | } 218 | 219 | /* 10: B' <-- X */ 220 | for (k = 0; k < 32 * r; k++) 221 | le32enc(&B[4 * k], X[k]); 222 | } 223 | 224 | /** 225 | * crypto_scrypt(passwd, passwdlen, salt, saltlen, N, r, p, buf, buflen): 226 | * Compute scrypt(passwd[0 .. passwdlen - 1], salt[0 .. saltlen - 1], N, r, 227 | * p, buflen) and write the result into buf. The parameters r, p, and buflen 228 | * must satisfy r * p < 2^30 and buflen <= (2^32 - 1) * 32. The parameter N 229 | * must be a power of 2 greater than 1. 230 | * 231 | * Return 0 on success; or -1 on error 232 | */ 233 | int 234 | libscrypt_scrypt(const uint8_t * passwd, size_t passwdlen, 235 | const uint8_t * salt, size_t saltlen, uint64_t N, uint32_t r, uint32_t p, 236 | uint8_t * buf, size_t buflen) 237 | { 238 | void * B0, * V0, * XY0; 239 | uint8_t * B; 240 | uint32_t * V; 241 | uint32_t * XY; 242 | uint32_t i; 243 | 244 | /* Sanity-check parameters. */ 245 | #if SIZE_MAX > UINT32_MAX 246 | if (buflen > (((uint64_t)(1) << 32) - 1) * 32) { 247 | errno = EFBIG; 248 | goto err0; 249 | } 250 | #endif 251 | if ((uint64_t)(r) * (uint64_t)(p) >= (1 << 30)) { 252 | errno = EFBIG; 253 | goto err0; 254 | } 255 | if (r == 0 || p == 0) { 256 | errno = EINVAL; 257 | goto err0; 258 | } 259 | if (((N & (N - 1)) != 0) || (N < 2)) { 260 | errno = EINVAL; 261 | goto err0; 262 | } 263 | if ((r > SIZE_MAX / 128 / p) || 264 | #if SIZE_MAX / 256 <= UINT32_MAX 265 | (r > SIZE_MAX / 256) || 266 | #endif 267 | (N > SIZE_MAX / 128 / r)) { 268 | errno = ENOMEM; 269 | goto err0; 270 | } 271 | 272 | /* Allocate memory. */ 273 | #ifdef HAVE_POSIX_MEMALIGN 274 | if ((errno = posix_memalign(&B0, 64, 128 * r * p)) != 0) 275 | goto err0; 276 | B = (uint8_t *)(B0); 277 | if ((errno = posix_memalign(&XY0, 64, 256 * r + 64)) != 0) 278 | goto err1; 279 | XY = (uint32_t *)(XY0); 280 | #ifndef MAP_ANON 281 | if ((errno = posix_memalign(&V0, 64, 128 * r * N)) != 0) 282 | goto err2; 283 | V = (uint32_t *)(V0); 284 | #endif 285 | #else 286 | if ((B0 = malloc(128 * r * p + 63)) == NULL) 287 | goto err0; 288 | B = (uint8_t *)(((uintptr_t)(B0) + 63) & ~ (uintptr_t)(63)); 289 | if ((XY0 = malloc(256 * r + 64 + 63)) == NULL) 290 | goto err1; 291 | XY = (uint32_t *)(((uintptr_t)(XY0) + 63) & ~ (uintptr_t)(63)); 292 | #ifndef MAP_ANON 293 | if ((V0 = malloc(128 * r * N + 63)) == NULL) 294 | goto err2; 295 | V = (uint32_t *)(((uintptr_t)(V0) + 63) & ~ (uintptr_t)(63)); 296 | #endif 297 | #endif 298 | #ifdef MAP_ANON 299 | if ((V0 = mmap(NULL, 128 * r * N, PROT_READ | PROT_WRITE, 300 | #ifdef MAP_NOCORE 301 | MAP_ANON | MAP_PRIVATE | MAP_NOCORE, 302 | #else 303 | MAP_ANON | MAP_PRIVATE, 304 | #endif 305 | -1, 0)) == MAP_FAILED) 306 | goto err2; 307 | V = (uint32_t *)(V0); 308 | #endif 309 | 310 | /* 1: (B_0 ... B_{p-1}) <-- PBKDF2(P, S, 1, p * MFLen) */ 311 | libscrypt_PBKDF2_SHA256(passwd, passwdlen, salt, saltlen, 1, B, p * 128 * r); 312 | 313 | /* 2: for i = 0 to p - 1 do */ 314 | for (i = 0; i < p; i++) { 315 | /* 3: B_i <-- MF(B_i, N) */ 316 | smix(&B[i * 128 * r], r, N, V, XY); 317 | } 318 | 319 | /* 5: DK <-- PBKDF2(P, B, 1, dkLen) */ 320 | libscrypt_PBKDF2_SHA256(passwd, passwdlen, B, p * 128 * r, 1, buf, buflen); 321 | 322 | /* Free memory. */ 323 | #ifdef MAP_ANON 324 | if (munmap(V0, 128 * r * N)) 325 | goto err2; 326 | #else 327 | free(V0); 328 | #endif 329 | free(XY0); 330 | free(B0); 331 | 332 | /* Success! */ 333 | return (0); 334 | 335 | err2: 336 | free(XY0); 337 | err1: 338 | free(B0); 339 | err0: 340 | /* Failure! */ 341 | return (-1); 342 | } 343 | -------------------------------------------------------------------------------- /libscrypt/libscrypt.h: -------------------------------------------------------------------------------- 1 | /*- 2 | */ 3 | #ifndef _CRYPTO_SCRYPT_H_ 4 | #define _CRYPTO_SCRYPT_H_ 5 | 6 | 7 | #include 8 | #include 9 | #ifdef __cplusplus 10 | extern "C"{ 11 | #endif 12 | 13 | #include "crypto_scrypt-hexconvert.h" 14 | 15 | /** 16 | * crypto_scrypt(passwd, passwdlen, salt, saltlen, N, r, p, buf, buflen): 17 | * Compute scrypt(passwd[0 .. passwdlen - 1], salt[0 .. saltlen - 1], N, r, 18 | * p, buflen) and write the result into buf. The parameters r, p, and buflen 19 | * must satisfy r * p < 2^30 and buflen <= (2^32 - 1) * 32. The parameter N 20 | * must be a power of 2 greater than 1. 21 | * 22 | * libscrypt_scrypt(passwd, passwdlen, salt, saltlen, N, r, p, buf, buflen): 23 | * password; duh 24 | * N: CPU AND RAM cost (first modifier) 25 | * r: RAM Cost 26 | * p: CPU cost (parallelisation) 27 | * In short, N is your main performance modifier. Values of r = 8, p = 1 are 28 | * standard unless you want to modify the CPU/RAM ratio. 29 | * Return 0 on success; or -1 on error. 30 | */ 31 | int libscrypt_scrypt(const uint8_t *, size_t, const uint8_t *, size_t, uint64_t, 32 | uint32_t, uint32_t, /*@out@*/ uint8_t *, size_t); 33 | 34 | /* Converts a series of input parameters to a MCF form for storage */ 35 | int libscrypt_mcf(uint32_t N, uint32_t r, uint32_t p, const char *salt, 36 | const char *hash, char *mcf); 37 | 38 | #ifndef _MSC_VER 39 | /* Generates a salt. Uses /dev/urandom/ 40 | */ 41 | int libscrypt_salt_gen(/*@out@*/ uint8_t *rand, size_t len); 42 | 43 | /* Creates a hash of a passphrase using a randomly generated salt */ 44 | /* Returns >0 on success, or 0 for fail */ 45 | int libscrypt_hash(char *dst, const char* passphrase, uint32_t N, uint8_t r, 46 | uint8_t p); 47 | #endif 48 | 49 | /* Checks a given MCF against a password */ 50 | int libscrypt_check(char *mcf, const char *password); 51 | 52 | #ifdef __cplusplus 53 | } 54 | #endif 55 | 56 | /* Sane default values */ 57 | #define SCRYPT_HASH_LEN 64 /* This can be user defined - 58 | *but 64 is the reference size 59 | */ 60 | #define SCRYPT_SAFE_N 30 /* This is much higher than you want. It's just 61 | * a blocker for insane defines 62 | */ 63 | #define SCRYPT_SALT_LEN 16 /* This is just a recommended size */ 64 | /* Standard MCF is: 65 | $s1 Identifier, three chars 66 | $0e0810 Work order and separator, six chars 67 | Formula for binary to base64 length = ceil(n/3)*4 68 | $pcL+DWle903AXcKJVwMffA== Salt is 16 bytes, or 24 in Base64 69 | $dn+9ujljVc5JTJMC2fYu1ZEHdJyqYkOurmcrBQbMHUfnD6qxbTmNiR075ohNBZjvp66E2aV1pfOrmyNHUefjMg== Hash is 64 bytes, or 88 in Base64. 70 | Work order, salt and hash have separators (3) 71 | 3 + 6 + 24 + 88 + 3 + null byte = 125 72 | This is rounded up to a multiple of four for alignment 73 | */ 74 | #define SCRYPT_MCF_LEN 128 75 | #define SCRYPT_MCF_ID "$s1" 76 | #define SCRYPT_N 16384 77 | #define SCRYPT_r 8 78 | #define SCRYPT_p 16 79 | #endif /* !_CRYPTO_SCRYPT_H_ */ 80 | -------------------------------------------------------------------------------- /libscrypt/libscrypt.version: -------------------------------------------------------------------------------- 1 | libscrypt { 2 | global: libscrypt_check; 3 | libscrypt_hash; 4 | libscrypt_mcf; 5 | libscrypt_salt_gen; 6 | libscrypt_scrypt; 7 | local: *; 8 | }; 9 | -------------------------------------------------------------------------------- /libscrypt/main.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | 6 | #include "b64.h" 7 | #include "crypto_scrypt-hexconvert.h" 8 | #include "libscrypt.h" 9 | 10 | #define REF1 "fdbabe1c9d3472007856e7190d01e9fe7c6ad7cbc8237830e77376634b3731622eaf30d92e22a3886ff109279d9830dac727afb94a83ee6d8360cbdfa2cc0640" 11 | 12 | #define REF2 "7023bdcb3afd7348461c06cd81fd38ebfda8fbba904f8e3ea9b543f6545da1f2d5432955613f0fcf62d49705242a9af9e61e85dc0d651e40dfcf017b45575887" 13 | 14 | 15 | int main() 16 | { 17 | uint8_t hashbuf[SCRYPT_HASH_LEN]; 18 | char outbuf[132]; 19 | char mcf[SCRYPT_MCF_LEN]; 20 | char mcf2[SCRYPT_MCF_LEN]; 21 | char saltbuf[64]; 22 | int retval; 23 | /** 24 | * libscrypt_scrypt(passwd, passwdlen, salt, saltlen, N, r, p, buf, buflen): 25 | * password; duh 26 | * N: CPU AND RAM cost (first modifier) 27 | * r: RAM Cost 28 | * p: CPU cost (parallelisation) 29 | * In short, N is your main performance modifier. Values of r = 8, p = 1 are 30 | * standard unless you want to modify the CPU/RAM ratio. 31 | int libscrypt_scrypt(const uint8_t *, size_t, const uint8_t *, size_t, uint64_t, 32 | uint32_t, uint32_t, uint8_t *, size_t); 33 | */ 34 | 35 | printf("TEST ONE: Direct call to reference function with password 'password' and salt 'NaCL'\n"); 36 | 37 | retval = libscrypt_scrypt((uint8_t*)"password",strlen("password"), (uint8_t*)"NaCl", strlen("NaCl"), 1024, 8, 16, hashbuf, sizeof(hashbuf)); 38 | 39 | if(retval != 0) 40 | { 41 | printf("TEST ONE FAILED: Failed to create hash of \"password\"\\n"); 42 | exit(EXIT_FAILURE); 43 | } 44 | 45 | printf("TEST ONE: SUCCESSFUL\n"); 46 | 47 | printf("TEST ONE and a half: Review errno on invalid input\n"); 48 | 49 | retval = libscrypt_scrypt((uint8_t*)"password",strlen("password"), (uint8_t*)"NaCl", strlen("NaCl"), 47, 1, 1, hashbuf, sizeof(hashbuf)); 50 | 51 | if(retval != -1) 52 | { 53 | printf("TEST ONE FAILED: Failed to detect invalid input\n"); 54 | exit(EXIT_FAILURE); 55 | } 56 | printf("TEST ONE and a half: Successfully failed on error: %s\n", strerror(errno)); 57 | 58 | /* Convert the binary string to hex representation. Outbuf must be 59 | * at least sizeof(hashbuf) * 2 + 1 60 | * Returns 0 on fail, 1 on success 61 | */ 62 | printf("TEST TWO: Convert binary output to hex\n"); 63 | retval = libscrypt_hexconvert(hashbuf, sizeof(hashbuf), outbuf, sizeof(outbuf)); 64 | if(!retval) 65 | { 66 | printf("TEST TWO: FAILED\n"); 67 | exit(EXIT_FAILURE); 68 | } 69 | printf("TEST TWO: SUCCESSFUL, Hex output is:\n%s\n", outbuf); 70 | 71 | printf("TEST THREE: Compare hex output to reference hash output\n"); 72 | 73 | /* REF1 is a reference vector from Colin's implementation. */ 74 | if(strcmp(outbuf, REF1) != 0) 75 | { 76 | printf("TEST THREE: FAILED to match reference on hash\n"); 77 | exit(EXIT_FAILURE); 78 | } 79 | else 80 | { 81 | printf("TEST THREE: SUCCESSUL, Test vector matched!\n"); 82 | } 83 | 84 | printf("TEST FOUR: Direct call to reference function with pleaseletmein password and SodiumChloride as salt\n"); 85 | 86 | /* Tests 4-6 repeat tests 1-3 with a different reference vector */ 87 | 88 | retval = libscrypt_scrypt((uint8_t*)"pleaseletmein",strlen("pleaseletmein"), (uint8_t*)"SodiumChloride", strlen("SodiumChloride"), 16384, 8, 1, hashbuf, sizeof(hashbuf)); 89 | 90 | if(retval != 0) 91 | { 92 | printf("TEST FOUR FAILED: Failed to create hash of 'pleaseletmein'\n"); 93 | exit(EXIT_FAILURE); 94 | } 95 | 96 | printf("TEST FOUR: SUCCESSFUL\n"); 97 | 98 | /* Convert the binary string to hex representation. Outbuf must be 99 | * at least sizeof(hashbuf) * 2 + 1 100 | */ 101 | printf("TEST FIVE: Convert binary output to hex\n"); 102 | retval = libscrypt_hexconvert(hashbuf, sizeof(hashbuf), outbuf, sizeof(outbuf)); 103 | if(!retval) 104 | { 105 | printf("TEST FIVE: FAILED\n"); 106 | exit(EXIT_FAILURE); 107 | } 108 | printf("TEST FIVE: SUCCESSFUL, Hex output is:\n%s\n", outbuf); 109 | 110 | printf("TEST SIX: Compare hex output to reference hash output\n"); 111 | 112 | if(strcmp(outbuf, REF2) != 0) 113 | { 114 | printf("TEST SIX: FAILED to match reference on hash\n"); 115 | exit(EXIT_FAILURE); 116 | } 117 | else 118 | { 119 | printf("TEST SIX: SUCCESSUL, Test vector matched!\n"); 120 | } 121 | 122 | /* This function will convert the binary output to BASE64. Although 123 | * we converted to hex for the reference vectors, BASE64 is more useful. 124 | * Returns -1 on error, else returns length. 125 | * Correct buffer length can be determined using the below function if 126 | retuired. 127 | * char* dest = (char*) malloc(modp_b64_encode_len); 128 | * Note that this is not an exported function 129 | */ 130 | 131 | printf("TEST SEVEN: BASE64 encoding the salt and hash output\n"); 132 | 133 | retval = libscrypt_b64_encode_compliant(hashbuf, sizeof(hashbuf), outbuf, sizeof(outbuf)); 134 | if(retval == -1) 135 | { 136 | printf("TEST SEVEN FAILED\n"); 137 | exit(EXIT_FAILURE); 138 | } 139 | retval = libscrypt_b64_encode_compliant((unsigned char*)"SodiumChloride", strlen("SodiumChloride"), saltbuf, sizeof(saltbuf)); 140 | if(retval == -1) 141 | { 142 | printf("TEST SEVEN FAILED\n"); 143 | exit(EXIT_FAILURE); 144 | } 145 | 146 | printf("TEST SEVEN: SUCCESSFUL\n"); 147 | 148 | printf("TEST EIGHT: Create an MCF format output\n"); 149 | 150 | /* Creates a standard format output 151 | * int crypto_scrypt_mcf(uint32_t N, uint32_t r, uint32_t p, char *salt, char *hash, char *mcf); 152 | * Returns 0 on error, most likely reason is log2(N) not an integer. 153 | */ 154 | retval = libscrypt_mcf(16384, 8, 1, saltbuf, outbuf, mcf); 155 | if(!retval) 156 | { 157 | printf("TEST EIGHT FAILED\n"); 158 | exit(EXIT_FAILURE); 159 | } 160 | 161 | printf("TEST EIGHT: SUCCESSFUL, calculated mcf\n%s\n", mcf); 162 | 163 | /* Since later calls to scrypt_check() butcher mcf, make a second */ 164 | strcpy(mcf2, mcf); 165 | 166 | /* Couldn't be simpler - for a given mcf, check is the password is valid 167 | * Returns < 0 on failure to calculate hash 168 | * 0 if password incorrect 169 | * >1 if password correct 170 | */ 171 | 172 | printf("TEST NINE: Password verify on given MCF\n"); 173 | retval = libscrypt_check(mcf, "pleaseletmein"); 174 | 175 | if(retval < 0) 176 | { 177 | printf("TEST NINE: FAILED, hash failed to calculate\n"); 178 | exit(EXIT_FAILURE); 179 | } 180 | if(retval == 0) 181 | { 182 | printf("TEST NINE: FAILED, claimed pleaseletmein hash claimed did not verify\n"); 183 | exit(EXIT_FAILURE); 184 | } 185 | /* retval >0 is a success */ 186 | printf("TEST NINE: SUCCESSFUL, tested pleaseletmein password\n"); 187 | 188 | printf("TEST TEN: Password verify on same MCF, incorrect password\n"); 189 | retval = libscrypt_check(mcf2, "pleasefailme"); 190 | 191 | if(retval < 0) 192 | { 193 | printf("TEST TEN: FAILED, hash failed to calculate\n"); 194 | exit(EXIT_FAILURE); 195 | } 196 | if(retval > 0) 197 | { 198 | printf("TEST TEN: FAILED, fail hash has passed\n"); 199 | exit(EXIT_FAILURE); 200 | } 201 | 202 | printf("TEST TEN: SUCCESSFUL, refused incorrect password\n"); 203 | 204 | printf("TEST ELEVEN: Testing salt generator\n"); 205 | 206 | retval = libscrypt_salt_gen((uint8_t*)saltbuf, SCRYPT_SALT_LEN); 207 | if(retval == -1) 208 | { 209 | printf("TEST ELEVEN (salt generate) FAILED\n"); 210 | exit(EXIT_FAILURE); 211 | } 212 | 213 | retval = libscrypt_b64_encode_compliant((uint8_t*)saltbuf, SCRYPT_SALT_LEN, outbuf, sizeof(outbuf)); 214 | if(retval == -1) 215 | { 216 | printf("TEST ELEVEN (b64 encode) FAILED\n"); 217 | exit(EXIT_FAILURE); 218 | } 219 | printf("TEST ELEVEN: SUCCESSFUL, Generated %s\n", outbuf); 220 | 221 | printf("TEST TWELVE: Simple hash creation\n"); 222 | 223 | retval = libscrypt_hash(outbuf, "My cats's breath smells like cat food", SCRYPT_N, SCRYPT_r, SCRYPT_p); 224 | if(!retval) 225 | { 226 | printf("TEST TWELVE: FAILED, Failed to create simple hash\n"); 227 | exit(EXIT_FAILURE); 228 | } 229 | printf("TEST TWELVE: SUCCESSFUL. Received the following from simple hash:\n%s\n", outbuf); 230 | 231 | printf("TEST THIRTEEN: Verify test twelve's hash\n"); 232 | 233 | retval = libscrypt_check(outbuf, "My cats's breath smells like cat food"); 234 | 235 | if (retval != 1) { 236 | printf("TEST THIRTEEN: FAILED, hash not verified\n"); 237 | exit(EXIT_FAILURE); 238 | } 239 | 240 | printf("TEST THIRTEEN: SUCCESSFUL\n"); 241 | 242 | return 0; 243 | } 244 | 245 | -------------------------------------------------------------------------------- /libscrypt/sha256.c: -------------------------------------------------------------------------------- 1 | /*- 2 | * Copyright 2005,2007,2009 Colin Percival 3 | * All rights reserved. 4 | * 5 | * Redistribution and use in source and binary forms, with or without 6 | * modification, are permitted provided that the following conditions 7 | * are met: 8 | * 1. Redistributions of source code must retain the above copyright 9 | * notice, this list of conditions and the following disclaimer. 10 | * 2. Redistributions in binary form must reproduce the above copyright 11 | * notice, this list of conditions and the following disclaimer in the 12 | * documentation and/or other materials provided with the distribution. 13 | * 14 | * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 15 | * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 16 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 17 | * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 18 | * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 19 | * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 20 | * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 21 | * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 22 | * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 23 | * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 24 | * SUCH DAMAGE. 25 | */ 26 | 27 | #include 28 | 29 | #include 30 | #include 31 | 32 | #include "sysendian.h" 33 | 34 | #include "sha256.h" 35 | 36 | /* 37 | * Encode a length len/4 vector of (uint32_t) into a length len vector of 38 | * (unsigned char) in big-endian form. Assumes len is a multiple of 4. 39 | */ 40 | static void 41 | be32enc_vect(unsigned char *dst, const uint32_t *src, size_t len) 42 | { 43 | size_t i; 44 | 45 | for (i = 0; i < len / 4; i++) 46 | be32enc(dst + i * 4, src[i]); 47 | } 48 | 49 | /* 50 | * Decode a big-endian length len vector of (unsigned char) into a length 51 | * len/4 vector of (uint32_t). Assumes len is a multiple of 4. 52 | */ 53 | static void 54 | be32dec_vect(uint32_t *dst, const unsigned char *src, size_t len) 55 | { 56 | size_t i; 57 | 58 | for (i = 0; i < len / 4; i++) 59 | dst[i] = be32dec(src + i * 4); 60 | } 61 | 62 | /* Elementary functions used by SHA256 */ 63 | #define Ch(x, y, z) ((x & (y ^ z)) ^ z) 64 | #define Maj(x, y, z) ((x & (y | z)) | (y & z)) 65 | #define SHR(x, n) (x >> n) 66 | #define ROTR(x, n) ((x >> n) | (x << (32 - n))) 67 | #define S0(x) (ROTR(x, 2) ^ ROTR(x, 13) ^ ROTR(x, 22)) 68 | #define S1(x) (ROTR(x, 6) ^ ROTR(x, 11) ^ ROTR(x, 25)) 69 | #define s0(x) (ROTR(x, 7) ^ ROTR(x, 18) ^ SHR(x, 3)) 70 | #define s1(x) (ROTR(x, 17) ^ ROTR(x, 19) ^ SHR(x, 10)) 71 | 72 | /* SHA256 round function */ 73 | #define RND(a, b, c, d, e, f, g, h, k) \ 74 | t0 = h + S1(e) + Ch(e, f, g) + k; \ 75 | t1 = S0(a) + Maj(a, b, c); \ 76 | d += t0; \ 77 | h = t0 + t1; 78 | 79 | /* Adjusted round function for rotating state */ 80 | #define RNDr(S, W, i, k) \ 81 | RND(S[(64 - i) % 8], S[(65 - i) % 8], \ 82 | S[(66 - i) % 8], S[(67 - i) % 8], \ 83 | S[(68 - i) % 8], S[(69 - i) % 8], \ 84 | S[(70 - i) % 8], S[(71 - i) % 8], \ 85 | W[i] + k) 86 | 87 | /* 88 | * SHA256 block compression function. The 256-bit state is transformed via 89 | * the 512-bit input block to produce a new state. 90 | */ 91 | static void 92 | SHA256_Transform(uint32_t * state, const unsigned char block[64]) 93 | { 94 | uint32_t W[64]; 95 | uint32_t S[8]; 96 | uint32_t t0, t1; 97 | int i; 98 | 99 | /* 1. Prepare message schedule W. */ 100 | be32dec_vect(W, block, 64); 101 | for (i = 16; i < 64; i++) 102 | W[i] = s1(W[i - 2]) + W[i - 7] + s0(W[i - 15]) + W[i - 16]; 103 | 104 | /* 2. Initialize working variables. */ 105 | memcpy(S, state, 32); 106 | 107 | /* 3. Mix. */ 108 | RNDr(S, W, 0, 0x428a2f98); 109 | RNDr(S, W, 1, 0x71374491); 110 | RNDr(S, W, 2, 0xb5c0fbcf); 111 | RNDr(S, W, 3, 0xe9b5dba5); 112 | RNDr(S, W, 4, 0x3956c25b); 113 | RNDr(S, W, 5, 0x59f111f1); 114 | RNDr(S, W, 6, 0x923f82a4); 115 | RNDr(S, W, 7, 0xab1c5ed5); 116 | RNDr(S, W, 8, 0xd807aa98); 117 | RNDr(S, W, 9, 0x12835b01); 118 | RNDr(S, W, 10, 0x243185be); 119 | RNDr(S, W, 11, 0x550c7dc3); 120 | RNDr(S, W, 12, 0x72be5d74); 121 | RNDr(S, W, 13, 0x80deb1fe); 122 | RNDr(S, W, 14, 0x9bdc06a7); 123 | RNDr(S, W, 15, 0xc19bf174); 124 | RNDr(S, W, 16, 0xe49b69c1); 125 | RNDr(S, W, 17, 0xefbe4786); 126 | RNDr(S, W, 18, 0x0fc19dc6); 127 | RNDr(S, W, 19, 0x240ca1cc); 128 | RNDr(S, W, 20, 0x2de92c6f); 129 | RNDr(S, W, 21, 0x4a7484aa); 130 | RNDr(S, W, 22, 0x5cb0a9dc); 131 | RNDr(S, W, 23, 0x76f988da); 132 | RNDr(S, W, 24, 0x983e5152); 133 | RNDr(S, W, 25, 0xa831c66d); 134 | RNDr(S, W, 26, 0xb00327c8); 135 | RNDr(S, W, 27, 0xbf597fc7); 136 | RNDr(S, W, 28, 0xc6e00bf3); 137 | RNDr(S, W, 29, 0xd5a79147); 138 | RNDr(S, W, 30, 0x06ca6351); 139 | RNDr(S, W, 31, 0x14292967); 140 | RNDr(S, W, 32, 0x27b70a85); 141 | RNDr(S, W, 33, 0x2e1b2138); 142 | RNDr(S, W, 34, 0x4d2c6dfc); 143 | RNDr(S, W, 35, 0x53380d13); 144 | RNDr(S, W, 36, 0x650a7354); 145 | RNDr(S, W, 37, 0x766a0abb); 146 | RNDr(S, W, 38, 0x81c2c92e); 147 | RNDr(S, W, 39, 0x92722c85); 148 | RNDr(S, W, 40, 0xa2bfe8a1); 149 | RNDr(S, W, 41, 0xa81a664b); 150 | RNDr(S, W, 42, 0xc24b8b70); 151 | RNDr(S, W, 43, 0xc76c51a3); 152 | RNDr(S, W, 44, 0xd192e819); 153 | RNDr(S, W, 45, 0xd6990624); 154 | RNDr(S, W, 46, 0xf40e3585); 155 | RNDr(S, W, 47, 0x106aa070); 156 | RNDr(S, W, 48, 0x19a4c116); 157 | RNDr(S, W, 49, 0x1e376c08); 158 | RNDr(S, W, 50, 0x2748774c); 159 | RNDr(S, W, 51, 0x34b0bcb5); 160 | RNDr(S, W, 52, 0x391c0cb3); 161 | RNDr(S, W, 53, 0x4ed8aa4a); 162 | RNDr(S, W, 54, 0x5b9cca4f); 163 | RNDr(S, W, 55, 0x682e6ff3); 164 | RNDr(S, W, 56, 0x748f82ee); 165 | RNDr(S, W, 57, 0x78a5636f); 166 | RNDr(S, W, 58, 0x84c87814); 167 | RNDr(S, W, 59, 0x8cc70208); 168 | RNDr(S, W, 60, 0x90befffa); 169 | RNDr(S, W, 61, 0xa4506ceb); 170 | RNDr(S, W, 62, 0xbef9a3f7); 171 | RNDr(S, W, 63, 0xc67178f2); 172 | 173 | /* 4. Mix local working variables into global state */ 174 | for (i = 0; i < 8; i++) 175 | state[i] += S[i]; 176 | 177 | /* Clean the stack. */ 178 | memset(W, 0, 256); 179 | memset(S, 0, 32); 180 | t0 = t1 = 0; 181 | } 182 | 183 | static unsigned char PAD[64] = { 184 | 0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 185 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 186 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 187 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 188 | }; 189 | 190 | /* Add padding and terminating bit-count. */ 191 | static void 192 | SHA256_Pad(SHA256_CTX * ctx) 193 | { 194 | unsigned char len[8]; 195 | uint32_t r, plen; 196 | 197 | /* 198 | * Convert length to a vector of bytes -- we do this now rather 199 | * than later because the length will change after we pad. 200 | */ 201 | be32enc_vect(len, ctx->count, 8); 202 | 203 | /* Add 1--64 bytes so that the resulting length is 56 mod 64 */ 204 | r = (ctx->count[1] >> 3) & 0x3f; 205 | plen = (r < 56) ? (56 - r) : (120 - r); 206 | libscrypt_SHA256_Update(ctx, PAD, (size_t)plen); 207 | 208 | /* Add the terminating bit-count */ 209 | libscrypt_SHA256_Update(ctx, len, 8); 210 | } 211 | 212 | /* SHA-256 initialization. Begins a SHA-256 operation. */ 213 | void 214 | libscrypt_SHA256_Init(SHA256_CTX * ctx) 215 | { 216 | 217 | /* Zero bits processed so far */ 218 | ctx->count[0] = ctx->count[1] = 0; 219 | 220 | /* Magic initialization constants */ 221 | ctx->state[0] = 0x6A09E667; 222 | ctx->state[1] = 0xBB67AE85; 223 | ctx->state[2] = 0x3C6EF372; 224 | ctx->state[3] = 0xA54FF53A; 225 | ctx->state[4] = 0x510E527F; 226 | ctx->state[5] = 0x9B05688C; 227 | ctx->state[6] = 0x1F83D9AB; 228 | ctx->state[7] = 0x5BE0CD19; 229 | } 230 | 231 | /* Add bytes into the hash */ 232 | void 233 | libscrypt_SHA256_Update(SHA256_CTX * ctx, const void *in, size_t len) 234 | { 235 | uint32_t bitlen[2]; 236 | uint32_t r; 237 | const unsigned char *src = in; 238 | 239 | /* Number of bytes left in the buffer from previous updates */ 240 | r = (ctx->count[1] >> 3) & 0x3f; 241 | 242 | /* Convert the length into a number of bits */ 243 | bitlen[1] = ((uint32_t)len) << 3; 244 | bitlen[0] = (uint32_t)(len >> 29); 245 | 246 | /* Update number of bits */ 247 | if ((ctx->count[1] += bitlen[1]) < bitlen[1]) 248 | ctx->count[0]++; 249 | ctx->count[0] += bitlen[0]; 250 | 251 | /* Handle the case where we don't need to perform any transforms */ 252 | if (len < 64 - r) { 253 | memcpy(&ctx->buf[r], src, len); 254 | return; 255 | } 256 | 257 | /* Finish the current block */ 258 | memcpy(&ctx->buf[r], src, 64 - r); 259 | SHA256_Transform(ctx->state, ctx->buf); 260 | src += 64 - r; 261 | len -= 64 - r; 262 | 263 | /* Perform complete blocks */ 264 | while (len >= 64) { 265 | SHA256_Transform(ctx->state, src); 266 | src += 64; 267 | len -= 64; 268 | } 269 | 270 | /* Copy left over data into buffer */ 271 | memcpy(ctx->buf, src, len); 272 | } 273 | 274 | /* 275 | * SHA-256 finalization. Pads the input data, exports the hash value, 276 | * and clears the context state. 277 | */ 278 | void 279 | libscrypt_SHA256_Final(unsigned char digest[32], SHA256_CTX * ctx) 280 | { 281 | 282 | /* Add padding */ 283 | SHA256_Pad(ctx); 284 | 285 | /* Write the hash */ 286 | be32enc_vect(digest, ctx->state, 32); 287 | 288 | /* Clear the context state */ 289 | memset((void *)ctx, 0, sizeof(*ctx)); 290 | } 291 | 292 | /* Initialize an HMAC-SHA256 operation with the given key. */ 293 | void 294 | libscrypt_HMAC_SHA256_Init(HMAC_SHA256_CTX * ctx, const void * _K, size_t Klen) 295 | { 296 | unsigned char pad[64]; 297 | unsigned char khash[32]; 298 | const unsigned char * K = _K; 299 | size_t i; 300 | 301 | /* If Klen > 64, the key is really SHA256(K). */ 302 | if (Klen > 64) { 303 | libscrypt_SHA256_Init(&ctx->ictx); 304 | libscrypt_SHA256_Update(&ctx->ictx, K, Klen); 305 | libscrypt_SHA256_Final(khash, &ctx->ictx); 306 | K = khash; 307 | Klen = 32; 308 | } 309 | 310 | /* Inner SHA256 operation is SHA256(K xor [block of 0x36] || data). */ 311 | libscrypt_SHA256_Init(&ctx->ictx); 312 | memset(pad, 0x36, 64); 313 | for (i = 0; i < Klen; i++) 314 | pad[i] ^= K[i]; 315 | libscrypt_SHA256_Update(&ctx->ictx, pad, 64); 316 | 317 | /* Outer SHA256 operation is SHA256(K xor [block of 0x5c] || hash). */ 318 | libscrypt_SHA256_Init(&ctx->octx); 319 | memset(pad, 0x5c, 64); 320 | for (i = 0; i < Klen; i++) 321 | pad[i] ^= K[i]; 322 | libscrypt_SHA256_Update(&ctx->octx, pad, 64); 323 | 324 | /* Clean the stack. */ 325 | memset(khash, 0, 32); 326 | } 327 | 328 | /* Add bytes to the HMAC-SHA256 operation. */ 329 | void 330 | libscrypt_HMAC_SHA256_Update(HMAC_SHA256_CTX * ctx, const void *in, size_t len) 331 | { 332 | 333 | /* Feed data to the inner SHA256 operation. */ 334 | libscrypt_SHA256_Update(&ctx->ictx, in, len); 335 | } 336 | 337 | /* Finish an HMAC-SHA256 operation. */ 338 | void 339 | libscrypt_HMAC_SHA256_Final(unsigned char digest[32], HMAC_SHA256_CTX * ctx) 340 | { 341 | unsigned char ihash[32]; 342 | 343 | /* Finish the inner SHA256 operation. */ 344 | libscrypt_SHA256_Final(ihash, &ctx->ictx); 345 | 346 | /* Feed the inner hash to the outer SHA256 operation. */ 347 | libscrypt_SHA256_Update(&ctx->octx, ihash, 32); 348 | 349 | /* Finish the outer SHA256 operation. */ 350 | libscrypt_SHA256_Final(digest, &ctx->octx); 351 | 352 | /* Clean the stack. */ 353 | memset(ihash, 0, 32); 354 | } 355 | 356 | /** 357 | * PBKDF2_SHA256(passwd, passwdlen, salt, saltlen, c, buf, dkLen): 358 | * Compute PBKDF2(passwd, salt, c, dkLen) using HMAC-SHA256 as the PRF, and 359 | * write the output to buf. The value dkLen must be at most 32 * (2^32 - 1). 360 | */ 361 | void 362 | libscrypt_PBKDF2_SHA256(const uint8_t * passwd, size_t passwdlen, const uint8_t * salt, 363 | size_t saltlen, uint64_t c, uint8_t * buf, size_t dkLen) 364 | { 365 | HMAC_SHA256_CTX PShctx, hctx; 366 | size_t i; 367 | uint8_t ivec[4]; 368 | uint8_t U[32]; 369 | uint8_t T[32]; 370 | uint64_t j; 371 | int k; 372 | size_t clen; 373 | 374 | /* Compute HMAC state after processing P and S. */ 375 | libscrypt_HMAC_SHA256_Init(&PShctx, passwd, passwdlen); 376 | libscrypt_HMAC_SHA256_Update(&PShctx, salt, saltlen); 377 | 378 | /* Iterate through the blocks. */ 379 | for (i = 0; i * 32 < dkLen; i++) { 380 | /* Generate INT(i + 1). */ 381 | be32enc(ivec, (uint32_t)(i + 1)); 382 | 383 | /* Compute U_1 = PRF(P, S || INT(i)). */ 384 | memcpy(&hctx, &PShctx, sizeof(HMAC_SHA256_CTX)); 385 | libscrypt_HMAC_SHA256_Update(&hctx, ivec, 4); 386 | libscrypt_HMAC_SHA256_Final(U, &hctx); 387 | 388 | /* T_i = U_1 ... */ 389 | memcpy(T, U, 32); 390 | 391 | for (j = 2; j <= c; j++) { 392 | /* Compute U_j. */ 393 | libscrypt_HMAC_SHA256_Init(&hctx, passwd, passwdlen); 394 | libscrypt_HMAC_SHA256_Update(&hctx, U, 32); 395 | libscrypt_HMAC_SHA256_Final(U, &hctx); 396 | 397 | /* ... xor U_j ... */ 398 | for (k = 0; k < 32; k++) 399 | T[k] ^= U[k]; 400 | } 401 | 402 | /* Copy as many bytes as necessary into buf. */ 403 | clen = dkLen - i * 32; 404 | if (clen > 32) 405 | clen = 32; 406 | memcpy(&buf[i * 32], T, clen); 407 | } 408 | 409 | /* Clean PShctx, since we never called _Final on it. */ 410 | memset(&PShctx, 0, sizeof(HMAC_SHA256_CTX)); 411 | } 412 | -------------------------------------------------------------------------------- /libscrypt/sha256.h: -------------------------------------------------------------------------------- 1 | /*- 2 | * Copyright 2005,2007,2009 Colin Percival 3 | * All rights reserved. 4 | * 5 | * Redistribution and use in source and binary forms, with or without 6 | * modification, are permitted provided that the following conditions 7 | * are met: 8 | * 1. Redistributions of source code must retain the above copyright 9 | * notice, this list of conditions and the following disclaimer. 10 | * 2. Redistributions in binary form must reproduce the above copyright 11 | * notice, this list of conditions and the following disclaimer in the 12 | * documentation and/or other materials provided with the distribution. 13 | * 14 | * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 15 | * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 16 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 17 | * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 18 | * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 19 | * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 20 | * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 21 | * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 22 | * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 23 | * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 24 | * SUCH DAMAGE. 25 | * 26 | * $FreeBSD: src/lib/libmd/sha256.h,v 1.2 2006/01/17 15:35:56 phk Exp $ 27 | */ 28 | 29 | #ifndef _SHA256_H_ 30 | #define _SHA256_H_ 31 | 32 | #include 33 | 34 | #include 35 | 36 | typedef struct libscrypt_SHA256Context { 37 | uint32_t state[8]; 38 | uint32_t count[2]; 39 | unsigned char buf[64]; 40 | } SHA256_CTX; 41 | 42 | typedef struct libscrypt_HMAC_SHA256Context { 43 | SHA256_CTX ictx; 44 | SHA256_CTX octx; 45 | } HMAC_SHA256_CTX; 46 | 47 | void libscrypt_SHA256_Init(/*@out@*/ SHA256_CTX *); 48 | void libscrypt_SHA256_Update(SHA256_CTX *, const void *, size_t); 49 | 50 | /* Original declaration: 51 | * void SHA256_Final(unsigned char [32], SHA256_CTX *); 52 | */ 53 | void libscrypt_SHA256_Final(/*@out@*/ unsigned char [], SHA256_CTX *); 54 | void libscrypt_HMAC_SHA256_Init(HMAC_SHA256_CTX *, const void *, size_t); 55 | void libscrypt_HMAC_SHA256_Update(HMAC_SHA256_CTX *, const void *, size_t); 56 | 57 | /* Original declaration: 58 | * void HMAC_SHA256_Final(unsigned char [32], HMAC_SHA256_CTX *); 59 | */ 60 | void libscrypt_HMAC_SHA256_Final(unsigned char [], HMAC_SHA256_CTX *); 61 | 62 | /** 63 | * PBKDF2_SHA256(passwd, passwdlen, salt, saltlen, c, buf, dkLen): 64 | * Compute PBKDF2(passwd, salt, c, dkLen) using HMAC-SHA256 as the PRF, and 65 | * write the output to buf. The value dkLen must be at most 32 * (2^32 - 1). 66 | */ 67 | void libscrypt_PBKDF2_SHA256(const uint8_t *, size_t, const uint8_t *, size_t, 68 | uint64_t, uint8_t *, size_t); 69 | 70 | #endif /* !_SHA256_H_ */ 71 | -------------------------------------------------------------------------------- /libscrypt/skey.h: -------------------------------------------------------------------------------- 1 | int libscrypt_skey_encode(unsigned char const *src, size_t srclength, 2 | /*@out@*/ char *target, size_t targetsize); 3 | -------------------------------------------------------------------------------- /libscrypt/slowequals.c: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | /* Implements a constant time version of strcmp() 4 | * Will return 1 if a and b are equal, 0 if they are not */ 5 | int slow_equals(const char* a, const char* b) 6 | { 7 | size_t lena, lenb, diff, i; 8 | lena = strlen(a); 9 | lenb = strlen(b); 10 | diff = strlen(a) ^ strlen(b); 11 | 12 | for(i=0; i we have isn't usable. */ 34 | #if !HAVE_DECL_BE64ENC 35 | #undef HAVE_SYS_ENDIAN_H 36 | #endif 37 | 38 | #ifdef HAVE_SYS_ENDIAN_H 39 | 40 | #include 41 | 42 | #else 43 | 44 | #include 45 | #ifdef _MSC_VER 46 | #define INLINE __inline 47 | #else 48 | #define INLINE inline 49 | #endif 50 | 51 | static INLINE uint32_t 52 | be32dec(const void *pp) 53 | { 54 | const uint8_t *p = (uint8_t const *)pp; 55 | 56 | return ((uint32_t)(p[3]) + ((uint32_t)(p[2]) << 8) + 57 | ((uint32_t)(p[1]) << 16) + ((uint32_t)(p[0]) << 24)); 58 | } 59 | 60 | static INLINE void 61 | be32enc(void *pp, uint32_t x) 62 | { 63 | uint8_t * p = (uint8_t *)pp; 64 | 65 | p[3] = x & 0xff; 66 | p[2] = (x >> 8) & 0xff; 67 | p[1] = (x >> 16) & 0xff; 68 | p[0] = (x >> 24) & 0xff; 69 | } 70 | 71 | static INLINE uint64_t 72 | be64dec(const void *pp) 73 | { 74 | const uint8_t *p = (uint8_t const *)pp; 75 | 76 | return ((uint64_t)(p[7]) + ((uint64_t)(p[6]) << 8) + 77 | ((uint64_t)(p[5]) << 16) + ((uint64_t)(p[4]) << 24) + 78 | ((uint64_t)(p[3]) << 32) + ((uint64_t)(p[2]) << 40) + 79 | ((uint64_t)(p[1]) << 48) + ((uint64_t)(p[0]) << 56)); 80 | } 81 | 82 | static INLINE void 83 | be64enc(void *pp, uint64_t x) 84 | { 85 | uint8_t * p = (uint8_t *)pp; 86 | 87 | p[7] = x & 0xff; 88 | p[6] = (x >> 8) & 0xff; 89 | p[5] = (x >> 16) & 0xff; 90 | p[4] = (x >> 24) & 0xff; 91 | p[3] = (x >> 32) & 0xff; 92 | p[2] = (x >> 40) & 0xff; 93 | p[1] = (x >> 48) & 0xff; 94 | p[0] = (x >> 56) & 0xff; 95 | } 96 | 97 | static INLINE uint32_t 98 | le32dec(const void *pp) 99 | { 100 | const uint8_t *p = (uint8_t const *)pp; 101 | 102 | return ((uint32_t)(p[0]) + ((uint32_t)(p[1]) << 8) + 103 | ((uint32_t)(p[2]) << 16) + ((uint32_t)(p[3]) << 24)); 104 | } 105 | 106 | static INLINE void 107 | le32enc(void *pp, uint32_t x) 108 | { 109 | uint8_t * p = (uint8_t *)pp; 110 | 111 | p[0] = x & 0xff; 112 | p[1] = (x >> 8) & 0xff; 113 | p[2] = (x >> 16) & 0xff; 114 | p[3] = (x >> 24) & 0xff; 115 | } 116 | 117 | static INLINE uint64_t 118 | le64dec(const void *pp) 119 | { 120 | const uint8_t *p = (uint8_t const *)pp; 121 | 122 | return ((uint64_t)(p[0]) + ((uint64_t)(p[1]) << 8) + 123 | ((uint64_t)(p[2]) << 16) + ((uint64_t)(p[3]) << 24) + 124 | ((uint64_t)(p[4]) << 32) + ((uint64_t)(p[5]) << 40) + 125 | ((uint64_t)(p[6]) << 48) + ((uint64_t)(p[7]) << 56)); 126 | } 127 | 128 | static INLINE void 129 | le64enc(void *pp, uint64_t x) 130 | { 131 | uint8_t * p = (uint8_t *)pp; 132 | 133 | p[0] = x & 0xff; 134 | p[1] = (x >> 8) & 0xff; 135 | p[2] = (x >> 16) & 0xff; 136 | p[3] = (x >> 24) & 0xff; 137 | p[4] = (x >> 32) & 0xff; 138 | p[5] = (x >> 40) & 0xff; 139 | p[6] = (x >> 48) & 0xff; 140 | p[7] = (x >> 56) & 0xff; 141 | } 142 | #endif /* !HAVE_SYS_ENDIAN_H */ 143 | 144 | #endif /* !_SYSENDIAN_H_ */ 145 | -------------------------------------------------------------------------------- /libscrypt/z85.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2013 Stanislav Artemkin . 3 | * 4 | * Redistribution and use in source and binary forms, with or without 5 | * modification, are permitted provided that the following conditions are 6 | * met: 7 | * 8 | * * Redistributions of source code must retain the above copyright 9 | * notice, this list of conditions and the following disclaimer. 10 | * * Redistributions in binary form must reproduce the above 11 | * copyright notice, this list of conditions and the following disclaimer 12 | * in the documentation and/or other materials provided with the 13 | * distribution. 14 | * 15 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 16 | * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 17 | * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 18 | * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 19 | * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 20 | * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 21 | * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 22 | * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 23 | * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 24 | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 25 | * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 26 | * 27 | * Implementation of 32/Z85 specification (http://rfc.zeromq.org/spec:32/Z85) 28 | * Source repository: http://github.com/artemkin/z85 29 | */ 30 | 31 | #include 32 | #include 33 | #include 34 | 35 | #include "z85.h" 36 | 37 | typedef unsigned int uint32_t; 38 | typedef unsigned char byte; 39 | 40 | // make sure uint32_t is 32-bit 41 | typedef char Z85_uint32_t_static_assert[(sizeof(uint32_t) * CHAR_BIT == 32) * 2 - 1]; 42 | 43 | #define DIV85_MAGIC 3233857729ULL 44 | // make sure magic constant is 64-bit 45 | typedef char Z85_div85_magic_static_assert[(sizeof(DIV85_MAGIC) * CHAR_BIT == 64) * 2 - 1]; 46 | 47 | #define DIV85(number) ((uint32_t)((DIV85_MAGIC * number) >> 32) >> 6) 48 | 49 | static const char* base85 = 50 | { 51 | "0123456789" 52 | "abcdefghij" 53 | "klmnopqrst" 54 | "uvwxyzABCD" 55 | "EFGHIJKLMN" 56 | "OPQRSTUVWX" 57 | "YZ.-:+=^!/" 58 | "*?&<>()[]{" 59 | "}@%$#" 60 | }; 61 | 62 | static byte base256[] = 63 | { 64 | 0x00, 0x44, 0x00, 0x54, 0x53, 0x52, 0x48, 0x00, 65 | 0x4B, 0x4C, 0x46, 0x41, 0x00, 0x3F, 0x3E, 0x45, 66 | 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 67 | 0x08, 0x09, 0x40, 0x00, 0x49, 0x42, 0x4A, 0x47, 68 | 0x51, 0x24, 0x25, 0x26, 0x27, 0x28, 0x29, 0x2A, 69 | 0x2B, 0x2C, 0x2D, 0x2E, 0x2F, 0x30, 0x31, 0x32, 70 | 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x3A, 71 | 0x3B, 0x3C, 0x3D, 0x4D, 0x00, 0x4E, 0x43, 0x00, 72 | 0x00, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F, 0x10, 73 | 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 74 | 0x19, 0x1A, 0x1B, 0x1C, 0x1D, 0x1E, 0x1F, 0x20, 75 | 0x21, 0x22, 0x23, 0x4F, 0x00, 0x50, 0x00, 0x00 76 | }; 77 | 78 | int libscrypt_z85_encode(src, srclength, target, targsize) 79 | unsigned char const *src; 80 | size_t srclength; 81 | char *target; 82 | size_t targsize; 83 | { 84 | size_t datalength = 0; 85 | memset(target, 0, targsize); 86 | 87 | if (targsize < (Z85_encode_with_padding_bound(srclength) + 1)) { 88 | return (-1); //not enough space for output 89 | } 90 | 91 | //encode the input buffer, padding it if necessary 92 | datalength = Z85_encode_with_padding((const char * )src, target, srclength); 93 | if ( datalength == 0) 94 | return (-1); //something went wrong 95 | 96 | target[datalength] = '\0'; // write null terminating char 97 | return datalength; 98 | } 99 | 100 | int libscrypt_z85_decode(src, target, targsize) 101 | char const *src; 102 | unsigned char *target; 103 | size_t targsize; 104 | { 105 | size_t datalength = 0; 106 | if (targsize < (Z85_decode_with_padding_bound(src, strlen(src)) + 1)) { 107 | return (-1); //not enough space for output 108 | } 109 | 110 | //decode the input buffer, padding it if necessary 111 | datalength = Z85_decode_with_padding(src, (char *) target, strlen(src)); 112 | if ( datalength == 0) 113 | return (-1); //something went wrong 114 | 115 | target[datalength] = '\0'; // write null terminating char 116 | return datalength; 117 | } 118 | 119 | char* Z85_encode_unsafe(const char* source, const char* sourceEnd, char* dest) 120 | { 121 | byte* src = (byte*)source; 122 | byte* end = (byte*)sourceEnd; 123 | byte* dst = (byte*)dest; 124 | uint32_t value; 125 | uint32_t value2; 126 | 127 | for (; src != end; src += 4, dst += 5) 128 | { 129 | // unpack big-endian frame 130 | value = (src[0] << 24) | (src[1] << 16) | (src[2] << 8) | src[3]; 131 | 132 | value2 = DIV85(value); dst[4] = base85[value - value2 * 85]; value = value2; 133 | value2 = DIV85(value); dst[3] = base85[value - value2 * 85]; value = value2; 134 | value2 = DIV85(value); dst[2] = base85[value - value2 * 85]; value = value2; 135 | value2 = DIV85(value); dst[1] = base85[value - value2 * 85]; 136 | dst[0] = base85[value2]; 137 | } 138 | 139 | return (char*)dst; 140 | } 141 | 142 | char* Z85_decode_unsafe(const char* source, const char* sourceEnd, char* dest) 143 | { 144 | byte* src = (byte*)source; 145 | byte* end = (byte*)sourceEnd; 146 | byte* dst = (byte*)dest; 147 | uint32_t value; 148 | 149 | for (; src != end; src += 5, dst += 4) 150 | { 151 | value = base256[(src[0] - 32) & 127]; 152 | value = value * 85 + base256[(src[1] - 32) & 127]; 153 | value = value * 85 + base256[(src[2] - 32) & 127]; 154 | value = value * 85 + base256[(src[3] - 32) & 127]; 155 | value = value * 85 + base256[(src[4] - 32) & 127]; 156 | 157 | // pack big-endian frame 158 | dst[0] = value >> 24; 159 | dst[1] = (byte)(value >> 16); 160 | dst[2] = (byte)(value >> 8); 161 | dst[3] = (byte)(value); 162 | } 163 | 164 | return (char*)dst; 165 | } 166 | 167 | size_t Z85_encode_bound(size_t size) 168 | { 169 | return size * 5 / 4; 170 | } 171 | 172 | size_t Z85_decode_bound(size_t size) 173 | { 174 | return size * 4 / 5; 175 | } 176 | 177 | size_t Z85_encode(const char* source, char* dest, size_t inputSize) 178 | { 179 | if (!source || !dest || inputSize % 4) 180 | { 181 | assert(!"wrong source, destination or input size"); 182 | return 0; 183 | } 184 | 185 | return Z85_encode_unsafe(source, source + inputSize, dest) - dest; 186 | } 187 | 188 | size_t Z85_decode(const char* source, char* dest, size_t inputSize) 189 | { 190 | if (!source || !dest || inputSize % 5) 191 | { 192 | assert(!"wrong source, destination or input size"); 193 | return 0; 194 | } 195 | 196 | return Z85_decode_unsafe(source, source + inputSize, dest) - dest; 197 | } 198 | 199 | size_t Z85_encode_with_padding_bound(size_t size) 200 | { 201 | if (size == 0) return 0; 202 | size = Z85_encode_bound(size); 203 | return size + (5 - size % 5) % 5 + 1; 204 | } 205 | 206 | size_t Z85_decode_with_padding_bound(const char* source, size_t size) 207 | { 208 | if (size == 0 || !source || (byte)(source[0] - '0' - 1) > 3) return 0; 209 | return Z85_decode_bound(size - 1) - 4 + (source[0] - '0'); 210 | } 211 | 212 | size_t Z85_encode_with_padding(const char* source, char* dest, size_t inputSize) 213 | { 214 | size_t tailBytes = inputSize % 4; 215 | char tailBuf[4] = { 0 }; 216 | char* dst = dest; 217 | const char* end = source + inputSize - tailBytes; 218 | 219 | assert(source && dest); 220 | 221 | // zero length string is not padded 222 | if (!source || !dest || inputSize == 0) 223 | { 224 | return 0; 225 | } 226 | 227 | (dst++)[0] = (tailBytes == 0 ? '4' : '0' + (char)tailBytes); // write tail bytes count 228 | dst = Z85_encode_unsafe(source, end, dst); // write body 229 | 230 | // write tail 231 | switch (tailBytes) 232 | { 233 | case 3: 234 | tailBuf[2] = end[2]; 235 | case 2: 236 | tailBuf[1] = end[1]; 237 | case 1: 238 | tailBuf[0] = end[0]; 239 | dst = Z85_encode_unsafe(tailBuf, tailBuf + 4, dst); 240 | } 241 | 242 | return dst - dest; 243 | } 244 | 245 | size_t Z85_decode_with_padding(const char* source, char* dest, size_t inputSize) 246 | { 247 | char* dst = dest; 248 | size_t tailBytes; 249 | char tailBuf[4] = { 0 }; 250 | const char* end = source + inputSize; 251 | 252 | assert(source && dest && (inputSize == 0 || (inputSize - 1) % 5 == 0)); 253 | 254 | // zero length string is not padded 255 | if (!source || !dest || inputSize == 0 || (inputSize - 1) % 5) 256 | { 257 | return 0; 258 | } 259 | 260 | tailBytes = (source++)[0] - '0'; // possible values: 1, 2, 3 or 4 261 | if (tailBytes - 1 > 3) 262 | { 263 | assert(!"wrong tail bytes count"); 264 | return 0; 265 | } 266 | 267 | end -= 5; 268 | if (source != end) 269 | { 270 | // decode body 271 | dst = Z85_decode_unsafe(source, end, dst); 272 | } 273 | 274 | // decode last 5 bytes chunk 275 | Z85_decode_unsafe(end, end + 5, tailBuf); 276 | 277 | switch (tailBytes) 278 | { 279 | case 4: 280 | dst[3] = tailBuf[3]; 281 | case 3: 282 | dst[2] = tailBuf[2]; 283 | case 2: 284 | dst[1] = tailBuf[1]; 285 | case 1: 286 | dst[0] = tailBuf[0]; 287 | } 288 | 289 | return dst - dest + tailBytes; 290 | } 291 | -------------------------------------------------------------------------------- /libscrypt/z85.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2013 Stanislav Artemkin . 3 | * 4 | * Redistribution and use in source and binary forms, with or without 5 | * modification, are permitted provided that the following conditions are 6 | * met: 7 | * 8 | * * Redistributions of source code must retain the above copyright 9 | * notice, this list of conditions and the following disclaimer. 10 | * * Redistributions in binary form must reproduce the above 11 | * copyright notice, this list of conditions and the following disclaimer 12 | * in the documentation and/or other materials provided with the 13 | * distribution. 14 | * 15 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 16 | * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 17 | * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 18 | * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 19 | * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 20 | * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 21 | * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 22 | * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 23 | * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 24 | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 25 | * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 26 | * 27 | * Implementation of 32/Z85 specification (http://rfc.zeromq.org/spec:32/Z85) 28 | * Source repository: http://github.com/artemkin/z85 29 | */ 30 | 31 | #pragma once 32 | 33 | #include 34 | 35 | #if defined (__cplusplus) 36 | extern "C" { 37 | #endif 38 | 39 | /******************************************************************************* 40 | * libscrypt wrappers * 41 | *******************************************************************************/ 42 | int libscrypt_z85_encode(unsigned char const *src, size_t srclength, 43 | /*@out@*/ char *target, size_t targetsize); 44 | int libscrypt_z85_decode(char const *src, 45 | /*@out@*/ unsigned char *target, size_t targetsize); 46 | 47 | /******************************************************************************* 48 | * ZeroMQ Base-85 encoding/decoding functions with custom padding * 49 | *******************************************************************************/ 50 | 51 | /** 52 | * @brief Encodes 'inputSize' bytes from 'source' into 'dest'. 53 | * If 'inputSize' is not divisible by 4 with no remainder, 'source' is padded. 54 | * Destination buffer must be already allocated. Use Z85_encode_with_padding_bound() to 55 | * evaluate size of the destination buffer. 56 | * 57 | * @param source in, input buffer (binary string to be encoded) 58 | * @param dest out, destination buffer 59 | * @param inputSize in, number of bytes to be encoded 60 | * @return number of printable symbols written into 'dest' or 0 if something goes wrong 61 | */ 62 | size_t Z85_encode_with_padding(const char* source, char* dest, size_t inputSize); 63 | 64 | /** 65 | * @brief Decodes 'inputSize' printable symbols from 'source' into 'dest', 66 | * encoded with Z85_encode_with_padding(). 67 | * Destination buffer must be already allocated. Use Z85_decode_with_padding_bound() to 68 | * evaluate size of the destination buffer. 69 | * 70 | * @param source in, input buffer (printable string to be decoded) 71 | * @param dest out, destination buffer 72 | * @param inputSize in, number of symbols to be decoded 73 | * @return number of bytes written into 'dest' or 0 if something goes wrong 74 | */ 75 | size_t Z85_decode_with_padding(const char* source, char* dest, size_t inputSize); 76 | 77 | /** 78 | * @brief Evaluates a size of output buffer needed to encode 'size' bytes 79 | * into string of printable symbols using Z85_encode_with_padding(). 80 | * 81 | * @param size in, number of bytes to be encoded 82 | * @return minimal size of output buffer in bytes 83 | */ 84 | size_t Z85_encode_with_padding_bound(size_t size); 85 | 86 | /** 87 | * @brief Evaluates a size of output buffer needed to decode 'size' symbols 88 | * into binary string using Z85_decode_with_padding(). 89 | * 90 | * @param source in, input buffer (first symbol is read from 'source' to evaluate padding) 91 | * @param size in, number of symbols to be decoded 92 | * @return minimal size of output buffer in bytes 93 | */ 94 | size_t Z85_decode_with_padding_bound(const char* source, size_t size); 95 | 96 | 97 | 98 | /******************************************************************************* 99 | * ZeroMQ Base-85 encoding/decoding functions (specification compliant) * 100 | *******************************************************************************/ 101 | 102 | /** 103 | * @brief Encodes 'inputSize' bytes from 'source' into 'dest'. 104 | * If 'inputSize' is not divisible by 4 with no remainder, 0 is retured. 105 | * Destination buffer must be already allocated. Use Z85_encode_bound() to 106 | * evaluate size of the destination buffer. 107 | * 108 | * @param source in, input buffer (binary string to be encoded) 109 | * @param dest out, destination buffer 110 | * @param inputSize in, number of bytes to be encoded 111 | * @return number of printable symbols written into 'dest' or 0 if something goes wrong 112 | */ 113 | size_t Z85_encode(const char* source, char* dest, size_t inputSize); 114 | 115 | /** 116 | * @brief Decodes 'inputSize' printable symbols from 'source' into 'dest'. 117 | * If 'inputSize' is not divisible by 5 with no remainder, 0 is returned. 118 | * Destination buffer must be already allocated. Use Z85_decode_bound() to 119 | * evaluate size of the destination buffer. 120 | * 121 | * @param source in, input buffer (printable string to be decoded) 122 | * @param dest out, destination buffer 123 | * @param inputSize in, number of symbols to be decoded 124 | * @return number of bytes written into 'dest' or 0 if something goes wrong 125 | */ 126 | size_t Z85_decode(const char* source, char* dest, size_t inputSize); 127 | 128 | /** 129 | * @brief Evaluates a size of output buffer needed to encode 'size' bytes 130 | * into string of printable symbols using Z85_encode(). 131 | * 132 | * @param size in, number of bytes to be encoded 133 | * @return minimal size of output buffer in bytes 134 | */ 135 | size_t Z85_encode_bound(size_t size); 136 | 137 | /** 138 | * @brief Evaluates a size of output buffer needed to decode 'size' symbols 139 | * into binary string using Z85_decode(). 140 | * 141 | * @param size in, number of symbols to be decoded 142 | * @return minimal size of output buffer in bytes 143 | */ 144 | size_t Z85_decode_bound(size_t size); 145 | 146 | 147 | 148 | /******************************************************************************* 149 | * ZeroMQ Base-85 unsafe encoding/decoding functions (specification compliant) * 150 | *******************************************************************************/ 151 | 152 | /** 153 | * @brief Encodes bytes from [source;sourceEnd) range into 'dest'. 154 | * It can be used for implementation of your own padding scheme. 155 | * Preconditions: 156 | * - (sourceEnd - source) % 4 == 0 157 | * - destination buffer must be already allocated 158 | * 159 | * @param source in, begin of input buffer 160 | * @param sourceEnd in, end of input buffer (not included) 161 | * @param dest out, output buffer 162 | * @return a pointer immediately after last symbol written into the 'dest' 163 | */ 164 | char* Z85_encode_unsafe(const char* source, const char* sourceEnd, char* dest); 165 | 166 | /** 167 | * @brief Decodes symbols from [source;sourceEnd) range into 'dest'. 168 | * It can be used for implementation of your own padding scheme. 169 | * Preconditions: 170 | * - (sourceEnd - source) % 5 == 0 171 | * - destination buffer must be already allocated 172 | * 173 | * @param source in, begin of input buffer 174 | * @param sourceEnd in, end of input buffer (not included) 175 | * @param dest out, output buffer 176 | * @return a pointer immediately after last byte written into the 'dest' 177 | */ 178 | char* Z85_decode_unsafe(const char* source, const char* sourceEnd, char* dest); 179 | 180 | #if defined (__cplusplus) 181 | } 182 | #endif 183 | 184 | -------------------------------------------------------------------------------- /man/genpass.1: -------------------------------------------------------------------------------- 1 | .TH GENPASS "1" "January 2016" "genpass 2016.01.01" "User Commands" 2 | .SH NAME 3 | genpass \- A stateless password generator. 4 | .SH SYNOPSIS 5 | .B genpass 6 | [\fIoption\fR]... [\fIsite\fR] 7 | .SH DESCRIPTION 8 | Generate stateless passwords based on a two level hash scheme. 9 | .TP 10 | \fB\-n\fR, \fB\-\-name\fR "Full Name" 11 | name 12 | .TP 13 | \fB\-p\fR, \fB\-\-password\fR "Secret" 14 | master password 15 | .TP 16 | \fB\-s\fR, \fB\-\-site\fR "site.tld" 17 | site login 18 | .TP 19 | \fB\-r\fR, \fB\-\-registration\-mode\fR 20 | ask twice for master password 21 | .TP 22 | \fB\-f\fR, \fB\-\-file\fR FILE 23 | use|write cache key from|to FILE 24 | .TP 25 | \fB\-l\fR, \fB\-\-key\-length\fR 8\-1024 26 | key length in bytes, "32" by default 27 | .TP 28 | \fB\-C\fR, \fB\-\-cache\-cost\fR 1\-30 29 | cpu/memory cost for cache key, "20" by default 30 | .TP 31 | \fB\-c\fR, \fB\-\-cost\fR 1\-30 32 | cpu/memory cost for final key, "10" by default 33 | .TP 34 | \fB\-\-scrypt\-r\fR 1\-9999 35 | block size, "8" by default (advanced) 36 | .TP 37 | \fB\-\-scrypt\-p\fR 1\-99999 38 | parallelization, "16" by default (advanced) 39 | .TP 40 | \fB\-\-config\fR FILE 41 | read configuration from FILE 42 | .TP 43 | \fB\-N\fR, \fB\-\-dry\-run\fR 44 | perform a trial run with no changes made 45 | .TP 46 | \fB\-e\fR, \fB\-\-encoding\fR ENCODING 47 | password encoding output, "z85" by default. 48 | .PP 49 | ENCODING: dec|hex|base64|z85|skey 50 | .TP 51 | \fB\-1\fR, \fB\-\-single\fR 52 | use single function derivation 53 | .TP 54 | \fB\-v\fR, \fB\-\-verbose\fR 55 | verbose mode 56 | .TP 57 | \fB\-V\fR, \fB\-\-version\fR 58 | show version and exit 59 | .TP 60 | \fB\-h\fR, \fB\-\-help\fR 61 | show this help message and exit 62 | .SH "REPORTING BUGS" 63 | Report genpass bugs in 64 | .br 65 | .SH "SEE ALSO" 66 | Password Multiplier using iterated sha1 hashing, 2005. 67 | .br 68 | Stronger Key Derivation Via Sequential Memory-hard Functions, 2009. 69 | .PP 70 | getpass(1) 71 | -------------------------------------------------------------------------------- /man/getpass.1: -------------------------------------------------------------------------------- 1 | .TH GETPASS "1" "January 2016" "getpass 2016.01.01" "User Commands" 2 | .SH NAME 3 | getpass \- A wrapper around genpass, a stateless password generator. 4 | .SH SYNOPSIS 5 | .B getpass 6 | [\fIoption\fR]... \fIsite\fR 7 | .SH DESCRIPTION 8 | Generate stateless passwords based on a two level hash scheme. Environment lookup, system clipboard integration and graphical support. 9 | .TP 10 | \fB\-n\fR, \fB\-\-name\fR "Full Name" 11 | name 12 | .TP 13 | \fB\-p\fR, \fB\-\-password\fR "Secret" 14 | master password 15 | .TP 16 | \fB\-r\fR, \fB\-\-registration\-mode\fR 17 | ask twice for master password 18 | .TP 19 | \fB\-f\fR, \fB\-\-file\fR FILE 20 | use|write cache key from|to FILE 21 | .TP 22 | \fB\-l\fR, \fB\-\-key\-length\fR 8\-1024 23 | key length in bytes, "32" by default 24 | .TP 25 | \fB\-C\fR, \fB\-\-cache\-cost\fR 1\-30 26 | cpu/memory cost for cache key, "20" by default 27 | .TP 28 | \fB\-c\fR, \fB\-\-cost\fR 1\-30 29 | cpu/memory cost for final key, "10" by default 30 | .TP 31 | \fB\-\-scrypt\-r\fR 1\-9999 32 | block size, "8" by default (advanced) 33 | .TP 34 | \fB\-\-scrypt\-p\fR 1\-99999 35 | parallelization, "16" by default (advanced) 36 | .TP 37 | \fB\-\-config\fR FILE 38 | read configuration from FILE 39 | .TP 40 | \fB\-N\fR, \fB\-\-dry\-run\fR 41 | perform a trial run with no changes made 42 | .TP 43 | \fB\-e\fR, \fB\-\-encoding\fR ENCODING 44 | password encoding output, "z85" by default. 45 | .PP 46 | ENCODING: dec|hex|base64|z85|skey 47 | .TP 48 | \fB\-1\fR, \fB\-\-single\fR 49 | use single function derivation 50 | .TP 51 | \fB\-k\fR, \fB\-\-kill-after\fR SEC 52 | kill clipboard after N seconds, "10" by default, 0 to disable 53 | .TP 54 | \fB\-v\fR, \fB\-\-verbose\fR 55 | verbose mode 56 | .TP 57 | \fB\-V\fR, \fB\-\-version\fR 58 | show version and exit 59 | .TP 60 | \fB\-h\fR, \fB\-\-help\fR 61 | show this help message and exit 62 | .SH "REPORTING BUGS" 63 | Report getpass bugs in 64 | .br 65 | .SH "SEE ALSO" 66 | Password Multiplier using iterated sha1 hashing, 2005. 67 | .br 68 | Stronger Key Derivation Via Sequential Memory-hard Functions, 2009. 69 | .PP 70 | genpass(1) 71 | -------------------------------------------------------------------------------- /poison/poison.h: -------------------------------------------------------------------------------- 1 | /* 2 | poison.h - header to ban unsafe C/C++ functions from applications, modified 3 | License: public domain 4 | 5 | Original: https://github.com/leafsr/gcc-poison, version 04.12.2013 6 | Post about it: http://blog.leafsr.com/2013/12/02/gcc-poison 7 | Copyright 2013 - Leaf Security Research 8 | */ 9 | 10 | //macro guard used to avoid the problem of double inclusion 11 | #ifndef __POISON_H__ 12 | #define __POISON_H__ 13 | #ifdef __GNUC__ 14 | 15 | /* string handling functions */ 16 | # pragma GCC poison strcpy wcscpy stpcpy wcpcpy 17 | # pragma GCC poison scanf sscanf vscanf fwscanf swscanf wscanf 18 | # pragma GCC poison gets puts 19 | # pragma GCC poison strcat wcscat 20 | # pragma GCC poison wcrtomb wctob 21 | # pragma GCC poison sprintf vsprintf vfprintf 22 | # pragma GCC poison asprintf vasprintf 23 | # pragma GCC poison strncpy wcsncpy 24 | # pragma GCC poison strtok wcstok 25 | # pragma GCC poison strdupa strndupa 26 | 27 | /* signal related */ 28 | # pragma GCC poison longjmp siglongjmp 29 | # pragma GCC poison setjmp sigsetjmp 30 | 31 | /* memory allocation */ 32 | ///next line is commented because it produces "warning: poisoning existing macro "alloca" 33 | //[enabledby default]" after including some system header 34 | //# pragma GCC poison alloca 35 | # pragma GCC poison mallopt 36 | 37 | /* file API */ 38 | # pragma GCC poison remove 39 | # pragma GCC poison mktemp tmpnam tempnam 40 | # pragma GCC poison getwd 41 | 42 | /* misc */ 43 | # pragma GCC poison getlogin getpass cuserid 44 | # pragma GCC poison rexec rexec_af 45 | 46 | /* command and program execution */ 47 | //use of that functions is often insecure and unjustified 48 | //system() call is used in cpwd so it was remowed from line below 49 | # pragma GCC poison exec execl execlp execle execv execvp execvpe execve fexecve 50 | 51 | /* deprecated network functions */ 52 | # pragma GCC poison gethostbyname gethostbyaddr inet_ntoa inet_aton 53 | 54 | #endif 55 | #endif 56 | -------------------------------------------------------------------------------- /readpass/Makefile: -------------------------------------------------------------------------------- 1 | CC?=gcc 2 | CFLAGS?=-O2 -Wall -g 3 | 4 | all: 5 | $(CC) -I. -c -o readpass.o readpass.c 6 | 7 | clean: 8 | rm -f *.o 9 | -------------------------------------------------------------------------------- /readpass/readpass.c: -------------------------------------------------------------------------------- 1 | /*- 2 | * Copyright 2009 Colin Percival 3 | * All rights reserved. 4 | * 5 | * Redistribution and use in source and binary forms, with or without 6 | * modification, are permitted provided that the following conditions 7 | * are met: 8 | * 1. Redistributions of source code must retain the above copyright 9 | * notice, this list of conditions and the following disclaimer. 10 | * 2. Redistributions in binary form must reproduce the above copyright 11 | * notice, this list of conditions and the following disclaimer in the 12 | * documentation and/or other materials provided with the distribution. 13 | * 14 | * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 15 | * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 16 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 17 | * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 18 | * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 19 | * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 20 | * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 21 | * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 22 | * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 23 | * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 24 | * SUCH DAMAGE. 25 | */ 26 | 27 | #include 28 | #include 29 | #include 30 | #include 31 | #include 32 | 33 | #include "warn.h" 34 | #include "readpass.h" 35 | 36 | #define MAXPASSLEN 2048 37 | #define MAXINPUTLEN 2048 38 | 39 | /** 40 | * tarsnap_readpass(passwd, prompt, confirmprompt, devtty) 41 | * If ${devtty} is non-zero, read a password from /dev/tty if possible; if 42 | * not, read from stdin. If reading from a tty (either /dev/tty or stdin), 43 | * disable echo and prompt the user by printing ${prompt} to stderr. If 44 | * ${confirmprompt} is non-NULL, read a second password (prompting if a 45 | * terminal is being used) and repeat until the user enters the same password 46 | * twice. Return the password as a malloced NUL-terminated string via 47 | * ${passwd}. The obscure name is to avoid namespace collisions due to the 48 | * getpass / readpass / readpassphrase / etc. functions in various libraries. 49 | */ 50 | int 51 | tarsnap_readpass(char ** passwd, const char * prompt, 52 | const char * confirmprompt, int devtty) 53 | { 54 | FILE * readfrom; 55 | char passbuf[MAXPASSLEN]; 56 | char confpassbuf[MAXPASSLEN]; 57 | struct termios term, term_old; 58 | int usingtty; 59 | 60 | /* 61 | * If devtty != 0, try to open /dev/tty; if that fails, or if devtty 62 | * is zero, we'll read the password from stdin instead. 63 | */ 64 | if ((devtty == 0) || ((readfrom = fopen("/dev/tty", "r")) == NULL)) 65 | readfrom = stdin; 66 | 67 | /* If we're reading from a terminal, try to disable echo. */ 68 | if ((usingtty = isatty(fileno(readfrom))) != 0) { 69 | if (tcgetattr(fileno(readfrom), &term_old)) { 70 | warn("Cannot read terminal settings"); 71 | goto err1; 72 | } 73 | memcpy(&term, &term_old, sizeof(struct termios)); 74 | term.c_lflag = (term.c_lflag & ~ECHO) | ECHONL; 75 | if (tcsetattr(fileno(readfrom), TCSANOW, &term)) { 76 | warn("Cannot set terminal settings"); 77 | goto err1; 78 | } 79 | } 80 | 81 | retry: 82 | /* If we have a terminal, prompt the user to enter the password. */ 83 | if (usingtty) 84 | fprintf(stderr, "%s: ", prompt); 85 | 86 | /* Read the password. */ 87 | if (fgets(passbuf, MAXPASSLEN, readfrom) == NULL) { 88 | warn("Cannot read password"); 89 | goto err2; 90 | } 91 | 92 | /* Confirm the password if necessary. */ 93 | if (confirmprompt != NULL) { 94 | if (usingtty) 95 | fprintf(stderr, "%s: ", confirmprompt); 96 | if (fgets(confpassbuf, MAXPASSLEN, readfrom) == NULL) { 97 | warn("Cannot read password"); 98 | goto err2; 99 | } 100 | if (strcmp(passbuf, confpassbuf)) { 101 | fprintf(stderr, 102 | "Passwords mismatch, please try again\n"); 103 | goto retry; 104 | } 105 | } 106 | 107 | /* Terminate the string at the first "\r" or "\n" (if any). */ 108 | passbuf[strcspn(passbuf, "\r\n")] = '\0'; 109 | 110 | /* If we changed terminal settings, reset them. */ 111 | if (usingtty) 112 | tcsetattr(fileno(readfrom), TCSANOW, &term_old); 113 | 114 | /* Close /dev/tty if we opened it. */ 115 | if (readfrom != stdin) 116 | fclose(readfrom); 117 | 118 | /* Copy the password out. */ 119 | if ((*passwd = strdup(passbuf)) == NULL) { 120 | warn("Cannot allocate memory"); 121 | goto err1; 122 | } 123 | 124 | /* Zero any stored passwords. */ 125 | memset(passbuf, 0, MAXPASSLEN); 126 | memset(confpassbuf, 0, MAXPASSLEN); 127 | 128 | /* Success! */ 129 | return (0); 130 | 131 | err2: 132 | /* Reset terminal settings if necessary. */ 133 | if (usingtty) 134 | tcsetattr(fileno(readfrom), TCSAFLUSH, &term_old); 135 | err1: 136 | /* Close /dev/tty if we opened it. */ 137 | if (readfrom != stdin) 138 | fclose(readfrom); 139 | 140 | /* Failure! */ 141 | return (-1); 142 | } 143 | 144 | //use termio settings as a workaround to flush stdin 145 | int 146 | tarsnap_readinput(char ** input, const char * prompt, 147 | const char * confirmprompt, int devtty) 148 | { 149 | FILE * readfrom; 150 | char inputbuf[MAXINPUTLEN]; 151 | char confinputbuf[MAXINPUTLEN]; 152 | struct termios term, term_old; 153 | int usingtty; 154 | 155 | /* 156 | * If devtty != 0, try to open /dev/tty; if that fails, or if devtty 157 | * is zero, we'll read entries from stdin instead. 158 | */ 159 | if ((devtty == 0) || ((readfrom = fopen("/dev/tty", "r")) == NULL)) 160 | readfrom = stdin; 161 | 162 | /* If we're reading from a terminal, try to disable echo. */ 163 | if ((usingtty = isatty(fileno(readfrom))) != 0) { 164 | if (tcgetattr(fileno(readfrom), &term_old)) { 165 | warn("Cannot read terminal settings"); 166 | goto err1; 167 | } 168 | memcpy(&term, &term_old, sizeof(struct termios)); 169 | term.c_lflag = (term.c_lflag & ~ECHO) | ECHONL; 170 | if (tcsetattr(fileno(readfrom), TCSANOW, &term)) { 171 | warn("Cannot set terminal settings"); 172 | goto err1; 173 | } 174 | } 175 | 176 | /* use termio settings as a workaround to flush stdin */ 177 | /* If we changed terminal settings, reset them. */ 178 | if (usingtty) 179 | tcsetattr(fileno(readfrom), TCSANOW, &term_old); 180 | retry: 181 | /* If we have a terminal, prompt the user to enter the input. */ 182 | if (usingtty) 183 | fprintf(stderr, "%s: ", prompt); 184 | 185 | /* Read the input. */ 186 | if (fgets(inputbuf, MAXINPUTLEN, readfrom) == NULL) { 187 | warn("Cannot read input"); 188 | goto err2; 189 | } 190 | 191 | /* Confirm the input if necessary. */ 192 | if (confirmprompt != NULL) { 193 | if (usingtty) 194 | fprintf(stderr, "%s: ", confirmprompt); 195 | if (fgets(confinputbuf, MAXINPUTLEN, readfrom) == NULL) { 196 | warn("Cannot read input"); 197 | goto err2; 198 | } 199 | if (strcmp(inputbuf, confinputbuf)) { 200 | fprintf(stderr, "Input mismatch, please try again\n"); 201 | goto retry; 202 | } 203 | } 204 | 205 | /* Terminate the string at the first "\r" or "\n" (if any). */ 206 | inputbuf[strcspn(inputbuf, "\r\n")] = '\0'; 207 | 208 | /* Close /dev/tty if we opened it. */ 209 | if (readfrom != stdin) 210 | fclose(readfrom); 211 | 212 | /* Copy the input out. */ 213 | if ((*input = strdup(inputbuf)) == NULL) { 214 | warn("Cannot allocate memory"); 215 | goto err1; 216 | } 217 | 218 | /* Zero any stored input. */ 219 | memset(inputbuf, 0, MAXINPUTLEN); 220 | memset(confinputbuf, 0, MAXINPUTLEN); 221 | 222 | /* Success! */ 223 | return (0); 224 | 225 | err2: 226 | /* Reset terminal settings if necessary. */ 227 | if (usingtty) 228 | tcsetattr(fileno(readfrom), TCSAFLUSH, &term_old); 229 | err1: 230 | /* Close /dev/tty if we opened it. */ 231 | if (readfrom != stdin) 232 | fclose(readfrom); 233 | 234 | /* Failure! */ 235 | return (-1); 236 | } 237 | -------------------------------------------------------------------------------- /readpass/readpass.h: -------------------------------------------------------------------------------- 1 | /*- 2 | * Copyright 2009 Colin Percival 3 | * All rights reserved. 4 | * 5 | * Redistribution and use in source and binary forms, with or without 6 | * modification, are permitted provided that the following conditions 7 | * are met: 8 | * 1. Redistributions of source code must retain the above copyright 9 | * notice, this list of conditions and the following disclaimer. 10 | * 2. Redistributions in binary form must reproduce the above copyright 11 | * notice, this list of conditions and the following disclaimer in the 12 | * documentation and/or other materials provided with the distribution. 13 | * 14 | * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 15 | * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 16 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 17 | * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 18 | * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 19 | * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 20 | * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 21 | * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 22 | * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 23 | * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 24 | * SUCH DAMAGE. 25 | * 26 | * This file was originally written by Colin Percival as part of the Tarsnap 27 | * online backup system. 28 | */ 29 | #ifndef _READPASS_H_ 30 | #define _READPASS_H_ 31 | 32 | /** 33 | * tarsnap_getpass(passwd, prompt, confirmprompt, devtty) 34 | * If ${devtty} is non-zero, read a password from /dev/tty if possible; if 35 | * not, read from stdin. If reading from a tty (either /dev/tty or stdin), 36 | * disable echo and prompt the user by printing ${prompt} to stderr. If 37 | * ${confirmprompt} is non-NULL, read a second password (prompting if a 38 | * terminal is being used) and repeat until the user enters the same password 39 | * twice. Return the password as a malloced NUL-terminated string via 40 | * ${passwd}. The obscure name is to avoid namespace collisions due to the 41 | * getpass / readpass / readpassphrase / etc. functions in various libraries. 42 | */ 43 | int tarsnap_readpass (char **, const char *, const char *, int); 44 | int tarsnap_readinput(char **, const char *, const char *, int); 45 | 46 | #endif /* !_READPASS_H_ */ 47 | -------------------------------------------------------------------------------- /readpass/warn.c: -------------------------------------------------------------------------------- 1 | /*- 2 | * Copyright 2009 Colin Percival 3 | * All rights reserved. 4 | * 5 | * Redistribution and use in source and binary forms, with or without 6 | * modification, are permitted provided that the following conditions 7 | * are met: 8 | * 1. Redistributions of source code must retain the above copyright 9 | * notice, this list of conditions and the following disclaimer. 10 | * 2. Redistributions in binary form must reproduce the above copyright 11 | * notice, this list of conditions and the following disclaimer in the 12 | * documentation and/or other materials provided with the distribution. 13 | * 14 | * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 15 | * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 16 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 17 | * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 18 | * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 19 | * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 20 | * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 21 | * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 22 | * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 23 | * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 24 | * SUCH DAMAGE. 25 | * 26 | * This file was originally written by Colin Percival as part of the Tarsnap 27 | * online backup system. 28 | */ 29 | //#include "scrypt_platform.h" 30 | 31 | #ifdef HAVE_ERR_H 32 | /* 33 | * Everything is provided through err.h and the associated library, so we 34 | * don't need to do anything here. 35 | */ 36 | #else 37 | #include 38 | #include 39 | #include 40 | #include 41 | 42 | #include "warn.h" 43 | 44 | const char * warn_progname = "(null)"; 45 | 46 | void 47 | warn(const char * fmt, ...) 48 | { 49 | va_list ap; 50 | 51 | va_start(ap, fmt); 52 | fprintf(stderr, "%s", warn_progname); 53 | if (fmt != NULL) { 54 | fprintf(stderr, ": "); 55 | vfprintf(stderr, fmt, ap); 56 | } 57 | fprintf(stderr, ": %s\n", strerror(errno)); 58 | va_end(ap); 59 | } 60 | 61 | void 62 | warnx(const char * fmt, ...) 63 | { 64 | va_list ap; 65 | 66 | va_start(ap, fmt); 67 | fprintf(stderr, "%s", warn_progname); 68 | if (fmt != NULL) { 69 | fprintf(stderr, ": "); 70 | vfprintf(stderr, fmt, ap); 71 | } 72 | fprintf(stderr, "\n"); 73 | va_end(ap); 74 | } 75 | #endif 76 | -------------------------------------------------------------------------------- /readpass/warn.h: -------------------------------------------------------------------------------- 1 | #ifndef _WARN_H_ 2 | #define _WARN_H_ 3 | 4 | #ifdef HAVE_ERR_H 5 | #include 6 | #else 7 | #define NEED_WARN_PROGNAME 8 | const char * warn_progname; 9 | void warn(const char *, ...); 10 | void warnx(const char *, ...); 11 | #endif 12 | 13 | #endif /* !_WARN_H_ */ 14 | -------------------------------------------------------------------------------- /test/README.md: -------------------------------------------------------------------------------- 1 | Usage 2 | ----- 3 | 4 | ```sh 5 | $ xvfb-run sh test.sh 6 | ``` 7 | -------------------------------------------------------------------------------- /test/genpass-mp-input.exp.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | rm -rf /tmp/genpass-*.exp 4 | CURRENT_DIR="$(cd "$(dirname "${0}" )" && pwd)" 5 | PATH="${CURRENT_DIR}/../:${PATH}"; export PATH 6 | 7 | expect_script=' 8 | log_user 0 9 | spawn genpass-static -f key -C1 -c1 -n1 1 10 | 11 | set timeout 1 12 | 13 | expect { "Master password:" { 14 | send "1" 15 | expect { 16 | "4ui?YtkC[}e[XHCYs.r9Zsd{NC+aDl/US?h9A)58!" 17 | }} 18 | 19 | timeout { 20 | puts "genpass failed"; 21 | exit 1 22 | } 23 | }' 24 | 25 | printf "%s\\n" "${expect_script}" > /tmp/genpass-mp-input.exp 26 | expect /tmp/genpass-mp-input.exp 27 | -------------------------------------------------------------------------------- /test/genpass-name-and-mp-input.exp.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | rm -rf /tmp/genpass-*.exp 4 | CURRENT_DIR="$(cd "$(dirname "${0}" )" && pwd)" 5 | PATH="${CURRENT_DIR}/../:${PATH}"; export PATH 6 | 7 | expect_script=' 8 | log_user 0 9 | spawn genpass-static -f key -C1 -c1 1 10 | 11 | set timeout 1 12 | 13 | expect { 14 | "Name:" { 15 | send "1" 16 | expect { 17 | "Master password:" { 18 | send "1" 19 | expect { 20 | "4ui?YtkC[}e[XHCYs.r9Zsd{NC+aDl/US?h9A)58!" 21 | }}}} 22 | 23 | timeout { 24 | puts "genpass failed"; 25 | exit 1 26 | } 27 | }' 28 | 29 | printf "%s\\n" "${expect_script}" > /tmp/genpass-name-and-mp-input.exp 30 | expect /tmp/genpass-name-and-mp-input.exp 31 | -------------------------------------------------------------------------------- /test/genpass-normal-input.exp.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | rm -rf /tmp/genpass-*.exp 4 | CURRENT_DIR="$(cd "$(dirname "${0}" )" && pwd)" 5 | PATH="${CURRENT_DIR}/../:${PATH}"; export PATH 6 | 7 | expect_script=' 8 | log_user 0 9 | spawn genpass-static -f key -C1 -c1 10 | 11 | set timeout 1 12 | 13 | expect { 14 | "Name:" { 15 | send "1" 16 | expect { 17 | "Site:" { 18 | send "1" 19 | expect { 20 | "Master password:" { 21 | send "1" 22 | expect { 23 | "4ui?YtkC[}e[XHCYs.r9Zsd{NC+aDl/US?h9A)58!" 24 | }}}}}} 25 | 26 | timeout { 27 | puts "genpass failed"; 28 | exit 1 29 | } 30 | }' 31 | 32 | printf "%s\\n" "${expect_script}" > /tmp/genpass-normal-input.exp 33 | expect /tmp/genpass-normal-input.exp 34 | -------------------------------------------------------------------------------- /test/genpass-registration-mode.exp.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | rm -rf /tmp/genpass-*.exp 4 | CURRENT_DIR="$(cd "$(dirname "${0}" )" && pwd)" 5 | PATH="${CURRENT_DIR}/../:${PATH}"; export PATH 6 | 7 | expect_script=' 8 | log_user 0 9 | spawn genpass-static -f key -C1 -c1 --registration-mode 10 | 11 | set timeout 1 12 | 13 | expect { 14 | "Name:" { 15 | send "1" 16 | expect { 17 | "Site:" { 18 | send "1" 19 | expect { 20 | "Master password:" { 21 | send "1" 22 | expect { 23 | "repeat again:" { 24 | send "1" 25 | expect { 26 | "4ui?YtkC[}e[XHCYs.r9Zsd{NC+aDl/US?h9A)58!" 27 | }}}}}}}} 28 | 29 | timeout { 30 | puts "genpass failed"; 31 | exit 1 32 | } 33 | }' 34 | 35 | printf "%s\\n" "${expect_script}" > /tmp/genpass-registration-mode.exp 36 | expect /tmp/genpass-registration-mode.exp 37 | 38 | expect_script=' 39 | log_user 0 40 | spawn genpass-static -f key -C1 -c1 --registration-mode 41 | 42 | set timeout 1 43 | 44 | expect { 45 | "Name:" { 46 | send "1" 47 | expect { 48 | "Site:" { 49 | send "1" 50 | expect { 51 | "Master password:" { 52 | send "1" 53 | expect { 54 | "repeat again:" { 55 | send "2" 56 | expect { 57 | "Master password:" { 58 | send "1" 59 | expect { 60 | "repeat again:" { 61 | send "1" 62 | expect { 63 | "4ui?YtkC[}e[XHCYs.r9Zsd{NC+aDl/US?h9A)58!" 64 | }}}}}}}}}}}} 65 | 66 | timeout { 67 | puts "genpass failed"; 68 | exit 1 69 | } 70 | }' 71 | 72 | printf "%s\\n" "${expect_script}" > /tmp/genpass-registration-mode.exp 73 | expect /tmp/genpass-registration-mode.exp 74 | -------------------------------------------------------------------------------- /test/genpass-site-and-mp-input.exp.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | rm -rf /tmp/genpass-*.exp 4 | CURRENT_DIR="$(cd "$(dirname "${0}" )" && pwd)" 5 | PATH="${CURRENT_DIR}/../:${PATH}"; export PATH 6 | 7 | expect_script=' 8 | log_user 0 9 | spawn genpass-static -f key -C1 -c1 -n1 10 | 11 | set timeout 1 12 | 13 | expect { 14 | "Site:" { 15 | send "1" 16 | expect { 17 | "Master password:" { 18 | send "1" 19 | expect { 20 | "4ui?YtkC[}e[XHCYs.r9Zsd{NC+aDl/US?h9A)58!" 21 | }}}} 22 | 23 | timeout { 24 | puts "genpass failed"; 25 | exit 1 26 | } 27 | }' 28 | 29 | printf "%s\\n" "${expect_script}" > /tmp/genpass-site-and-mp-input.exp 30 | expect /tmp/genpass-site-and-mp-input.exp 31 | -------------------------------------------------------------------------------- /test/genpass-static.db: -------------------------------------------------------------------------------- 1 | @begin{essential} 2 | test -f ../../genpass 3 | test -f ../../genpass-static 4 | @end 5 | 6 | @begin{return-codes} 7 | genpass-static -h; test X"${?}" = X"0" 8 | genpass-static -V; test X"${?}" = X"0" 9 | genpass-static -n; test X"${?}" = X"1" 10 | genpass-static -p; test X"${?}" = X"1" 11 | genpass-static -s; test X"${?}" = X"1" 12 | genpass-static -f; test X"${?}" = X"1" 13 | genpass-static -l; test X"${?}" = X"1" 14 | genpass-static -C; test X"${?}" = X"1" 15 | genpass-static -c; test X"${?}" = X"1" 16 | genpass-static --scrypt-r; test X"${?}" = X"1" 17 | genpass-static --scrypt-p; test X"${?}" = X"1" 18 | genpass-static --config; test X"${?}" = X"1" 19 | genpass-static --cui; test X"${?}" = X"1" 20 | 21 | printf "%s" '-h' | genpass-static -f ./key -C1 -c1 -n1 -p1 1; test X"${?}" = X"0" 22 | #test ! -f ./key #TODO 10-10-2016 03:17 >> fix bug 23 | @end 24 | 25 | @begin{error-messages} 26 | test X"$(genpass-static -h |head -1)" = X"Usage: genpass [option]... [site]" 27 | test X"$(genpass-static --help |head -1)" = X"Usage: genpass [option]... [site]" 28 | test X"$(genpass-static --cui 2>&1|head -1)" = X"genpass: unrecognized option '--cui'" 29 | test X"$(genpass-static --cui |head -1)" = X"" 30 | test X"$(genpass-static -n 2>&1|head -1)" = X"genpass: option '-n' requires an argument" 31 | test X"$(genpass-static -n |head -1)" = X"" 32 | test X"$(genpass-static -l a 2>&1|head -1)" = X"genpass: option '-l' requires a numerical argument, 'a'" 33 | test X"$(genpass-static -la 2>&1|head -1)" = X"genpass: option '-l' requires a numerical argument, 'a'" 34 | test X"$(genpass-static -la |head -1)" = X"" 35 | test X"$(genpass-static -l1 2>&1|head -1)" = X"genpass: option '-l' numerical value must be between 8-1024, '1'" 36 | test X"$(genpass-static -C a 2>&1|head -1)" = X"genpass: option '-C' requires a numerical argument, 'a'" 37 | test X"$(genpass-static -C121 2>&1|head -1)" = X"genpass: option '-C' numerical value must be between 1-30, '121'" 38 | test X"$(genpass-static -c a 2>&1|head -1)" = X"genpass: option '-c' requires a numerical argument, 'a'" 39 | test X"$(genpass-static -c121 2>&1|head -1)" = X"genpass: option '-c' numerical value must be between 1-30, '121'" 40 | test X"$(genpass-static -e d 2>&1|head -1)" = X"genpass: invalid text encoding 'd'" 41 | test X"$(genpass-static --config 2>&1|head -1)" = X"genpass: option '--config' requires an argument" 42 | test X"$(genpass-static --config cui 2>&1|head -1)" = X"genpass: couldn't load config file 'cui'" 43 | test X"$(genpass-static --scrypt-r 2>&1|head -1)" = X"genpass: option '--scrypt-r' requires an argument" 44 | test X"$(genpass-static --scrypt-r a 2>&1|head -1)" = X"genpass: option '--scrypt-r' requires a numerical argument, 'a'" 45 | test X"$(genpass-static --scrypt-r 10291 2>&1|head -1)" = X"genpass: option '--scrypt-r' numerical value must be between 1-9999, '10291'" 46 | test X"$(genpass-static --scrypt-p 2>&1|head -1)" = X"genpass: option '--scrypt-p' requires an argument" 47 | test X"$(genpass-static --scrypt-p a 2>&1|head -1)" = X"genpass: option '--scrypt-p' requires a numerical argument, 'a'" 48 | test X"$(genpass-static --scrypt-r 102911 2>&1|head -1)" = X"genpass: option '--scrypt-r' numerical value must be between 1-9999, '102911'" 49 | @end 50 | 51 | @begin{password-generation} 52 | test X"$(genpass-static -f ./key -C1 -c1 -n1 -p1 1)" = X"4>KGf9&t4Xl?:6V+5jSV1ttxP56oiwW>/XmZ^dr{N" 53 | test X"$(genpass-static -f ./key -C1 -c1 -n1 -p1 1 -e z85)" = X"4>KGf9&t4Xl?:6V+5jSV1ttxP56oiwW>/XmZ^dr{N" 54 | test X"$(genpass-static -f ./key -C1 -c1 -l8 -e dec -n1 -p1 1)" = X"57175901779215943103" 55 | test X"$(genpass-static -f ./key -C1 -c1 -l8 -e hex -n1 -p1 1)" = X"39af5ab15c9f2b67" 56 | test X"$(genpass-static -f ./key -C1 -c1 -l8 -e base64 -n1 -p1 1)" = X"Oa9asVyfK2c" 57 | test X"$(genpass-static -f ./key -C1 -c1 -l8 -e skey -n1 -p1 1)" = X"RYE EGAN LEAR MEAL USES LUCK" 58 | test -f ./key && rm -rf key 59 | 60 | test X"$(genpass-static -f ./key -C1 -c1 -n2 -p1 1)" = X"4Topkr=o[&1 | grep "Generating new cache key" >/dev/null 2>&1 66 | genpass-static -f ./key -v -C1 -c1 -n1 -p1 1 2>&1 | grep "Loaded valid cache key value" >/dev/null 2>&1 67 | genpass-static -f ./key -v -C1 -c1 -l8 -n1 -p1 1 2>&1 | grep "Invalid cache key value" >/dev/null 2>&1 68 | genpass-static -f ./key -v -C1 -c1 -l8 -n1 -p1 1 2>&1 | grep "Loaded valid cache key value" >/dev/null 2>&1 69 | genpass-static -f ./key -v -C1 -c2 -l8 -n1 -p1 1 2>&1 | grep "Loaded valid cache key value" >/dev/null 2>&1 70 | genpass-static -f ./key -v -C2 -c1 -l8 -n1 -p1 1 2>&1 | grep "Invalid cache key value" >/dev/null 2>&1 71 | genpass-static -f ./key -v -C2 -c1 -l8 -n1 -p1 1 2>&1 | grep "Loaded valid cache key value" >/dev/null 2>&1 72 | genpass-static -f ./key -v -C2 -c1 -l8 --scrypt-r 1 --scrypt-p 1 -n1 -p1 1 2>&1 | grep "Invalid cache key value" >/dev/null 2>&1 73 | genpass-static -f ./key -v -C2 -c1 -l8 --scrypt-r 1 --scrypt-p 1 -n1 -p1 1 2>&1 | grep "Loaded valid cache key value" >/dev/null 2>&1 74 | genpass-static -f ./key -v -C2 -c1 -l8 --scrypt-r 2 --scrypt-p 1 -n1 -p1 1 2>&1 | grep "Invalid cache key value" >/dev/null 2>&1 75 | genpass-static -f ./key -v -C2 -c1 -l8 --scrypt-r 2 --scrypt-p 2 -n1 -p1 1 2>&1 | grep "Invalid cache key value" >/dev/null 2>&1 76 | genpass-static -f ./key -v -C2 -c1 -l8 --scrypt-r 2 --scrypt-p 2 -n1 -p1 1 2>&1 | grep "Loaded valid cache key value" >/dev/null 2>&1 77 | test -f ./key && rm -rf key 78 | 79 | genpass-static -f ./key -1 -v -c1 -n1 -p1 1 2>&1 | grep "Generating single derived key" >/dev/null 2>&1 80 | test ! -f ./key 81 | genpass-static -f ./key -N -v -C1 -c1 -n1 -p1 1 2>&1 | grep "Generating new cache key" >/dev/null 2>&1 82 | test ! -f ./key 83 | @end 84 | 85 | @begin{config-file} 86 | #TODO 03-10-2016 12:39 >> BUG, remove ''/"" from name user 87 | #printf "%s\\n%s\\n" "[user]" "name='1'" > genpass.config 88 | printf "%s\\n%s\\n" "[user]" "name=1" > genpass.config 89 | test X"$(genpass-static -f ./key --config genpass.config -C1 -c1 -p1 1)" = X"4>KGf9&t4Xl?:6V+5jSV1ttxP56oiwW>/XmZ^dr{N" 90 | printf "%s\\n%s\\n%s\\n" "[user]" "name=1" "site=1" > genpass.config 91 | test X"$(genpass-static -f ./key --config genpass.config -C1 -c1 -p1)" = X"4>KGf9&t4Xl?:6V+5jSV1ttxP56oiwW>/XmZ^dr{N" 92 | printf "%s\\n%s\\n%s\\n%s\\n%s\\n" "[user]" "name=1" "site=1" "[general]" "cache_cost=1" > genpass.config 93 | test X"$(genpass-static -f ./key --config genpass.config -c1 -p1)" = X"4>KGf9&t4Xl?:6V+5jSV1ttxP56oiwW>/XmZ^dr{N" 94 | printf "%s\\n%s\\n%s\\n%s\\n%s\\n%s\\n" "[user]" "name=1" "site=1" "[general]" "cache_cost=1" "cost=1" > genpass.config 95 | test X"$(genpass-static -f ./key --config genpass.config -p1)" = X"4>KGf9&t4Xl?:6V+5jSV1ttxP56oiwW>/XmZ^dr{N" 96 | printf "%s\\n%s\\n%s\\n%s\\n%s\\n%s\\n%s\\n" "[user]" "name=1" "password=1" "site=1" "[general]" "cache_cost=1" "cost=1" > genpass.config 97 | test X"$(genpass-static -f ./key --config genpass.config)" = X"4>KGf9&t4Xl?:6V+5jSV1ttxP56oiwW>/XmZ^dr{N" 98 | test -f genpass.config && rm -rf genpass.config 99 | @end 100 | 101 | @begin{interactive} 102 | #expect tests 103 | for genpass_test_exp in ../genpass*exp.sh; do sh "${genpass_test_exp}" || exit 1; done 104 | @end 105 | 106 | # vim: set ts=8 sw=4 tw=0 ft=sh : 107 | -------------------------------------------------------------------------------- /test/getpass.db: -------------------------------------------------------------------------------- 1 | @begin{initializate} 2 | #use genpass-static to avoid depending on the user 3 | #installing genpass and libraries on its system 4 | cp ../../genpass ../../genpass.orig 5 | cp ../../genpass-static ../../genpass 6 | @end 7 | 8 | @begin{return-codes} 9 | getpass -h; test X"${?}" = X"0" 10 | getpass -V; test X"${?}" = X"0" 11 | getpass -n; test X"${?}" = X"1" 12 | getpass -p; test X"${?}" = X"1" 13 | getpass -s; test X"${?}" = X"1" 14 | getpass -f; test X"${?}" = X"1" 15 | getpass -l; test X"${?}" = X"1" 16 | getpass -C; test X"${?}" = X"1" 17 | getpass -c; test X"${?}" = X"1" 18 | getpass --scrypt-r; test X"${?}" = X"1" 19 | getpass --scrypt-p; test X"${?}" = X"1" 20 | getpass --config; test X"${?}" = X"1" 21 | getpass --cui; test X"${?}" = X"1" 22 | 23 | printf "%s" '-h' | getpass -f ./key -C1 -c1 -n1 -p1 1; test X"${?}" = X"0" 24 | test ! -f ./key 25 | @end 26 | 27 | @begin{error-messages} 28 | test X"$(getpass -h |head -1)" = X"Usage: getpass [option]... site" 29 | test X"$(getpass --help |head -1)" = X"Usage: getpass [option]... site" 30 | test X"$(getpass --cui 2>&1|head -1)" = X"genpass: unrecognized option '--cui'" 31 | test X"$(getpass --cui |head -1)" = X"" 32 | test X"$(getpass -n 2>&1|head -1)" = X"genpass: option '-n' requires an argument" 33 | test X"$(getpass -n |head -1)" = X"" 34 | test X"$(getpass -l a 2>&1|head -1)" = X"genpass: option '-l' requires a numerical argument, 'a'" 35 | test X"$(getpass -la 2>&1|head -1)" = X"genpass: option '-l' requires a numerical argument, 'a'" 36 | test X"$(getpass -la |head -1)" = X"" 37 | test X"$(getpass -l1 2>&1|head -1)" = X"genpass: option '-l' numerical value must be between 8-1024, '1'" 38 | test X"$(getpass -C a 2>&1|head -1)" = X"genpass: option '-C' requires a numerical argument, 'a'" 39 | test X"$(getpass -C121 2>&1|head -1)" = X"genpass: option '-C' numerical value must be between 1-30, '121'" 40 | test X"$(getpass -c a 2>&1|head -1)" = X"genpass: option '-c' requires a numerical argument, 'a'" 41 | test X"$(getpass -c121 2>&1|head -1)" = X"genpass: option '-c' numerical value must be between 1-30, '121'" 42 | test X"$(getpass -e d 2>&1|head -1)" = X"genpass: invalid text encoding 'd'" 43 | test X"$(getpass --scrypt-r 2>&1|head -1)" = X"genpass: option '--scrypt-r' requires an argument" 44 | test X"$(getpass --scrypt-r a 2>&1|head -1)" = X"genpass: option '--scrypt-r' requires a numerical argument, 'a'" 45 | test X"$(getpass --scrypt-r 10291 2>&1|head -1)" = X"genpass: option '--scrypt-r' numerical value must be between 1-9999, '10291'" 46 | test X"$(getpass --scrypt-p 2>&1|head -1)" = X"genpass: option '--scrypt-p' requires an argument" 47 | test X"$(getpass --scrypt-p a 2>&1|head -1)" = X"genpass: option '--scrypt-p' requires a numerical argument, 'a'" 48 | test X"$(getpass --scrypt-r 102911 2>&1|head -1)" = X"genpass: option '--scrypt-r' numerical value must be between 1-9999, '102911'" 49 | test X"$(getpass --config 2>&1|head -1)" = X"genpass: option '--config' requires an argument" 50 | test X"$(getpass --config cui 2>&1|head -1)" = X"genpass: couldn't load config file 'cui'" 51 | @end 52 | 53 | @begin{password-generation} 54 | getpass -f ./key -C1 -c1 -n1 -p1 1 && test X"$(xclip -o -selection clipboard)" = X"4>KGf9&t4Xl?:6V+5jSV1ttxP56oiwW>/XmZ^dr{N" 55 | getpass -f ./key -C1 -c1 -n1 -p1 1 -e z85 && test X"$(xclip -o -selection clipboard)" = X"4>KGf9&t4Xl?:6V+5jSV1ttxP56oiwW>/XmZ^dr{N" 56 | getpass -f ./key -C1 -c1 -l8 -e dec -n1 -p1 1 && test X"$(xclip -o -selection clipboard)" = X"57175901779215943103" 57 | getpass -f ./key -C1 -c1 -l8 -e hex -n1 -p1 1 && test X"$(xclip -o -selection clipboard)" = X"39af5ab15c9f2b67" 58 | getpass -f ./key -C1 -c1 -l8 -e base64 -n1 -p1 1 && test X"$(xclip -o -selection clipboard)" = X"Oa9asVyfK2c" 59 | getpass -f ./key -C1 -c1 -l8 -e skey -n1 -p1 1 && test X"$(xclip -o -selection clipboard)" = X"RYE EGAN LEAR MEAL USES LUCK" 60 | test -f ./key && rm -rf key 61 | 62 | getpass -f ./key -C1 -c1 -n2 -p1 1 && test X"$(xclip -o -selection clipboard)" = X"4Topkr=o[&1 | grep "Generating new cache key" >/dev/null 2>&1 68 | getpass -f ./key -v -C1 -c1 -n1 -p1 1 2>&1 | grep "Loaded valid cache key value" >/dev/null 2>&1 69 | getpass -f ./key -v -C1 -c1 -l8 -n1 -p1 1 2>&1 | grep "Invalid cache key value" >/dev/null 2>&1 70 | getpass -f ./key -v -C1 -c1 -l8 -n1 -p1 1 2>&1 | grep "Loaded valid cache key value" >/dev/null 2>&1 71 | getpass -f ./key -v -C1 -c2 -l8 -n1 -p1 1 2>&1 | grep "Loaded valid cache key value" >/dev/null 2>&1 72 | getpass -f ./key -v -C2 -c1 -l8 -n1 -p1 1 2>&1 | grep "Invalid cache key value" >/dev/null 2>&1 73 | getpass -f ./key -v -C2 -c1 -l8 -n1 -p1 1 2>&1 | grep "Loaded valid cache key value" >/dev/null 2>&1 74 | getpass -f ./key -v -C2 -c1 -l8 --scrypt-r 1 --scrypt-p 1 -n1 -p1 1 2>&1 | grep "Invalid cache key value" >/dev/null 2>&1 75 | getpass -f ./key -v -C2 -c1 -l8 --scrypt-r 1 --scrypt-p 1 -n1 -p1 1 2>&1 | grep "Loaded valid cache key value" >/dev/null 2>&1 76 | getpass -f ./key -v -C2 -c1 -l8 --scrypt-r 2 --scrypt-p 1 -n1 -p1 1 2>&1 | grep "Invalid cache key value" >/dev/null 2>&1 77 | getpass -f ./key -v -C2 -c1 -l8 --scrypt-r 2 --scrypt-p 2 -n1 -p1 1 2>&1 | grep "Invalid cache key value" >/dev/null 2>&1 78 | getpass -f ./key -v -C2 -c1 -l8 --scrypt-r 2 --scrypt-p 2 -n1 -p1 1 2>&1 | grep "Loaded valid cache key value" >/dev/null 2>&1 79 | test -f ./key && rm -rf key 80 | getpass -f ./key -1 -v -c1 -n1 -p1 1 2>&1 | grep "Generating single derived key" >/dev/null 2>&1 81 | test ! -f ./key 82 | getpass -f ./key -N -v -C1 -c1 -n1 -p1 1 2>&1 | grep "Generating new cache key" >/dev/null 2>&1 83 | test ! -f ./key 84 | getpass -k 1 -f ./key -C1 -c1 -n1 -p1 1 && test X"$(xclip -o -selection clipboard)" = X"4>KGf9&t4Xl?:6V+5jSV1ttxP56oiwW>/XmZ^dr{N" 85 | test X"$(xclip -o -selection clipboard)" = X"4>KGf9&t4Xl?:6V+5jSV1ttxP56oiwW>/XmZ^dr{N" 86 | sleep 1.1 || sleep 2 && test X"$(xclip -o -selection clipboard)" = X"" 87 | @end 88 | 89 | @begin{config-file} 90 | #TODO 03-10-2016 12:39 >> BUG, remove ''/"" from name user 91 | #printf "%s\\n%s\\n" "[user]" "name='1'" > genpass.config 92 | printf "%s\\n%s\\n" "[user]" "name=1" > genpass.config 93 | getpass -f ./key --config genpass.config -C1 -c1 -p1 1 && test X"$(xclip -o -selection clipboard)" = X"4>KGf9&t4Xl?:6V+5jSV1ttxP56oiwW>/XmZ^dr{N" 94 | printf "%s\\n%s\\n%s\\n" "[user]" "name=1" "site=1" > genpass.config 95 | getpass -f ./key --config genpass.config -C1 -c1 -p1 && test X"$(xclip -o -selection clipboard)" = X"4>KGf9&t4Xl?:6V+5jSV1ttxP56oiwW>/XmZ^dr{N" 96 | printf "%s\\n%s\\n%s\\n%s\\n%s\\n" "[user]" "name=1" "site=1" "[general]" "cache_cost=1" > genpass.config 97 | getpass -f ./key --config genpass.config -c1 -p1 && test X"$(xclip -o -selection clipboard)" = X"4>KGf9&t4Xl?:6V+5jSV1ttxP56oiwW>/XmZ^dr{N" 98 | printf "%s\\n%s\\n%s\\n%s\\n%s\\n%s\\n" "[user]" "name=1" "site=1" "[general]" "cache_cost=1" "cost=1" > genpass.config 99 | getpass -f ./key --config genpass.config -p1 && test X"$(xclip -o -selection clipboard)" = X"4>KGf9&t4Xl?:6V+5jSV1ttxP56oiwW>/XmZ^dr{N" 100 | printf "%s\\n%s\\n%s\\n%s\\n%s\\n%s\\n%s\\n" "[user]" "name=1" "password=1" "site=1" "[general]" "cache_cost=1" "cost=1" > genpass.config 101 | getpass -f ./key --config genpass.config && test X"$(xclip -o -selection clipboard)" = X"4>KGf9&t4Xl?:6V+5jSV1ttxP56oiwW>/XmZ^dr{N" 102 | test -f genpass.config && rm -rf genpass.config 103 | @end 104 | 105 | @begin{cleanup} 106 | #revert tmp changes, see {initializate} test 107 | mv ../../genpass.orig ../../genpass 108 | @end 109 | 110 | # vim: set ts=8 sw=4 tw=0 ft=sh : 111 | -------------------------------------------------------------------------------- /test/test.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | #usage: ./test.sh [tool] [test] 3 | #based on the GNU shtool test suite 4 | 5 | _false() { return 1; } 6 | 7 | CURRENT_DIR="$(cd "$(dirname "${0}")" && pwd)" 8 | cd "${CURRENT_DIR}" 9 | 10 | #override temp debug string, avoid "Bad substitution" errors 11 | PS4=">>" 12 | 13 | TMPDIR="test.tmp" 14 | TMPSCRIPT="test.tmp.sh" 15 | 16 | #initial score values 17 | failed="0"; passed="0"; ran="0" 18 | 19 | #use default or user input ($1) 20 | [ -z "${1}" ] && db_tests="*.db" || db_tests="${1%.db}.db" 21 | 22 | for db_test in "${CURRENT_DIR}"/${db_tests}; do 23 | tool="$(basename "${db_test}")"; tool="${tool%.db}" 24 | 25 | #check tool existence 26 | if [ -f ../"${tool}" ]; then 27 | printf "%s\\n\\n" "Info - running '${tool}' tests:" 28 | else 29 | printf "%s\\n" "Warning - '${tool}' doesn't exists, skipping ..." 30 | _false 31 | continue 32 | fi 33 | 34 | #read all tests defined in *.db files or user input ($2) 35 | tests=""; if [ -z "${2}" ]; then 36 | tests="$(grep '^@begin' "${db_test}" 2>/dev/null | \ 37 | sed -e 's/^@begin{//' -e 's/}.*$//')" 38 | else 39 | tests="${2}" 40 | fi 41 | 42 | #move to a tmp subdirectory 43 | rm -rf "${TMPDIR}" || (sleep 1; rm -rf "${TMPDIR}") 44 | mkdir "${TMPDIR}" || exit 1 45 | cd "${TMPDIR}" || exit 1 46 | 47 | OLDIFS="${IFS}"; IFS=' 48 | ' #this a new line 49 | for test in ${tests}; do 50 | #check tests exists 51 | if ! grep "^@begin{$test}" "${db_test}" >/dev/null 2>&1; then 52 | printf "%s\\n" "Warning - '${tool}' doesn't exists, skipping ..." 53 | _false 54 | continue 55 | fi 56 | 57 | #clean tmp directory 58 | rm -rf ./* || (sleep 1; rm -rf ./*) 59 | #print test title 60 | printf "%s %s\\n" "${test}" "$(printf "%*s" "65" ""|tr ' ' '.')" | \ 61 | awk '{printf("%s ", substr($0, 0, 65));}' 62 | 63 | #generate tmp test script 64 | printf "%s\\n" "PATH=../..:/bin:/usr/bin" > "${TMPSCRIPT}" 65 | sed -e "/^@begin{$test}/,/^@end/p" -e '1,$d' "${db_test}" | \ 66 | sed -e '/^@begin/d' -e '/^@end/d' \ 67 | -e 's/\([^\\]\)[ ]*$/\1 || exit 1/g' >> "${TMPSCRIPT}" 68 | printf "exit 0\\n" >> "${TMPSCRIPT}" 69 | 70 | #execute current test 71 | sh -x "${TMPSCRIPT}" > "${TMPSCRIPT%.sh}.log" 2>&1 72 | 73 | #validate test result 74 | if [ "${?}" -eq "0" ]; then 75 | passed="$((${passed} + 1))" 76 | printf "ok\\n" 77 | else 78 | #generate report 79 | printf "FAILED\\n" 80 | printf "+---Test------------------------------\\n" 81 | cat "${TMPSCRIPT}" | sed -e 's/^/| /g' 82 | printf "+---Trace-----------------------------\\n" 83 | cat "${TMPSCRIPT%.sh}.log" | sed -e 's/^/| /g' 84 | failed="$((${failed} + 1))" 85 | printf "+-------------------------------------\\n" 86 | fi 87 | 88 | ran="$((${ran} + 1))" 89 | done 90 | 91 | IFS="${OLDIFS}" 92 | cd .. && rm -rf "${TMPDIR}" >/dev/null 2>&1 93 | printf "\\n" 94 | done 95 | 96 | #result and cleanup 97 | if [ "${failed}" -gt "0" ]; then 98 | printf "FAILED: passed: ${passed}/${ran}, failed: ${failed}/${ran}\\n" 99 | exit 1 100 | else 101 | printf "OK: passed: ${passed}/${ran}\\n" 102 | fi 103 | 104 | # vim: set ts=8 sw=4 tw=0 ft=sh : 105 | --------------------------------------------------------------------------------