zxcvbn-c: new module for password strength estimation

This commit is contained in:
moneromooo.monero 2016-12-15 23:30:32 +00:00
parent 55f4858a40
commit aae35df77d
14 changed files with 284622 additions and 0 deletions

28
src/zxcvbn-c/.gitignore vendored Normal file
View file

@ -0,0 +1,28 @@
*.o
*.ko
*.obj
*.elf
*.gch
*.pch
*.lib
*.a
*.la
*.lo
*.dll
*.so
*.so.*
*.dylib
*.exe
*.out
*.app
*.i*86
*.x86_64
*.hex
test.cpp
zxcvbn.cpp
zxcvbn.dict
test-*file
test-*line
test-*lib
dictgen
dict-*.h

86
src/zxcvbn-c/README.md Normal file
View file

@ -0,0 +1,86 @@
# zxcvbn-c
This is a C/C++ implementation of the zxcvbn password strength estimation.
The code is intended to be included as part of the source of a C/C++ program. Like the
original this code is for character sets which use single byte characters primarily in the
code range 0x20 to 0x7E.
The original coffee script version is available at
https://github.com/lowe/zxcvbn
An article on the reasons for zxcvbn is at
https://tech.dropox.com/2012/04/zxcvbn-realistic-password-strength-estimation
##Building
The makefile will build several test programs to test the code. It shows the steps needed
to use the code in C and C++ programs, using the dictionary data read from file or included
within the program executable.
The makefile has only been tried on Linux using GCC version 4.8.4, but should be faily
portable to other systems.
When dictionary data is included in your program's executable, the files `zxcvbn.c` ,
`zxcvbn.h` , `dict-src.h` are used in your program.
When dictionary data is read from file, the files `zxcvbn.c` , `zxcvbn.h` , `dict-crc.h`
and `zxcvbn.dict` are used in your program, compiled with `#define USE_DICT_FILE`. The CRC
of the dictionary data file is written to `dict-crc.h` so your executable can detect
corruption of the data.
Rename `zxcvbn.c` to `zxcvbn.cpp` (or whatever your compiler uses) to compile as C++.
The `dict*.h` and `zxcvbn.dict` files are generated by the dictgen program compiled from
dict-generate.cpp (see makefile for details).
##Using
Initially call `ZxcvbnInit()` with the pathname of the `zxcvbn.dict` file. This can be
omitted when dictionary data is included in the executable.
Call `ZxcvbnMatch()` with the password and optional user dictionary to get the entropy
estimation and optional information on the password parts (which will need freeing with
`ZxcvbnFreeInfo()` after use). Do this for each password to be tested, or as each character
of it is entered into your program. The optional user dictionary can change between each
call.
Finally call `ZxcvbnUninit()` to free the dictionary data from read from file. This can be
omitted when dictionary data is included in the executable.
Review the test program in `test.c` for an example.
## Differences from the original version.
The entropy calculated will sometimes differ from the original because of
* The UK keyboard layout is also included, so there are additional spacial sequences, e.g.
**;'#** is a spacial sequence.
* The different character classes in a password are taken into account when calculating the
strength of brute-force matches.
* Dijktra's path searching algorithm is used to combine parts of the entered password. This
can result in the found parts of the password being combined differently than the
original coffee script. E.g. the password **passwordassword**
is combined by the original coffee script as **p** (3.5 bits) + **asswordassword** (12.6
bits) + multiple part allowance (1.0bit) to give total entropy of 17.1 bits. This
implementation combines it as **password** (1.0 bit) + **assword** (11.6 bits) + multiple
part allowance (1.0bit) to give 13.6 bits.
* For multi part passwords the original coffee script version multiplies the number of
guesses needed by the factorial of the number of parts. This is not possible in this
version as Dijktra's algorithm is used. Instead one bit entropy is added for the part at the
end of the password, 1.7 bits for each part in the middle of a password and nothing
for the part at the beginning. This gives similar results compared to the coffee script
version when there are 4 or less parts, but will differ significantly when there are many
parts (which is likely to be a rare occurrence).
##References
The original coffee-script version is available at
https://github.com/lowe/zxcvbn
The dictionary words are taken from the original coffee script version.
Dictionary trie encoding (used for by the word lookup code) based on idea from the Caroline
Word Graph from
http://www.pathcom.com/~vadco/cwg.html

File diff suppressed because it is too large Load diff

103
src/zxcvbn-c/makefile Normal file
View file

@ -0,0 +1,103 @@
CFLAGS ?= -O2 -Wall -Wextra -Wdeclaration-after-statement
CXXFLAGS ?= -O2 -Wall -Wextra
# default programs
CC ?= gcc
AR ?= ar
CXX ?= g++
# need zxcvbn.h prior to package installation
CPPFLAGS += -I.
# library metadata
TARGET_LIB = libzxcvbn.so.0.0.0
SONAME = libzxcvbn.so.0
WORDS = words-eng_wiki.txt words-female.txt words-male.txt words-passwd.txt words-surname.txt words-tv_film.txt
all: test-file test-inline test-c++inline test-c++file test-shlib test-statlib
test-shlib: test.c $(TARGET_LIB)
if [ ! -e libzxcvbn.so ]; then ln -s $(TARGET_LIB) libzxcvbn.so; fi
$(CC) $(CPPFLAGS) $(CFLAGS) -o $@ $< -L. $(LDFLAGS) -lzxcvbn -lm
$(TARGET_LIB): zxcvbn-inline-pic.o
$(CC) $(CPPFLAGS) $(CFLAGS) \
-o $@ $^ -fPIC -shared -Wl,-soname,$(SONAME) $(LDFLAGS) -lm
if [ ! -e $(SONAME) ]; then ln -s $(TARGET_LIB) $(SONAME); fi
test-statlib: test.c libzxcvbn.a
$(CC) $(CPPFLAGS) $(CFLAGS) -o $@ $^ $(LDFLAGS) -lm
libzxcvbn.a: zxcvbn-inline.o
$(AR) cvq $@ $^
test-file: test.c zxcvbn-file.o
$(CC) $(CPPFLAGS) $(CFLAGS) \
-DUSE_DICT_FILE -o test-file test.c zxcvbn-file.o $(LDFLAGS) -lm
zxcvbn-file.o: zxcvbn.c dict-crc.h zxcvbn.h
$(CC) $(CPPFLAGS) $(CFLAGS) \
-DUSE_DICT_FILE -c -o zxcvbn-file.o zxcvbn.c
test-inline: test.c zxcvbn-inline.o
$(CC) $(CPPFLAGS) $(CFLAGS) \
-o test-inline test.c zxcvbn-inline.o $(LDFLAGS) -lm
zxcvbn-inline-pic.o: zxcvbn.c dict-src.h zxcvbn.h
$(CC) $(CPPFLAGS) $(CFLAGS) -fPIC -c -o $@ $<
zxcvbn-inline.o: zxcvbn.c dict-src.h zxcvbn.h
$(CC) $(CPPFLAGS) $(CFLAGS) -c -o zxcvbn-inline.o zxcvbn.c
dict-src.h: dictgen $(WORDS)
./dictgen -o dict-src.h $(WORDS)
dict-crc.h: dictgen $(WORDS)
./dictgen -b -o zxcvbn.dict -h dict-crc.h $(WORDS)
dictgen: dict-generate.cpp makefile
$(CXX) $(CPPFLAGS) -std=c++11 $(CXXFLAGS) \
-o dictgen dict-generate.cpp $(LDFLAGS)
test-c++inline: test.c zxcvbn-c++inline.o
if [ ! -e test.cpp ]; then ln -s test.c test.cpp; fi
$(CXX) $(CPPFLAGS) $(CXXFLAGS) \
-o test-c++inline test.cpp zxcvbn-c++inline.o $(LDFLAGS) -lm
zxcvbn-c++inline.o: zxcvbn.c dict-src.h zxcvbn.h
if [ ! -e zxcvbn.cpp ]; then ln -s zxcvbn.c zxcvbn.cpp; fi
$(CXX) $(CPPFLAGS) $(CXXFLAGS) \
-c -o zxcvbn-c++inline.o zxcvbn.cpp
test-c++file: test.c zxcvbn-c++file.o
if [ ! -e test.cpp ]; then ln -s test.c test.cpp; fi
$(CXX) $(CPPFLAGS) $(CXXFLAGS) \
-DUSE_DICT_FILE -o test-c++file test.cpp zxcvbn-c++file.o $(LDFLAGS) -lm
zxcvbn-c++file.o: zxcvbn.c dict-crc.h zxcvbn.h
if [ ! -e zxcvbn.cpp ]; then ln -s zxcvbn.c zxcvbn.cpp; fi
$(CXX) $(CPPFLAGS) $(CXXFLAGS) \
-DUSE_DICT_FILE -c -o zxcvbn-c++file.o zxcvbn.cpp
test: test-file test-inline test-c++inline test-c++file test-shlib test-statlib testcases.txt
@echo Testing C build, dictionary from file
./test-file -t testcases.txt
@echo Testing C build, dictionary in executable
./test-inline -t testcases.txt
@echo Testing C shlib, dictionary in shlib
LD_LIBRARY_PATH=. ./test-shlib -t testcases.txt
@echo Testing C static lib, dictionary in lib
./test-statlib -t testcases.txt
@echo Testing C++ build, dictionary from file
./test-c++file -t testcases.txt
@echo Testing C++ build, dictionary in executable
./test-c++inline -t testcases.txt
@echo Finished
clean:
rm -f test-file zxcvbn-file.o test-c++file zxcvbn-c++file.o
rm -f test-inline zxcvbn-inline.o zxcvbn-inline-pic.o test-c++inline zxcvbn-c++inline.o
rm -f dict-*.h zxcvbn.dict zxcvbn.cpp test.cpp
rm -f dictgen
rm -f ${TARGET_LIB} ${SONAME} libzxcvbn.so test-shlib libzxcvbn.a test-statlib

286
src/zxcvbn-c/test.c Normal file
View file

@ -0,0 +1,286 @@
/**********************************************************************************
* Program to test the C implementation of the zxcvbn password strength estimator.
* Copyright (c) 2015, Tony Evans
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification, are
* permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice, this list
* of conditions and the following disclaimer.
*
* 2. 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.
*
* 3. Neither the name of the copyright holder nor the names of its contributors may be
* used to endorse or promote products derived from this software without specific
* prior written permission.
*
* 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.
*
**********************************************************************************/
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <sys/time.h>
#include <zxcvbn.h>
/* For pre-compiled headers under windows */
#ifdef _WIN32
#include "stdafx.h"
#endif
const char *UsrDict[] =
{
"Onename.Twoname@example.com", "Onename", "Twoname", "example.com", "example",
0
};
static void CalcPass(const char *Pwd, int Quiet)
{
double e;
if (!Quiet)
{
/* Output the details of how the entropy figure was calculated */
int Len, ChkLen;
struct timeval t1, t2;
ZxcMatch_t *Info, *p;
double m = 0.0;
gettimeofday(&t1, 0);
e = ZxcvbnMatch(Pwd, UsrDict, &Info);
gettimeofday(&t2, 0);
for(p = Info; p; p = p->Next)
m += p->Entrpy;
Len = strlen(Pwd);
m = e - m;
printf("Pass %s \tLength %d\tEntropy bits=%.3f log10=%.3f\tMulti-word extra bits=%.1f\n", Pwd, Len, e, e * 0.301029996, m);
p = Info;
ChkLen = 0;
while(p)
{
int n;
switch((int)p->Type)
{
case BRUTE_MATCH: printf(" Type: Bruteforce "); break;
case DICTIONARY_MATCH: printf(" Type: Dictionary "); break;
case DICT_LEET_MATCH: printf(" Type: Dict+Leet "); break;
case USER_MATCH: printf(" Type: User Words "); break;
case USER_LEET_MATCH: printf(" Type: User+Leet "); break;
case REPEATS_MATCH: printf(" Type: Repeated "); break;
case SEQUENCE_MATCH: printf(" Type: Sequence "); break;
case SPATIAL_MATCH: printf(" Type: Spatial "); break;
case DATE_MATCH: printf(" Type: Date "); break;
case BRUTE_MATCH+MULTIPLE_MATCH: printf(" Type: Bruteforce(Rep)"); break;
case DICTIONARY_MATCH+MULTIPLE_MATCH: printf(" Type: Dictionary(Rep)"); break;
case DICT_LEET_MATCH+MULTIPLE_MATCH: printf(" Type: Dict+Leet(Rep) "); break;
case USER_MATCH+MULTIPLE_MATCH: printf(" Type: User Words(Rep)"); break;
case USER_LEET_MATCH+MULTIPLE_MATCH: printf(" Type: User+Leet(Rep) "); break;
case REPEATS_MATCH+MULTIPLE_MATCH: printf(" Type: Repeated(Rep) "); break;
case SEQUENCE_MATCH+MULTIPLE_MATCH: printf(" Type: Sequence(Rep) "); break;
case SPATIAL_MATCH+MULTIPLE_MATCH: printf(" Type: Spatial(Rep) "); break;
case DATE_MATCH+MULTIPLE_MATCH: printf(" Type: Date(Rep) "); break;
default: printf(" Type: Unknown%d ", p->Type); break;
}
ChkLen += p->Length;
printf(" Length %d Entropy %6.3f (%.2f) ", p->Length, p->Entrpy, p->Entrpy * 0.301029996);
for(n = 0; n < p->Length; ++n, ++Pwd)
printf("%c", *Pwd);
printf("\n");
p = p->Next;
}
ZxcvbnFreeInfo(Info);
t2.tv_sec -= t1.tv_sec;
t2.tv_usec -= t1.tv_usec;
t2.tv_usec += t2.tv_sec * 1000000;
printf(" Calculation Time %.2fms\n", t2.tv_usec/1000.0);
if (ChkLen != Len)
printf("*** Password length (%d) != sum of length of parts (%d) ***\n", Len, ChkLen);
}
else
{
/* Only get the final entropy figure */
e = ZxcvbnMatch(Pwd, UsrDict, 0);
printf("Pass %s \tEntropy %.3f\n", Pwd, e);
}
}
int DoChecks(char *file)
{
char Line[500];
int y = 0;
int w = 0;
int r = 0;
FILE *f = fopen(file, "r");
if (f == NULL)
{
printf("Failed to open %s\n", file);
return 1;
}
memset(Line, 0, sizeof Line);
while(fgets(Line, sizeof Line - 4, f))
{
/* Line is password + whitespace + expected entropy */
char *Pwd, *s, *t;
double Ent, e, x;
unsigned int i;
++y;
for(i = 0; i < sizeof Line - 5; ++i)
{
if (!Line[i] || (Line[i] == '\n'))
break;
}
/* Skip blank lines or those starting with # */
if ((i < 3) || (Line[0] == '#'))
continue;
memset(Line + i, 0, 4);
Pwd = Line;
/* Skip leading whitespace */
while(*Pwd && (*Pwd <= ' '))
++Pwd;
/* Make password null termnated */
s = Pwd;
t = strchr(s, '\t');
if (t == NULL)
t = strstr(s, " ");
if (t == NULL)
{
printf("Bad test condition on line %d\n", y);
r = 1;
break;
}
*t++ = 0;
/* Skip whitespace before entropy value */
while(*t && (*t <= ' '))
++t;
if (!*t)
{
printf("Bad test condition on line %d\n", y);
r = 1;
break;
}
Ent = atof(t);
if ((Ent < 0.0) || (Ent > 1000.0))
{
printf("Bad entropy value on line %d\n", y);
r = 1;
break;
}
e = ZxcvbnMatch(Pwd, UsrDict, 0);
x = e / Ent;
/* More than 1% difference is a fail. */
if ((x > 1.01) || (x < 1.0/1.01))
{
printf("Line %2d Calculated entropy %5.2f, expected %5.2f <%s>\n", y, e, Ent, Pwd);
r = 1;
break;
}
++w;
}
fclose(f);
if (!r)
printf("Tested %d words\n", w);
return r;
}
int main(int argc, char **argv)
{
int i, Quiet, Checks, White;
Quiet = 0;
Checks = 0;
White = 0;
if (!ZxcvbnInit("zxcvbn.dict"))
{
printf("Failed to open dictionary file\n");
return 1;
}
if ((argc > 1) && (argv[1][0] == '-'))
{
if (!strcmp(argv[1], "-qs") || !strcmp(argv[1], "-sq"))
Quiet = White = 1;
if (!strcmp(argv[1], "-t"))
Checks = 1;
if (!strcmp(argv[1], "-q"))
Quiet = 1;
if (!strcmp(argv[1], "-s"))
White = 1;
if ((Checks + Quiet + White) == 0)
{
char *s = strrchr(argv[0], '/');
if (s == NULL)
s = argv[0];
else
++s;
printf( "Usage: %s [ -q | -qs ] [ pwd1 pwd2 ... ]\n"
" Output entropy of given passwords. If no passwords on command line read\n"
" them from stdin.\n"
" -q option stops password analysis details from being output.\n"
" -s Ignore anything from space on a line when reading from stdin.\n"
" %s -t file\n"
" Read the file and check for correct results.\n", s, s);
return 1;
}
}
if (Checks)
{
for(i = 2; i < argc; ++i)
{
Checks = DoChecks(argv[i]);
if (Checks)
return 1;
}
return 0;
}
i = 1+Quiet;
if (i >= argc)
{
/* No test passwords on command line, so get them from stdin */
char Line[500];
while(fgets(Line, sizeof Line, stdin))
{
/* Drop the trailing newline character */
for(i = 0; i < (int)(sizeof Line - 1); ++i)
{
if (Line[i] < ' ')
{
Line[i] = 0;
break;
}
if (White && (Line[i] == ' '))
{
Line[i] = 0;
break;
}
}
if (Line[0])
CalcPass(Line, Quiet);
}
}
else
{
/* Do the test passwords on the command line */
for(; i < argc; ++i)
{
CalcPass(argv[i], Quiet);
}
}
ZxcvbnUnInit();
return 0;
}

View file

@ -0,0 +1,62 @@
zxcvbn 5.83
qwER43@! 26.44
Tr0ub4dour&3 30.87
archi 13.61
D0g.................. 19.02
abcdefghijk987654321 8.53
neverforget13/3/1997 34.86
1qaz2wsx3edc 9.98
barbarbara 12.43
abarbarbara 16.18
temppass22 17.20
briansmith 5.32
htimsnairb 6.07
briansmith4mayor 21.63
password1 4.0
viking 7.93
thx1138 7.70
ScoRpi0ns 19.54
do you know 25.51
ryanhunter2000 20.8
rianhunter2000 28.25
asdfghju7654rewq 29.57
AOEUIDHG&*()LS_ 33.33
12345678 1.59
defghi6789 13.61
02468 3.32
adgjmpsvy 4.17
rosebud 8.09
Rosebud 9.09
ROSEBUD 9.09
rosebuD 9.09
R0$38uD 12.09
ros3bud99 14.41
r0s3bud99 14.41
R0$38uD99 17.41
verlineVANDERMARK 27.24
eheuczkqyq 41.24
rWibMFACxAUGZmxhVncy 111.0
illness 11.26
1llness 12.26
i1lness 12.84
11lness 22.44
ssenl1i 12.84
Ba9ZyWABu99[BK#6MBgbH88Tofv)vs$w 171.63
correcthorsebatterystaple 47.98
elpatsyrettabesrohtcerroc 48.98
coRrecth0rseba++ery9.23.2007staple$ 71.95
pass.word.pass.word.pass.word. 60.41
passpasswordword 17.28
quvpzquvpz 24.50
magicfavoriteunclepromisedpublicbotherislandjimseriouslycellleadknowingbrokenadvicesomehowpaidblairlosingpushhelpedkillingusuallyearlierbosslaurabeginninglikedinnocentdocruleselizabethsabrinasummerexcoplearnedthirtyrisklettingphillipspeakingofficerridiculoussupportafternoonericwithsobutallwellareheohaboutrightyou're 545.9

100000
src/zxcvbn-c/words-eng_wiki.txt Normal file

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

1219
src/zxcvbn-c/words-male.txt Normal file

File diff suppressed because it is too large Load diff

47023
src/zxcvbn-c/words-passwd.txt Normal file

File diff suppressed because it is too large Load diff

88799
src/zxcvbn-c/words-surname.txt Normal file

File diff suppressed because it is too large Load diff

39070
src/zxcvbn-c/words-tv_film.txt Normal file

File diff suppressed because it is too large Load diff

1770
src/zxcvbn-c/zxcvbn.c Normal file

File diff suppressed because it is too large Load diff

139
src/zxcvbn-c/zxcvbn.h Normal file
View file

@ -0,0 +1,139 @@
#ifndef ZXCVBN_H_F98183CE2A01_INCLUDED
#define ZXCVBN_H_F98183CE2A01_INCLUDED
/**********************************************************************************
* C implementation of the zxcvbn password strength estimation method.
* Copyright (c) 2015, Tony Evans
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification, are
* permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice, this list
* of conditions and the following disclaimer.
*
* 2. 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.
*
* 3. Neither the name of the copyright holder nor the names of its contributors may be
* used to endorse or promote products derived from this software without specific
* prior written permission.
*
* 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.
*
**********************************************************************************/
/* If this is defined, the dictiononary data is read from file. When undefined */
/* dictionary data is included in the source code. */
/*#define USE_DICT_FILE */
/* If this is defined, C++ builds which read dictionary data from file will use */
/* stdio FILE streams (and fopen,fread,fclose). When undefined, C++ builds will */
/* use std::ifstream to read dictionary data. Ignored for C builds (stdio FILE */
/* streams are always used). */
/*#define USE_FILE_IO */
#ifndef __cplusplus
/* C build. Use the standard malloc/free for heap memory */
#include <stdlib.h>
#define MallocFn(T,N) ((T *)malloc((N) * sizeof(T)))
#define FreeFn(P) free(P)
#else
/* C++ build. Use the new/delete operators for heap memory */
#define MallocFn(T,N) (new T[N])
#define FreeFn(P) (delete [] P)
#endif
/* Enum for the types of match returned in the Info arg to ZxcvbnMatch */
typedef enum
{
NON_MATCH, /* 0 */
BRUTE_MATCH, /* 1 */
DICTIONARY_MATCH, /* 2 */
DICT_LEET_MATCH, /* 3 */
USER_MATCH, /* 4 */
USER_LEET_MATCH, /* 5 */
REPEATS_MATCH, /* 6 */
SEQUENCE_MATCH, /* 7 */
SPATIAL_MATCH, /* 8 */
DATE_MATCH, /* 9 */
YEAR_MATCH, /* 10 */
MULTIPLE_MATCH = 32 /* Added to above to indicate matching part has been repeated */
} ZxcTypeMatch_t;
/* Linked list of information returned in the Info arg to ZxcvbnMatch */
struct ZxcMatch
{
int Begin; /* Char position of begining of match */
int Length; /* Number of chars in the match */
double Entrpy; /* The entropy of the match */
double MltEnpy; /* Entropy with additional allowance for multipart password */
ZxcTypeMatch_t Type; /* Type of match (Spatial/Dictionary/Order/Repeat) */
struct ZxcMatch *Next;
};
typedef struct ZxcMatch ZxcMatch_t;
#ifdef __cplusplus
extern "C" {
#endif
#ifdef USE_DICT_FILE
/**********************************************************************************
* Read the dictionnary data from the given file. Returns 1 if OK, 0 if error.
* Called once at program startup.
*/
int ZxcvbnInit(const char *);
/**********************************************************************************
* Free the dictionnary data after use. Called once at program shutdown.
*/
void ZxcvbnUnInit();
#else
/* As the dictionary data is included in the source, define these functions to do nothing. */
#define ZxcvbnInit(s) 1
#define ZxcvbnUnInit() do {} while(0)
#endif
/**********************************************************************************
* The main password matching function. May be called multiple times.
* The parameters are:
* Passwd The password to be tested. Null terminated string.
* UserDict User supplied dictionary words to be considered particulary bad. Passed
* as a pointer to array of string pointers, with null last entry (like
* the argv parameter to main()). May be null or point to empty array when
* there are no user dictionary words.
* Info The address of a pointer variable to receive information on the parts
* of the password. This parameter can be null if no information is wanted.
* The data should be freed by calling ZxcvbnFreeInfo().
*
* Returns the entropy of the password (in bits).
*/
double ZxcvbnMatch(const char *Passwd, const char *UserDict[], ZxcMatch_t **Info);
/**********************************************************************************
* Free the data returned in the Info parameter to ZxcvbnMatch().
*/
void ZxcvbnFreeInfo(ZxcMatch_t *Info);
#ifdef __cplusplus
}
#endif
#endif