Add some password-related feature (#92)

* Add Standalone Password Generator. Closes #18 
* Add an entropy meter for passwords. Closes #84
* Don't require password repeat when it is visible. Fixes #27
This commit is contained in:
TheZ3ro 2016-11-24 03:59:24 +01:00 committed by Jonathan White
parent 19a960856c
commit b2f3cc6903
28 changed files with 28401 additions and 195 deletions

25
COPYING
View File

@ -27,6 +27,7 @@ Copyright: 2010-2012, Felix Geyer <debfx@fobos.de>
2000-2008, Tom Sato <VEF00200@nifty.ne.jp>
2013, Laszlo Papp <lpapp@kde.org>
2013, David Faure <faure@kde.org>
2016, KeePassXC Team
License: GPL-2 or GPL-3
Files: cmake/GNUInstallDirs.cmake
@ -34,13 +35,16 @@ Copyright: 2011 Nikita Krupen'ko <krnekit@gmail.com>
2011 Kitware, Inc.
License: BSD-3-clause
Files: share/icons/application/*/apps/keepassx.png
share/icons/application/scalable/apps/keepassx.svgz
Copyright: 2006, Otto Salminen
2009, Miguelito Vieira
2011-2013, Felix Geyer <debfx@fobos.de>
2012, Tobias Tangemann <tobiastangemann@gmail.com>
License: GPL-2
Files: share/icons/application/*/apps/keepassxc.png
share/icons/application/scalable/apps/keepassxc.svgz
share/icons/application/*/apps/keepassxc-dark.png
share/icons/application/scalable/apps/keepassxc-dark.svgz
share/icons/application/*/apps/keepassxc-locked.png
share/icons/application/scalable/apps/keepassxc-locked.svgz
share/icons/application/*/mimetypes/application-x-keepassxc.png
share/icons/application/scalable/mimetypes/application-x-keepassxc.svgz
Copyright: 2016, Lorenzo Stella <lorenzo.stl@gmail.com>
License: LGPL-2
Files: share/icons/application/*/actions/auto-type.png
share/icons/application/*/actions/database-change-key.png
@ -136,6 +140,7 @@ Files: share/icons/application/*/actions/application-exit.png
share/icons/application/*/actions/document-save-as.png
share/icons/application/*/actions/edit-clear-locationbar-ltr.png
share/icons/application/*/actions/edit-clear-locationbar-rtl.png
share/icons/application/*/actions/password-generator.png
share/icons/application/*/actions/password-copy.png
share/icons/application/*/actions/password-show-*.png
share/icons/application/*/actions/system-search.png
@ -187,3 +192,9 @@ License: LGPL-2.1 or GPL-3
Files: cmake/GetGitRevisionDescription.cmake*
Copyright: 2009-2010, Iowa State University
License: Boost-1.0
Files: src/zxcvbn/zxcvbn.*
src/utils/entropy-meter.cpp
Copyright: 2015, Tony Evans
2016, KeePassXC Team
License: BSD 3-clause

Binary file not shown.

After

Width:  |  Height:  |  Size: 733 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.0 KiB

View File

@ -0,0 +1,865 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!-- Created with Inkscape (http://www.inkscape.org/) -->
<svg
xmlns:dc="http://purl.org/dc/elements/1.1/"
xmlns:cc="http://creativecommons.org/ns#"
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:svg="http://www.w3.org/2000/svg"
xmlns="http://www.w3.org/2000/svg"
xmlns:xlink="http://www.w3.org/1999/xlink"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
width="128"
height="128"
id="svg1307"
sodipodi:version="0.32"
inkscape:version="0.46+devel"
version="1.0"
sodipodi:docname="roll.svgz"
inkscape:output_extension="org.inkscape.output.svgz.inkscape"
inkscape:export-filename="/home/pinheiro/pics/oxygen-icons/scalable/actions/roll.png"
inkscape:export-xdpi="180"
inkscape:export-ydpi="180">
<defs
id="defs1309">
<linearGradient
id="linearGradient3718"
inkscape:collect="always">
<stop
id="stop3720"
offset="0"
style="stop-color:#ffffff;stop-opacity:1;" />
<stop
id="stop3722"
offset="1"
style="stop-color:#ffffff;stop-opacity:0" />
</linearGradient>
<linearGradient
id="linearGradient3680">
<stop
id="stop3682"
offset="0"
style="stop-color:#ffffff;stop-opacity:1;" />
<stop
style="stop-color:#ffffff;stop-opacity:0.49803922;"
offset="0.22032471"
id="stop3684" />
<stop
style="stop-color:#ffffff;stop-opacity:0;"
offset="0.5"
id="stop3686" />
<stop
id="stop3688"
offset="0.5"
style="stop-color:#ffffff;stop-opacity:0;" />
<stop
id="stop3690"
offset="1"
style="stop-color:#ffffff;stop-opacity:0;" />
</linearGradient>
<linearGradient
inkscape:collect="always"
id="linearGradient3291">
<stop
style="stop-color:#ffffff;stop-opacity:1;"
offset="0"
id="stop3293" />
<stop
style="stop-color:#ffffff;stop-opacity:0;"
offset="1"
id="stop3295" />
</linearGradient>
<inkscape:perspective
sodipodi:type="inkscape:persp3d"
inkscape:vp_x="0 : 64 : 1"
inkscape:vp_y="0 : 1000 : 0"
inkscape:vp_z="128 : 64 : 1"
inkscape:persp3d-origin="64 : 42.666667 : 1"
id="perspective87" />
<linearGradient
inkscape:collect="always"
id="linearGradient2381">
<stop
style="stop-color:#393939;stop-opacity:1;"
offset="0"
id="stop2383" />
<stop
style="stop-color:#393939;stop-opacity:0;"
offset="1"
id="stop2385" />
</linearGradient>
<linearGradient
inkscape:collect="always"
id="linearGradient2518">
<stop
style="stop-color:#ffffff;stop-opacity:1;"
offset="0"
id="stop2520" />
<stop
style="stop-color:#ffffff;stop-opacity:0;"
offset="1"
id="stop2522" />
</linearGradient>
<linearGradient
id="linearGradient2496">
<stop
style="stop-color:#ffffff;stop-opacity:1;"
offset="0"
id="stop2498" />
<stop
id="stop2508"
offset="0.04228718"
style="stop-color:#ffffff;stop-opacity:0.49803922;" />
<stop
id="stop2504"
offset="0.5"
style="stop-color:#ffffff;stop-opacity:0;" />
<stop
style="stop-color:#ffffff;stop-opacity:0;"
offset="0.5"
id="stop2506" />
<stop
style="stop-color:#ffffff;stop-opacity:0;"
offset="1"
id="stop2500" />
</linearGradient>
<linearGradient
inkscape:collect="always"
id="linearGradient2488">
<stop
style="stop-color:#ffffff;stop-opacity:1;"
offset="0"
id="stop2490" />
<stop
style="stop-color:#ffffff;stop-opacity:0;"
offset="1"
id="stop2492" />
</linearGradient>
<linearGradient
inkscape:collect="always"
id="linearGradient2453">
<stop
style="stop-color:#ffffff;stop-opacity:1;"
offset="0"
id="stop2455" />
<stop
style="stop-color:#ffffff;stop-opacity:0;"
offset="1"
id="stop2457" />
</linearGradient>
<linearGradient
inkscape:collect="always"
id="linearGradient2419">
<stop
style="stop-color:#ffffff;stop-opacity:1;"
offset="0"
id="stop2421" />
<stop
style="stop-color:#ffffff;stop-opacity:0;"
offset="1"
id="stop2423" />
</linearGradient>
<linearGradient
id="linearGradient3225">
<stop
style="stop-color:#ffffff;stop-opacity:1;"
offset="0"
id="stop3227" />
<stop
id="stop2347"
offset="0.5"
style="stop-color:#e9e9e9;stop-opacity:1;" />
<stop
style="stop-color:#d3d3d3;stop-opacity:1;"
offset="1"
id="stop3229" />
</linearGradient>
<radialGradient
inkscape:collect="always"
xlink:href="#linearGradient2419"
id="radialGradient2425"
cx="96.433075"
cy="57.087173"
fx="96.433075"
fy="57.087173"
r="59.198612"
gradientTransform="matrix(0.32911414,-0.18426278,0.00344988,0.00676072,59.169639,65.342464)"
gradientUnits="userSpaceOnUse" />
<radialGradient
inkscape:collect="always"
xlink:href="#linearGradient2419"
id="radialGradient2429"
gradientUnits="userSpaceOnUse"
gradientTransform="matrix(0.31464719,0.16663594,-0.00390006,0.0070264,6.1939502,29.102501)"
cx="96.433075"
cy="57.087173"
fx="96.433075"
fy="57.087173"
r="59.198612" />
<radialGradient
inkscape:collect="always"
xlink:href="#linearGradient2419"
id="radialGradient2433"
gradientUnits="userSpaceOnUse"
gradientTransform="matrix(-6.5370771e-4,0.36915148,-0.01148035,8.9888928e-4,66.206754,56.948367)"
cx="96.433075"
cy="57.087173"
fx="96.433075"
fy="57.087173"
r="59.198612" />
<radialGradient
inkscape:collect="always"
xlink:href="#linearGradient2419"
id="radialGradient2480"
gradientUnits="userSpaceOnUse"
gradientTransform="matrix(0.30975608,-0.17225438,0.00324696,0.00631933,7.1075276,35.761713)"
cx="96.433075"
cy="57.087173"
fx="96.433075"
fy="57.087173"
r="59.198612" />
<radialGradient
inkscape:collect="always"
xlink:href="#linearGradient2419"
id="radialGradient2484"
gradientUnits="userSpaceOnUse"
gradientTransform="matrix(0.30528058,0.15922188,-0.00378396,0.00671573,60.709321,2.5331232)"
cx="96.433075"
cy="57.087173"
fx="96.433075"
fy="57.087173"
r="59.198612" />
<linearGradient
inkscape:collect="always"
xlink:href="#linearGradient2496"
id="linearGradient1432"
gradientUnits="userSpaceOnUse"
gradientTransform="matrix(0.814691,-0.4513534,-0.01142073,0.9309698,-11.541647,47.221462)"
x1="116.81535"
y1="186.85913"
x2="154.86906"
y2="30.208342" />
<radialGradient
inkscape:collect="always"
xlink:href="#linearGradient3718"
id="radialGradient1435"
gradientUnits="userSpaceOnUse"
gradientTransform="matrix(0.4096939,-0.05084026,0.0016784,0.495142,37.98752,30.25767)"
cx="68.964005"
cy="63.915367"
fx="68.964005"
fy="63.915367"
r="20.153163" />
<radialGradient
inkscape:collect="always"
xlink:href="#linearGradient2518"
id="radialGradient1438"
gradientUnits="userSpaceOnUse"
gradientTransform="matrix(0.68188455,-0.10453237,0.03601738,0.43439777,16.732111,38.459404)"
cx="68.964005"
cy="63.915367"
fx="68.964005"
fy="63.915367"
r="20.153163" />
<linearGradient
inkscape:collect="always"
xlink:href="#linearGradient2488"
id="linearGradient1441"
gradientUnits="userSpaceOnUse"
x1="94.021759"
y1="3.2521791"
x2="92.337082"
y2="6.8190994"
gradientTransform="matrix(0.77496397,-0.47736424,0.41995021,0.75244601,-11.810014,48.172506)" />
<radialGradient
inkscape:collect="always"
xlink:href="#linearGradient3225"
id="radialGradient1456"
gradientUnits="userSpaceOnUse"
gradientTransform="matrix(0.80824314,-0.45051001,-0.01677524,0.96571805,-10.092238,38.234456)"
cx="113.60279"
cy="117.94415"
fx="113.60279"
fy="117.94415"
r="6.6403217" />
<radialGradient
inkscape:collect="always"
xlink:href="#linearGradient3225"
id="radialGradient1459"
gradientUnits="userSpaceOnUse"
gradientTransform="matrix(0.80824314,-0.45051001,-0.01677524,0.96571805,-12.747064,45.293861)"
cx="148.67097"
cy="79.114578"
fx="148.67097"
fy="79.114578"
r="6.2969127" />
<radialGradient
inkscape:collect="always"
xlink:href="#linearGradient3225"
id="radialGradient1463"
gradientUnits="userSpaceOnUse"
gradientTransform="matrix(0.76906443,0.41392843,-0.01330547,0.86085475,-11.512513,48.253962)"
cx="59.905712"
cy="5.9431438"
fx="59.905712"
fy="5.9431438"
r="7.4961972" />
<radialGradient
inkscape:collect="always"
xlink:href="#linearGradient3225"
id="radialGradient1467"
gradientUnits="userSpaceOnUse"
gradientTransform="matrix(0.81000807,-0.44693085,0.84280642,0.45175053,-16.121677,46.553274)"
cx="84.408051"
cy="50.798088"
fx="84.408051"
fy="50.798088"
r="6.9240074" />
<radialGradient
inkscape:collect="always"
xlink:href="#linearGradient3225"
id="radialGradient1471"
gradientUnits="userSpaceOnUse"
gradientTransform="matrix(0.81000807,-0.44693085,0.84280642,0.45175053,-13.240155,47.67091)"
cx="67.268486"
cy="30.446516"
fx="67.268486"
fy="30.446516"
r="6.8208823" />
<radialGradient
inkscape:collect="always"
xlink:href="#linearGradient3225"
id="radialGradient1474"
gradientUnits="userSpaceOnUse"
gradientTransform="matrix(0.81000807,-0.44693085,0.84280642,0.45175053,-11.409803,49.062709)"
cx="49.933464"
cy="9.8521395"
fx="49.933464"
fy="9.8521395"
r="6.9496646" />
<radialGradient
inkscape:collect="always"
xlink:href="#linearGradient2453"
id="radialGradient1480"
gradientUnits="userSpaceOnUse"
gradientTransform="matrix(0.5645257,-0.34773821,0.28363904,0.50821111,10.679939,54.077116)"
cx="67.876709"
cy="60.201225"
fx="67.876709"
fy="60.201225"
r="60.815896" />
<linearGradient
inkscape:collect="always"
xlink:href="#linearGradient2381"
id="linearGradient2387"
x1="-90.709442"
y1="153.80435"
x2="78.643684"
y2="12.660598"
gradientUnits="userSpaceOnUse"
gradientTransform="matrix(0.75854865,0.40826863,-0.0137637,0.89050228,-5.4092216,29.668461)" />
<linearGradient
inkscape:collect="always"
xlink:href="#linearGradient3291"
id="linearGradient3297"
x1="57.296326"
y1="-20.721647"
x2="67.490227"
y2="55.915768"
gradientUnits="userSpaceOnUse" />
<linearGradient
inkscape:collect="always"
xlink:href="#linearGradient3291"
id="linearGradient3301"
gradientUnits="userSpaceOnUse"
x1="57.296326"
y1="-16.490377"
x2="57.296326"
y2="45.567513" />
<filter
inkscape:collect="always"
id="filter3429"
x="-0.090069178"
width="1.1801384"
y="-0.16560408"
height="1.3312082">
<feGaussianBlur
inkscape:collect="always"
stdDeviation="0.68605903"
id="feGaussianBlur3431" />
</filter>
<filter
inkscape:collect="always"
id="filter3433"
x="-0.091769746"
width="1.1835395"
y="-0.1687308"
height="1.3374616">
<feGaussianBlur
inkscape:collect="always"
stdDeviation="0.68605903"
id="feGaussianBlur3435" />
</filter>
<filter
inkscape:collect="always"
id="filter3437"
x="-0.090402938"
width="1.1808059"
y="-0.16621775"
height="1.3324355">
<feGaussianBlur
inkscape:collect="always"
stdDeviation="0.68605903"
id="feGaussianBlur3439" />
</filter>
<filter
inkscape:collect="always"
id="filter3482"
x="-0.039611745"
width="1.0792235"
y="-0.29708207"
height="1.5941641">
<feGaussianBlur
inkscape:collect="always"
stdDeviation="1.3721181"
id="feGaussianBlur3484" />
</filter>
<filter
inkscape:collect="always"
id="filter3518">
<feGaussianBlur
inkscape:collect="always"
stdDeviation="0.45785798"
id="feGaussianBlur3520" />
</filter>
<filter
inkscape:collect="always"
id="filter3574">
<feGaussianBlur
inkscape:collect="always"
stdDeviation="1.0125102"
id="feGaussianBlur3576" />
</filter>
<radialGradient
inkscape:collect="always"
xlink:href="#linearGradient2453"
id="radialGradient3638"
gradientUnits="userSpaceOnUse"
gradientTransform="matrix(-0.634595,-0.3859285,-0.3188445,0.5737883,277.62315,52.360143)"
cx="67.876709"
cy="60.201225"
fx="67.876709"
fy="60.201225"
r="60.815896" />
<radialGradient
inkscape:collect="always"
xlink:href="#linearGradient3225"
id="radialGradient3640"
gradientUnits="userSpaceOnUse"
gradientTransform="matrix(-0.8645212,0.4720778,1.4956952e-2,0.9675874,302.57014,45.61879)"
cx="59.905712"
cy="5.9431438"
fx="59.905712"
fy="5.9431438"
r="7.4961972" />
<radialGradient
inkscape:collect="always"
xlink:href="#linearGradient3225"
id="radialGradient3642"
gradientUnits="userSpaceOnUse"
gradientTransform="matrix(-0.9085628,-0.4993103,1.8857387e-2,1.0854359,303.95792,42.280409)"
cx="148.67097"
cy="79.114578"
fx="148.67097"
fy="79.114578"
r="6.2969127" />
<radialGradient
inkscape:collect="always"
xlink:href="#linearGradient3225"
id="radialGradient3644"
gradientUnits="userSpaceOnUse"
gradientTransform="matrix(-0.9085628,-0.4993103,1.8857387e-2,1.0854359,300.97358,34.368164)"
cx="113.60279"
cy="117.94415"
fx="113.60279"
fy="117.94415"
r="6.6403217" />
<radialGradient
inkscape:collect="always"
xlink:href="#linearGradient2419"
id="radialGradient3646"
gradientUnits="userSpaceOnUse"
gradientTransform="matrix(-0.369964,-0.2042355,-3.878083e-3,7.6302398e-3,223.11488,65.450748)"
cx="96.433075"
cy="57.087173"
fx="96.433075"
fy="57.087173"
r="59.198612" />
<radialGradient
inkscape:collect="always"
xlink:href="#linearGradient2419"
id="radialGradient3648"
gradientUnits="userSpaceOnUse"
gradientTransform="matrix(-0.3537014,0.1900896,4.3841428e-3,7.864176e-3,282.66594,24.246158)"
cx="96.433075"
cy="57.087173"
fx="96.433075"
fy="57.087173"
r="59.198612" />
<radialGradient
inkscape:collect="always"
xlink:href="#linearGradient2419"
id="radialGradient3650"
gradientUnits="userSpaceOnUse"
gradientTransform="matrix(7.3484633e-4,0.414965,1.2905298e-2,9.0936266e-4,214.00431,56.076739)"
cx="96.433075"
cy="57.087173"
fx="96.433075"
fy="57.087173"
r="59.198612" />
<radialGradient
inkscape:collect="always"
xlink:href="#linearGradient2419"
id="radialGradient3652"
gradientUnits="userSpaceOnUse"
gradientTransform="matrix(-0.369964,-0.2042355,-3.878083e-3,7.6302398e-3,282.46217,32.207255)"
cx="96.433075"
cy="57.087173"
fx="96.433075"
fy="57.087173"
r="59.198612" />
<radialGradient
inkscape:collect="always"
xlink:href="#linearGradient2419"
id="radialGradient3654"
gradientUnits="userSpaceOnUse"
gradientTransform="matrix(-0.3537014,0.1900896,4.3841428e-3,7.864176e-3,223.01536,-6.4711824)"
cx="96.433075"
cy="57.087173"
fx="96.433075"
fy="57.087173"
r="59.198612" />
<linearGradient
inkscape:collect="always"
xlink:href="#linearGradient2488"
id="linearGradient3656"
gradientUnits="userSpaceOnUse"
gradientTransform="matrix(-0.871153,-0.5297908,-0.4720747,0.8495381,302.90457,45.524605)"
x1="94.021759"
y1="3.2521791"
x2="92.337082"
y2="6.8190994" />
<radialGradient
inkscape:collect="always"
xlink:href="#linearGradient2518"
id="radialGradient3658"
gradientUnits="userSpaceOnUse"
gradientTransform="matrix(-0.7665205,-0.1115024,-4.0487885e-2,0.4886327,270.81978,34.857245)"
cx="68.964005"
cy="63.915367"
fx="68.964005"
fy="63.915367"
r="20.153163" />
<radialGradient
inkscape:collect="always"
xlink:href="#linearGradient2518"
id="radialGradient3660"
gradientUnits="userSpaceOnUse"
gradientTransform="matrix(0.2230559,-1.7307682e-2,7.7435003e-3,0.4922829,50.471168,28.127869)"
cx="68.964005"
cy="63.915367"
fx="68.964005"
fy="63.915367"
r="20.153163" />
<linearGradient
inkscape:collect="always"
xlink:href="#linearGradient2496"
id="linearGradient3662"
gradientUnits="userSpaceOnUse"
gradientTransform="matrix(0.814691,-0.4513534,-1.1420728e-2,0.9309698,-11.541647,47.22146)"
x1="116.81535"
y1="186.85913"
x2="154.86906"
y2="30.208342" />
<linearGradient
inkscape:collect="always"
xlink:href="#linearGradient2381"
id="linearGradient3664"
gradientUnits="userSpaceOnUse"
gradientTransform="matrix(-0.8527002,0.4656229,1.5472064e-2,1.0009108,295.7093,24.780188)"
x1="-90.709442"
y1="153.80435"
x2="78.643684"
y2="12.660598" />
<linearGradient
inkscape:collect="always"
xlink:href="#linearGradient3291"
id="linearGradient3666"
gradientUnits="userSpaceOnUse"
x1="57.296326"
y1="-16.490377"
x2="57.296326"
y2="45.567513" />
<radialGradient
inkscape:collect="always"
xlink:href="#linearGradient3225"
id="radialGradient3668"
gradientUnits="userSpaceOnUse"
gradientTransform="matrix(-0.9105468,-0.4952714,-0.9474161,0.5152438,302.45468,46.528825)"
cx="49.933464"
cy="9.8521395"
fx="49.933464"
fy="9.8521395"
r="6.9496646" />
<radialGradient
inkscape:collect="always"
xlink:href="#linearGradient3225"
id="radialGradient3670"
gradientUnits="userSpaceOnUse"
gradientTransform="matrix(-0.9105468,-0.4952714,-0.9474161,0.5152438,304.51222,44.948156)"
cx="67.268486"
cy="30.446516"
fx="67.268486"
fy="30.446516"
r="6.8208823" />
<radialGradient
inkscape:collect="always"
xlink:href="#linearGradient3225"
id="radialGradient3672"
gradientUnits="userSpaceOnUse"
gradientTransform="matrix(-0.9105468,-0.4952714,-0.9474161,0.5152438,307.7514,43.666425)"
cx="84.408051"
cy="50.798088"
fx="84.408051"
fy="50.798088"
r="6.9240074" />
<linearGradient
inkscape:collect="always"
xlink:href="#linearGradient3680"
id="linearGradient3678"
gradientUnits="userSpaceOnUse"
gradientTransform="matrix(0.814691,-0.4513534,-0.01142073,0.9309698,-11.541647,47.221462)"
x1="274.36163"
y1="186.47618"
x2="42.380108"
y2="13.043629" />
<filter
inkscape:collect="always"
id="filter3714">
<feGaussianBlur
inkscape:collect="always"
stdDeviation="0.42187368"
id="feGaussianBlur3716" />
</filter>
<filter
inkscape:collect="always"
id="filter3753">
<feGaussianBlur
inkscape:collect="always"
stdDeviation="0.76746435"
id="feGaussianBlur3755" />
</filter>
</defs>
<sodipodi:namedview
id="base"
pagecolor="#ffffff"
bordercolor="#666666"
borderopacity="1.0"
inkscape:pageopacity="0.0"
inkscape:pageshadow="2"
inkscape:zoom="3.0078888"
inkscape:cx="119.14631"
inkscape:cy="77.382382"
inkscape:current-layer="layer1"
showgrid="false"
inkscape:document-units="px"
inkscape:grid-bbox="true"
guidetolerance="0.1px"
showguides="true"
inkscape:guide-bbox="true"
inkscape:window-width="1106"
inkscape:window-height="958"
inkscape:window-x="376"
inkscape:window-y="25" />
<metadata
id="metadata1312">
<rdf:RDF>
<cc:Work
rdf:about="">
<dc:format>image/svg+xml</dc:format>
<dc:type
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
<cc:license
rdf:resource="http://creativecommons.org/licenses/GPL/2.0/" />
<dc:contributor>
<cc:Agent>
<dc:title>Oxygen team</dc:title>
</cc:Agent>
</dc:contributor>
<dc:title></dc:title>
</cc:Work>
<cc:License
rdf:about="http://creativecommons.org/licenses/LGPL/2.1/">
<cc:permits
rdf:resource="http://web.resource.org/cc/Reproduction" />
<cc:permits
rdf:resource="http://web.resource.org/cc/Distribution" />
<cc:requires
rdf:resource="http://web.resource.org/cc/Notice" />
<cc:permits
rdf:resource="http://web.resource.org/cc/DerivativeWorks" />
<cc:requires
rdf:resource="http://web.resource.org/cc/ShareAlike" />
<cc:requires
rdf:resource="http://web.resource.org/cc/SourceCode" />
</cc:License>
</rdf:RDF>
</metadata>
<g
id="layer1"
inkscape:label="Layer 1"
inkscape:groupmode="layer">
<path
style="fill:#181818;fill-opacity:1;fill-rule:evenodd;stroke:none;filter:url(#filter3753)"
d="m 63.6875,11.34375 c -0.307888,0.01157 -0.622049,0.03822 -0.9375,0.0625 -0.124077,0.0093 -0.251114,0.0201 -0.375,0.03125 -0.05233,0.0049 -0.103739,0.02601 -0.15625,0.03125 -0.712,0.06846 -1.428165,0.153454 -2.125,0.28125 -0.155698,0.02997 -0.311968,0.06025 -0.46875,0.09375 -1.997959,0.408268 -3.903345,1.039509 -5.53125,1.9375 -0.566172,0.280908 -1.121148,0.597939 -1.6875,0.9375 l -2.0625,1.125 c -3.384614,1.788314 -7.092461,4.343647 -12.375,7.28125 -3.43228,1.90868 -6.456933,3.625939 -9.1875,5.1875 l -4.96875,2.75 c -0.498481,0.274974 -0.961001,0.544756 -1.375,0.84375 l -0.3125,0.1875 c -0.268281,0.175855 -0.545708,0.372427 -0.8125,0.5625 -0.966273,0.596455 -1.527441,1.009092 -1.5,1.0625 0.0068,0.0132 0.146679,-0.07019 0.21875,-0.09375 -3.962556,3.207756 -7.410412,7.880262 -8,12.96875 L 12.0625,46.75 c -0.07009,0.509421 -0.116296,1.030587 -0.125,1.59375 L 10.34375,83.3125 c -0.105144,6.80274 4.445942,14.767952 10.21875,17.875 L 53.8125,119 c 0.416106,0.22396 0.814802,0.4009 1.21875,0.5625 6.179168,2.49704 14.387189,2.03917 19.03125,-0.53125 0.38938,-0.16551 0.784222,-0.33772 1.1875,-0.5625 l 31.125,-17.75 c 5.44542,-3.035234 9.8947,-10.375507 10,-16.4375 l -0.34375,-35.625 c 0.006,-0.33561 -0.0106,-0.655677 -0.0313,-0.96875 l 0.125,-0.21875 C 115.17195,41.889964 112.94649,34.769399 108.25,32.1875 l -1.375,-0.59375 C 106.25301,31.004608 98.645471,26.824191 89.15625,21.875 85.474411,19.954703 82.224469,18.29233 79.34375,16.84375 l -6.53125,-3.5 c -2.121537,-1.139951 -3.811692,-1.796844 -6.625,-1.96875 -0.253862,-0.01693 -0.519547,-0.02233 -0.78125,-0.03125 -0.147499,-0.0043 -0.289561,0.0017 -0.4375,0 -0.414575,-0.0064 -0.85006,-0.0162 -1.28125,0 z"
id="path2913"
sodipodi:nodetypes="cssssscccscccccscccccccccccccccccsccsssc" />
<path
style="fill:#181818;fill-opacity:1;fill-rule:evenodd;stroke:none"
d="m 21.128502,28.09122 c -4.766214,3.124206 -9.405072,8.541154 -10.096359,14.50736 l 8.629169,48.78787 35.366196,27.16282 c 5.06326,2.14656 14.524273,2.44687 19.76131,-0.92915 L 117.12128,43.463792 c -0.95305,-5.578786 -3.1596,-12.685613 -7.85609,-15.267512 L 76.187417,14.016615 27.411339,24.642694 21.128502,28.09122 z"
id="path2415"
sodipodi:nodetypes="cccccccccc" />
<path
style="opacity:0;fill:url(#radialGradient1480);fill-opacity:1;fill-rule:evenodd;stroke:none"
d="m 21.128502,28.09122 c -4.766214,3.124206 -9.405072,8.541154 -10.096359,14.50736 l 8.629169,48.78787 37.487054,27.87435 c 4.487477,0.90002 9.451421,1.77535 17.640452,-2.89762 L 117.12128,43.463792 c -0.95305,-5.578786 -3.1596,-12.685613 -7.85609,-15.267512 L 76.187417,14.016615 27.411339,24.642694 21.128502,28.09122 z"
id="path2435"
sodipodi:nodetypes="cccccccccc" />
<path
style="fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none"
d="m 21.534884,37.678074 33.235279,17.969949 c 5.772809,3.10706 10.335586,11.084985 10.230441,17.887724 l -0.586755,37.784793 c -0.105145,6.80273 -4.837214,9.77795 -10.610022,6.67089 L 20.568547,100.1994 C 14.795739,97.092352 10.232963,89.114423 10.338107,82.311683 l 0.586756,-37.96271 c 0.105144,-6.802738 4.837213,-9.777959 10.610021,-6.670899 z"
id="rect1412"
sodipodi:nodetypes="ccccccccc" />
<path
style="fill:#1a1a1a;fill-opacity:1;fill-rule:nonzero;stroke:none"
d="M 22.804196,27.057004 54.101765,9.7925263 C 59.722729,6.6918703 68.514472,6.488197 73.814194,9.3358593 L 108.41349,27.926853 c 5.29972,2.847662 5.0411,7.636379 -0.57986,10.737037 L 76.536061,55.928366 c -5.620963,3.100656 -14.412707,3.304329 -19.712429,0.456667 L 22.224339,37.79404 c -5.299722,-2.847662 -5.041106,-7.636381 0.579857,-10.737036 z"
id="rect1414" />
<path
style="fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none"
d="M 76.279616,56.950767 107.40321,39.201951 c 5.44542,-3.03524 9.7445,-0.598541 9.6392,5.463458 l -0.65538,38.618606 c -0.1053,6.061993 -4.57393,13.385785 -10.01935,16.421019 L 75.244086,117.45385 c -5.445414,3.03523 -9.744496,0.59853 -9.639194,-5.46346 l 0.65538,-38.61861 c 0.105301,-6.062 4.57393,-13.385772 10.019344,-16.421013 z"
id="rect1416"
sodipodi:nodetypes="ccccccccc" />
<path
style="fill:url(#radialGradient1463);fill-opacity:1;fill-rule:nonzero;stroke:none"
d="m 34.579473,71.713674 c 3.193841,1.719 5.720571,5.980985 5.665315,9.556022 -0.05526,3.575036 -2.670955,5.069246 -5.864796,3.350246 -3.19384,-1.719 -5.720571,-5.980986 -5.665314,-9.556022 0.05526,-3.575036 2.670954,-5.069247 5.864795,-3.350246 z"
id="rect2299" />
<path
style="fill:url(#radialGradient1459);fill-opacity:1;fill-rule:nonzero;stroke:none"
d="m 106.19386,48.637332 c 2.81955,-1.571604 5.04233,-0.124684 4.98382,3.244214 -0.0585,3.368899 -2.37553,7.346262 -5.19509,8.917866 -2.81954,1.571599 -5.04232,0.124685 -4.9838,-3.244214 0.0585,-3.368897 2.37552,-7.346266 5.19507,-8.917866 z"
id="rect2301" />
<path
style="fill:url(#radialGradient1456);fill-opacity:1;fill-rule:nonzero;stroke:none"
d="m 79.85942,94.543208 c 2.973317,-1.657309 5.317323,-0.131486 5.255611,3.421141 -0.06171,3.552621 -2.505079,7.746891 -5.478396,9.404201 -2.973318,1.65731 -5.317324,0.13148 -5.255611,-3.42112 0.06171,-3.55264 2.505079,-7.746904 5.478396,-9.404222 z"
id="rect2303" />
<path
style="fill:url(#radialGradient2425);fill-opacity:1;fill-rule:nonzero;stroke:none"
d="m 110.58717,37.051279 c 0.11274,0.220925 -8.5242,5.287057 -19.278872,11.30833 -10.754671,6.021272 -19.574594,10.728803 -19.687327,10.507878 -0.112734,-0.220924 8.5242,-5.287055 19.278871,-11.308329 10.754678,-6.021273 19.574588,-10.728803 19.687328,-10.507879 z"
id="path2417" />
<path
style="fill:url(#radialGradient2429);fill-opacity:1;fill-rule:nonzero;stroke:none"
d="M 54.940385,55.437448 C 54.81294,55.667054 46.364754,51.434053 36.082827,45.988786 25.8009,40.543518 17.559582,35.937824 17.687026,35.708218 c 0.127446,-0.229607 8.575631,4.003395 18.857558,9.448661 10.281927,5.445267 18.523246,10.050963 18.395801,10.280569 z"
id="path2427" />
<path
style="opacity:0.352459;fill:url(#radialGradient2433);fill-opacity:1;fill-rule:nonzero;stroke:none"
d="m 65.449635,114.45135 c -0.375151,0.0294 -0.662284,-9.73704 -0.640922,-21.800043 0.02136,-12.062997 0.343169,-21.877093 0.71832,-21.906467 0.37515,-0.02937 0.662284,9.737046 0.640922,21.800043 -0.02136,12.062997 -0.343169,21.877087 -0.71832,21.906467 z"
id="path2431" />
<path
style="fill:url(#radialGradient2480);fill-opacity:1;fill-rule:nonzero;stroke:none"
d="M 55.500752,9.3142325 C 55.606855,9.5207335 47.477933,14.256682 37.355837,19.885546 27.23374,25.514411 18.932593,29.915169 18.826489,29.708669 18.720387,29.502168 26.849309,24.76622 36.971404,19.137356 47.093501,13.508491 55.394649,9.1077316 55.500752,9.3142325 z"
id="path2478" />
<path
style="fill:url(#radialGradient2484);fill-opacity:1;fill-rule:nonzero;stroke:none"
d="M 108.00464,27.696488 C 107.88099,27.915941 99.6843,23.871327 89.70845,18.668329 79.732601,13.465333 71.736615,9.0645036 71.860266,8.8450494 c 0.123651,-0.2194542 8.320347,3.8251596 18.296196,9.0281566 9.975848,5.202996 17.971838,9.603826 17.848178,9.823282 z"
id="path2482" />
<path
style="fill:url(#linearGradient1441);fill-opacity:1;fill-rule:evenodd;stroke:none"
d="M 52.391314,10.725421 C 60.218637,6.0324839 68.182969,7.1388117 72.02313,8.5821097 66.243539,7.7850786 57.513187,8.4568441 52.391314,10.725421 z"
id="path2486" />
<path
style="fill:url(#linearGradient1432);fill-opacity:1;fill-rule:nonzero;stroke:none;filter:url(#filter3574)"
d="m 77.08844,56.915281 34.08864,-19.331703 c 5.59118,-3.097618 10.02975,-0.486059 9.95196,5.855507 l -0.50832,41.436025 c -0.0778,6.341565 -4.64162,13.940612 -10.23281,17.03823 l -34.088639,20.3317 c -5.591181,3.09763 -10.029752,0.48606 -9.951956,-5.8555 l 0.508319,-42.43603 c 0.0778,-6.341566 4.641626,-13.940614 10.232806,-17.038229 z"
id="rect2556"
sodipodi:nodetypes="ccccccccc"
transform="matrix(0.88958423,-0.00696863,0,0.88958423,7.0366649,7.5268987)" />
<path
style="fill:url(#radialGradient1438);fill-opacity:1;fill-rule:evenodd;stroke:none"
d="m 50.216546,53.06469 7.857374,4.162351 c 3.644704,1.96934 11.80512,2.303829 17.092856,-0.409972 l 14.63311,-8.036739 -14.617571,7.67824 c -6.819372,2.782435 -12.100091,1.948265 -17.117359,0.49485 l -7.84841,-3.88873 z"
id="path2514" />
<path
style="opacity:0.54455447;fill:url(#radialGradient1435);fill-opacity:1;fill-rule:evenodd;stroke:none;filter:url(#filter3714)"
d="m 48.539396,51.570209 8.832636,4.748176 c 4.097087,4.930516 13.270379,5.877301 19.214433,-0.31034 l 16.449381,-8.905407 -16.309189,8.078374 c -7.351304,3.398287 -14.788017,2.426427 -19.241976,0.405541 l -8.945285,-4.016344 z"
id="path2526"
sodipodi:nodetypes="ccccccc"
transform="matrix(0.88958423,-0.00696863,0,0.88958423,7.0366649,7.5268987)" />
<path
id="path1506"
d="m 21.534884,37.678074 34.124863,18.407772 c 5.772809,3.10706 9.004709,10.947536 8.899565,17.750275 l -0.291005,39.175029 c -0.105145,6.80274 -6.773179,6.84305 -12.545987,3.73599 L 20.568547,100.1994 C 14.795739,97.092352 10.232963,89.114423 10.338107,82.311683 l 0.586756,-37.96271 c 0.105144,-6.802738 4.837213,-9.777959 10.610021,-6.670899 z"
style="fill:url(#linearGradient2387);fill-opacity:1;fill-rule:nonzero;stroke:none"
sodipodi:nodetypes="ccccccccc" />
<path
sodipodi:type="inkscape:offset"
inkscape:radius="-1.1669018"
inkscape:original="M 64.125 0.28125 C 60.119734 0.34266221 56.06557 1.2507431 52.90625 2.96875 L 17.71875 22.09375 C 11.40011 25.529764 11.104972 30.908467 17.0625 34.15625 L 29.03125 40.6875 C 29.041477 40.689095 29.05227 40.685908 29.0625 40.6875 C 34.361479 41.512149 40.004261 41.96875 45.84375 41.96875 C 74.648901 41.96875 98.402523 31.131908 101.8125 17.1875 L 75.0625 2.625 C 72.083736 1.0011076 68.130266 0.21983779 64.125 0.28125 z "
style="fill:url(#linearGradient3301);fill-opacity:1;stroke:none;filter:url(#filter3518)"
id="path3299"
d="M 64.15625,1.4375 C 60.315227,1.4963939 56.411613,2.3997005 53.46875,4 l -35.1875,19.125 c -2.941524,1.599572 -4.254537,3.489516 -4.34375,5.125 -0.08921,1.635484 0.953539,3.384565 3.6875,4.875 l 11.78125,6.4375 c 5.194852,0.80039 10.715154,1.25 16.4375,1.25 14.256241,0 27.253781,-2.694155 37.03125,-7.0625 9.353803,-4.17906 15.530816,-9.912929 17.4375,-16.03125 L 74.5,3.65625 C 71.764111,2.1647623 67.998056,1.3785941 64.15625,1.4375 z"
transform="matrix(0.88958423,-0.00696863,0,0.88958423,7.0366649,7.5268987)" />
<g
id="g3441"
style="filter:url(#filter3482)"
transform="matrix(0.88958423,-0.00696863,0,0.88958423,7.0366649,7.5268987)">
<path
style="fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;filter:url(#filter3429)"
d="m 27.480576,23.293682 c 3.505712,-1.906853 9.264565,-1.844946 12.912228,0.138803 3.647663,1.983749 3.761942,5.115894 0.256231,7.022747 -3.505711,1.906852 -9.264564,1.844946 -12.912227,-0.138803 -3.647663,-1.98375 -3.761943,-5.115894 -0.256232,-7.022747 z"
id="path3327" />
<path
style="fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;filter:url(#filter3433)"
d="m 60.840861,23.804955 c 3.440747,-1.871518 9.092885,-1.810759 12.672954,0.13623 3.580069,1.946988 3.692229,5.021092 0.251482,6.89261 -3.440747,1.871516 -9.092884,1.810758 -12.672954,-0.13623 -3.580068,-1.946989 -3.692229,-5.021094 -0.251482,-6.89261 z"
id="path3329" />
<path
style="fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;filter:url(#filter3437)"
d="m 92.391788,24.467376 c 3.492768,-1.899812 9.230362,-1.838135 12.864552,0.13829 3.6342,1.976426 3.74806,5.097007 0.25529,6.99682 -3.49277,1.899812 -9.230362,1.838135 -12.864558,-0.13829 -3.634195,-1.976426 -3.748052,-5.097006 -0.255284,-6.99682 z"
id="path3331" />
</g>
<path
style="fill:url(#radialGradient1474);fill-opacity:1;fill-rule:nonzero;stroke:none"
d="m 31.482952,28.057089 c 3.118626,-1.720736 8.241611,-1.705796 11.486514,0.0335 3.244904,1.739293 3.346565,4.524804 0.227939,6.24554 -3.118625,1.720735 -8.24161,1.705796 -11.486513,-0.0335 -3.244904,-1.739293 -3.346565,-4.524802 -0.22794,-6.245539 z"
id="rect2291" />
<path
style="fill:url(#radialGradient1471);fill-opacity:1;fill-rule:nonzero;stroke:none"
d="m 61.159735,28.279434 c 3.060835,-1.68885 8.088887,-1.674188 11.27366,0.03288 3.184773,1.707062 3.284549,4.440954 0.223715,6.129804 -3.060834,1.688849 -8.088886,1.674187 -11.27366,-0.03287 -3.184772,-1.707063 -3.284549,-4.440957 -0.223715,-6.129805 z"
id="rect2293" />
<path
style="fill:url(#radialGradient1467);fill-opacity:1;fill-rule:nonzero;stroke:none"
d="m 89.226942,28.648846 c 3.107112,-1.714382 8.211185,-1.699499 11.444108,0.03337 3.23292,1.732872 3.33421,4.508098 0.2271,6.222482 -3.107116,1.714382 -8.211187,1.699499 -11.444111,-0.03337 -3.232922,-1.732872 -3.334208,-4.508097 -0.227097,-6.222482 z"
id="rect2295" />
<path
style="opacity:0.20081967;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none"
d="m 32.745512,27.50858 c -0.444882,0.160874 -0.863106,0.357774 -1.252933,0.572866 -1.973505,1.088903 -2.658724,2.61258 -2.072615,4.019316 -0.110112,-1.174485 0.658612,-2.360809 2.281271,-3.256129 3.118627,-1.720737 8.247246,-1.702176 11.49215,0.03712 1.133181,0.607393 1.886843,1.33499 2.250084,2.107659 -0.152505,-1.039536 -0.963043,-2.069142 -2.45874,-2.870847 -2.83929,-1.521881 -7.125046,-1.736102 -10.239217,-0.609982 z"
id="path1381" />
<path
id="path2263"
d="m 62.328392,27.787252 c -0.444881,0.160873 -0.863105,0.357773 -1.252933,0.572865 -1.973505,1.088904 -2.658724,2.61258 -2.072615,4.019316 -0.110113,-1.174485 0.658612,-2.360808 2.281271,-3.256128 3.118626,-1.720738 8.247247,-1.702177 11.49215,0.03712 1.133182,0.607393 1.886843,1.33499 2.250083,2.107659 -0.152505,-1.039536 -0.963042,-2.069141 -2.458739,-2.870847 -2.839291,-1.52188 -7.125046,-1.736101 -10.239217,-0.609981 z"
style="opacity:0.20081967;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none" />
<path
style="opacity:0.20081967;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none"
d="m 90.312362,28.060759 c -0.444879,0.160875 -0.863106,0.357775 -1.252933,0.572866 -1.973503,1.088903 -2.658722,2.61258 -2.072613,4.019316 -0.110112,-1.174485 0.658612,-2.360808 2.28127,-3.256128 3.118624,-1.720737 8.247248,-1.702176 11.492144,0.03712 1.13319,0.607392 1.88685,1.33499 2.25009,2.107659 -0.1525,-1.039538 -0.96304,-2.069141 -2.45874,-2.870847 -2.839292,-1.52188 -7.125047,-1.736101 -10.239218,-0.609982 z"
id="path2265" />
<path
sodipodi:nodetypes="ccccccccc"
id="path3674"
d="m 77.08844,56.915281 37.08864,-22.331703 c 5.59118,-3.097618 10.02975,-0.486059 9.95196,5.855507 l -0.50832,41.436025 c -0.0778,6.341565 -4.64162,13.940612 -10.23281,17.03823 l -37.088639,23.3317 c -5.591181,3.09763 -10.029752,0.48606 -9.951956,-5.8555 l 0.508319,-42.43603 c 0.0778,-6.341566 4.641626,-13.940614 10.232806,-17.038229 z"
style="fill:url(#linearGradient3678);fill-opacity:1;fill-rule:nonzero;stroke:none;filter:url(#filter3574)"
transform="matrix(-0.88958423,0.00696863,0,0.88958423,123.04786,8.3972843)" />
</g>
</svg>

After

Width:  |  Height:  |  Size: 38 KiB

View File

@ -174,13 +174,17 @@ endif()
qt5_wrap_ui(keepassx_SOURCES ${keepassx_FORMS})
add_library(zxcvbn STATIC zxcvbn/zxcvbn.cpp)
target_link_libraries(zxcvbn)
add_library(keepassx_core STATIC ${keepassx_SOURCES})
set_target_properties(keepassx_core PROPERTIES COMPILE_DEFINITIONS KEEPASSX_BUILDING_CORE)
target_link_libraries(keepassx_core Qt5::Core Qt5::Concurrent Qt5::Widgets Qt5::Network)
target_link_libraries(keepassx_core zxcvbn Qt5::Core Qt5::Concurrent Qt5::Widgets Qt5::Network)
add_executable(${PROGNAME} WIN32 MACOSX_BUNDLE ${keepassx_SOURCES_MAINEXE})
target_link_libraries(${PROGNAME}
keepassx_core
zxcvbn
${MHD_LIBRARIES}
Qt5::Core
Qt5::Concurrent

View File

@ -102,6 +102,7 @@ void Config::init(const QString& fileName)
m_defaults.insert("security/lockdatabaseidle", false);
m_defaults.insert("security/lockdatabaseidlesec", 10);
m_defaults.insert("security/lockdatabaseminimize", false);
m_defaults.insert("security/passwordsrepeat", false);
m_defaults.insert("security/passwordscleartext", false);
m_defaults.insert("security/autotypeask", true);
m_defaults.insert("GUI/Language", "system");

View File

@ -18,6 +18,7 @@
#include "PasswordGenerator.h"
#include "crypto/Random.h"
#include "zxcvbn/zxcvbn.h"
PasswordGenerator::PasswordGenerator()
: m_length(0)
@ -26,6 +27,11 @@ PasswordGenerator::PasswordGenerator()
{
}
double PasswordGenerator::calculateEntropy(QString password)
{
return ZxcvbnMatch(password.toLatin1(), 0, 0);
}
void PasswordGenerator::setLength(int length)
{
m_length = length;

View File

@ -46,6 +46,7 @@ public:
public:
PasswordGenerator();
double calculateEntropy(QString password);
void setLength(int length);
void setCharClasses(const CharClasses& classes);
void setFlags(const GeneratorFlags& flags);

View File

@ -69,24 +69,6 @@
</property>
</widget>
</item>
<item row="0" column="1">
<layout class="QHBoxLayout" name="horizontalLayout">
<item>
<widget class="PasswordEdit" name="editPassword">
<property name="echoMode">
<enum>QLineEdit::Password</enum>
</property>
</widget>
</item>
<item>
<widget class="QToolButton" name="buttonTogglePassword">
<property name="checkable">
<bool>true</bool>
</property>
</widget>
</item>
</layout>
</item>
<item row="1" column="1">
<layout class="QHBoxLayout" name="horizontalLayout_2">
<item>
@ -111,6 +93,24 @@
</item>
</layout>
</item>
<item row="0" column="1">
<layout class="QHBoxLayout" name="horizontalLayout">
<item>
<widget class="PasswordEdit" name="editPassword">
<property name="echoMode">
<enum>QLineEdit::Password</enum>
</property>
</widget>
</item>
<item>
<widget class="QToolButton" name="buttonTogglePassword">
<property name="checkable">
<bool>true</bool>
</property>
</widget>
</item>
</layout>
</item>
</layout>
</item>
<item>

View File

@ -39,6 +39,7 @@
#include "http/HttpSettings.h"
#include "http/OptionDialog.h"
#include "gui/SettingsWidget.h"
#include "gui/PasswordGeneratorWidget.h"
class HttpPlugin: public ISettingsPage
{
@ -168,6 +169,7 @@ MainWindow::MainWindow()
m_ui->actionGroupDelete->setIcon(filePath()->icon("actions", "group-delete", false));
m_ui->actionSettings->setIcon(filePath()->icon("actions", "configure"));
m_ui->actionPasswordGenerator->setIcon(filePath()->icon("actions", "password-generator", false));
m_ui->actionAbout->setIcon(filePath()->icon("actions", "help-about"));
@ -261,6 +263,8 @@ MainWindow::MainWindow()
SLOT(deleteGroup()));
connect(m_ui->actionSettings, SIGNAL(triggered()), SLOT(switchToSettings()));
connect(m_ui->actionPasswordGenerator, SIGNAL(toggled(bool)), SLOT(switchToPasswordGen(bool)));
connect(m_ui->passwordGeneratorWidget, SIGNAL(dialogTerminated()), SLOT(closePasswordGen()));
connect(m_ui->actionAbout, SIGNAL(triggered()), SLOT(showAboutDialog()));
@ -340,8 +344,9 @@ void MainWindow::minimizeWindow()
void MainWindow::setMenuActionState(DatabaseWidget::Mode mode)
{
bool inDatabaseTabWidget = (m_ui->stackedWidget->currentIndex() == 0);
bool inWelcomeWidget = (m_ui->stackedWidget->currentIndex() == 2);
int currentIndex = m_ui->stackedWidget->currentIndex();
bool inDatabaseTabWidget = (currentIndex == 0);
bool inWelcomeWidget = (currentIndex == 2);
if (inDatabaseTabWidget && m_ui->tabWidget->currentIndex() != -1) {
DatabaseWidget* dbWidget = m_ui->tabWidget->currentDatabaseWidget();
@ -453,6 +458,12 @@ void MainWindow::setMenuActionState(DatabaseWidget::Mode mode)
m_ui->actionRepairDatabase->setEnabled(inDatabaseTabWidgetOrWelcomeWidget);
m_ui->actionLockDatabases->setEnabled(m_ui->tabWidget->hasLockableDatabases());
if ((3 == currentIndex) != m_ui->actionPasswordGenerator->isChecked()) {
bool blocked = m_ui->actionPasswordGenerator->blockSignals(true);
m_ui->actionPasswordGenerator->toggle();
m_ui->actionPasswordGenerator->blockSignals(blocked);
}
}
void MainWindow::updateWindowTitle()
@ -501,6 +512,24 @@ void MainWindow::switchToSettings()
m_ui->stackedWidget->setCurrentIndex(1);
}
void MainWindow::switchToPasswordGen(bool enabled)
{
if (enabled == true) {
m_ui->passwordGeneratorWidget->loadSettings();
m_ui->passwordGeneratorWidget->regeneratePassword();
m_ui->passwordGeneratorWidget->setStandaloneMode(true);
m_ui->stackedWidget->setCurrentIndex(3);
} else {
m_ui->passwordGeneratorWidget->saveSettings();
switchToDatabases();
}
}
void MainWindow::closePasswordGen()
{
switchToPasswordGen(false);
}
void MainWindow::databaseStatusChanged(DatabaseWidget *)
{
updateTrayIcon();

View File

@ -54,6 +54,8 @@ private Q_SLOTS:
void showAboutDialog();
void switchToDatabases();
void switchToSettings();
void switchToPasswordGen(bool enabled);
void closePasswordGen();
void databaseStatusChanged(DatabaseWidget *dbWidget);
void databaseTabChanged(int tabIndex);
void openRecentDatabase(QAction* action);

View File

@ -87,6 +87,13 @@
</item>
</layout>
</widget>
<widget class="QWidget" name="pagePasswordGenerator">
<layout class="QVBoxLayout" name="verticalLayout_6">
<item>
<widget class="PasswordGeneratorWidget" name="passwordGeneratorWidget" native="true"/>
</item>
</layout>
</widget>
</widget>
</item>
</layout>
@ -171,6 +178,7 @@
<string>Tools</string>
</property>
<addaction name="actionLockDatabases"/>
<addaction name="actionPasswordGenerator"/>
<addaction name="actionSettings"/>
</widget>
<widget class="QMenu" name="menuView">
@ -205,6 +213,7 @@
<addaction name="actionEntryCopyUsername"/>
<addaction name="actionEntryCopyPassword"/>
<addaction name="separator"/>
<addaction name="actionPasswordGenerator"/>
<addaction name="actionLockDatabases"/>
<addaction name="separator"/>
</widget>
@ -372,6 +381,14 @@
<string>&amp;Settings</string>
</property>
</action>
<action name="actionPasswordGenerator">
<property name="checkable">
<bool>true</bool>
</property>
<property name="text">
<string>Password Generator</string>
</property>
</action>
<action name="actionEntryAutoType">
<property name="enabled">
<bool>false</bool>
@ -453,6 +470,12 @@
<header>gui/WelcomeWidget.h</header>
<container>1</container>
</customwidget>
<customwidget>
<class>PasswordGeneratorWidget</class>
<extends>QWidget</extends>
<header>gui/PasswordGeneratorWidget.h</header>
<container>1</container>
</customwidget>
</customwidgets>
<resources/>
<connections/>

View File

@ -17,6 +17,10 @@
#include "PasswordEdit.h"
#include "core/Config.h"
#include <QFontDatabase>
const QColor PasswordEdit::CorrectSoFarColor = QColor(255, 205, 15);
const QColor PasswordEdit::ErrorColor = QColor(255, 125, 125);
@ -24,6 +28,13 @@ PasswordEdit::PasswordEdit(QWidget* parent)
: QLineEdit(parent)
, m_basePasswordEdit(nullptr)
{
setEchoMode(QLineEdit::Password);
updateStylesheet();
// set font to system monospace font and increase letter spacing
QFont passwordFont = QFontDatabase::systemFont(QFontDatabase::FixedFont);
passwordFont.setLetterSpacing(QFont::PercentageSpacing, 110);
setFont(passwordFont);
}
void PasswordEdit::enableVerifyMode(PasswordEdit* basePasswordEdit)
@ -31,6 +42,8 @@ void PasswordEdit::enableVerifyMode(PasswordEdit* basePasswordEdit)
m_basePasswordEdit = basePasswordEdit;
updateStylesheet();
connect(m_basePasswordEdit, SIGNAL(textChanged(QString)), SLOT(autocompletePassword(QString)));
connect(m_basePasswordEdit, SIGNAL(textChanged(QString)), SLOT(updateStylesheet()));
connect(this, SIGNAL(textChanged(QString)), SLOT(updateStylesheet()));
@ -40,6 +53,21 @@ void PasswordEdit::enableVerifyMode(PasswordEdit* basePasswordEdit)
void PasswordEdit::setShowPassword(bool show)
{
setEchoMode(show ? QLineEdit::Normal : QLineEdit::Password);
// if I have a parent, I'm the child
if (m_basePasswordEdit){
if (config()->get("security/passwordsrepeat").toBool()) {
setEnabled(!show);
setReadOnly(show);
setText(m_basePasswordEdit->text());
}
else {
// This fix a bug when the QLineEdit is disabled while switching config
if (isEnabled() == false) {
setEnabled(true);
setReadOnly(false);
}
}
}
updateStylesheet();
Q_EMIT showPasswordChanged(show);
}
@ -53,15 +81,6 @@ void PasswordEdit::updateStylesheet()
{
QString stylesheet("QLineEdit { ");
if (echoMode() == QLineEdit::Normal) {
#ifdef Q_OS_MAC
// Qt on Mac OS doesn't seem to know the generic monospace family (tested with 4.8.6)
stylesheet.append("font-family: monospace,Menlo,Monaco; ");
#else
stylesheet.append("font-family: monospace,Courier New; ");
#endif
}
if (m_basePasswordEdit && !passwordsEqual()) {
stylesheet.append("background: %1; ");
@ -76,3 +95,10 @@ void PasswordEdit::updateStylesheet()
stylesheet.append("}");
setStyleSheet(stylesheet);
}
void PasswordEdit::autocompletePassword(QString password)
{
if (config()->get("security/passwordsrepeat").toBool() && echoMode() == QLineEdit::Normal) {
setText(password);
}
}

View File

@ -39,6 +39,7 @@ Q_SIGNALS:
private Q_SLOTS:
void updateStylesheet();
void autocompletePassword(QString password);
private:
bool passwordsEqual() const;

View File

@ -34,18 +34,23 @@ PasswordGeneratorWidget::PasswordGeneratorWidget(QWidget* parent)
m_ui->togglePasswordButton->setIcon(filePath()->onOffIcon("actions", "password-show"));
connect(m_ui->editNewPassword->lineEdit(), SIGNAL(textChanged(QString)), SLOT(updateApplyEnabled(QString)));
connect(m_ui->togglePasswordButton, SIGNAL(toggled(bool)), m_ui->editNewPassword, SLOT(setEcho(bool)));
connect(m_ui->buttonApply, SIGNAL(clicked()), SLOT(emitNewPassword()));
connect(m_ui->buttonApply, SIGNAL(clicked()), SLOT(saveSettings()));
connect(m_ui->editNewPassword, SIGNAL(textChanged(QString)), SLOT(updateApplyEnabled(QString)));
connect(m_ui->editNewPassword, SIGNAL(textChanged(QString)), SLOT(updatePasswordStrength(QString)));
connect(m_ui->togglePasswordButton, SIGNAL(toggled(bool)), SLOT(togglePasswordShown(bool)));
connect(m_ui->buttonApply, SIGNAL(clicked()), SLOT(applyPassword()));
connect(m_ui->buttonGenerate, SIGNAL(clicked()), SLOT(generatePassword()));
connect(m_ui->sliderLength, SIGNAL(valueChanged(int)), SLOT(sliderMoved()));
connect(m_ui->spinBoxLength, SIGNAL(valueChanged(int)), SLOT(spinBoxChanged()));
connect(m_ui->optionButtons, SIGNAL(buttonClicked(int)), SLOT(updateGenerator()));
m_ui->editNewPassword->setGenerator(m_generator.data());
// set font size of password quality and entropy labels dynamically to 80% of the default font size
QFont defaultFont;
defaultFont.setPointSize(static_cast<int>(defaultFont.pointSize() * 0.8f));
m_ui->entropyLabel->setFont(defaultFont);
m_ui->strengthLabel->setFont(defaultFont);
loadSettings();
reset();
}
@ -82,17 +87,28 @@ void PasswordGeneratorWidget::saveSettings()
void PasswordGeneratorWidget::reset()
{
m_ui->editNewPassword->lineEdit()->setText("");
m_ui->togglePasswordButton->setChecked(config()->get("security/passwordscleartext").toBool());
m_ui->editNewPassword->setText("");
setStandaloneMode(false);
togglePasswordShown(config()->get("security/passwordscleartext").toBool());
updateGenerator();
}
void PasswordGeneratorWidget::setStandaloneMode(bool standalone)
{
if (standalone) {
m_ui->buttonApply->setText(tr("Close"));
togglePasswordShown(true);
} else {
m_ui->buttonApply->setText(tr("Apply"));
}
}
void PasswordGeneratorWidget::regeneratePassword()
{
if (m_generator->isValid()) {
QString password = m_generator->generatePassword();
m_ui->editNewPassword->setEditText(password);
m_ui->editNewPassword->setText(password);
updatePasswordStrength(password);
}
}
@ -101,9 +117,30 @@ void PasswordGeneratorWidget::updateApplyEnabled(const QString& password)
m_ui->buttonApply->setEnabled(!password.isEmpty());
}
void PasswordGeneratorWidget::emitNewPassword()
void PasswordGeneratorWidget::updatePasswordStrength(const QString& password)
{
Q_EMIT newPassword(m_ui->editNewPassword->lineEdit()->text());
double entropy = m_generator->calculateEntropy(password);
m_ui->entropyLabel->setText(tr("Entropy: %1 bit").arg(QString::number(entropy, 'f', 2)));
if (entropy > m_ui->entropyProgressBar->maximum()) {
entropy = m_ui->entropyProgressBar->maximum();
}
m_ui->entropyProgressBar->setValue(entropy);
colorStrengthIndicator(entropy);
}
void PasswordGeneratorWidget::generatePassword()
{
QString password = m_generator->generatePassword();
m_ui->editNewPassword->setText(password);
}
void PasswordGeneratorWidget::applyPassword()
{
saveSettings();
Q_EMIT appliedPassword(m_ui->editNewPassword->text());
Q_EMIT dialogTerminated();
}
void PasswordGeneratorWidget::sliderMoved()
@ -133,6 +170,41 @@ void PasswordGeneratorWidget::spinBoxChanged()
updateGenerator();
}
void PasswordGeneratorWidget::togglePasswordShown(bool showing)
{
m_ui->editNewPassword->setShowPassword(showing);
bool blockSignals = m_ui->togglePasswordButton->blockSignals(true);
m_ui->togglePasswordButton->setChecked(showing);
m_ui->togglePasswordButton->blockSignals(blockSignals);
}
void PasswordGeneratorWidget::colorStrengthIndicator(double entropy)
{
// Take the existing stylesheet and convert the text and background color to arguments
QString style = m_ui->entropyProgressBar->styleSheet();
QRegularExpression re("(QProgressBar::chunk\\s*\\{.*?background-color:)[^;]+;",
QRegularExpression::CaseInsensitiveOption |
QRegularExpression::DotMatchesEverythingOption);
style.replace(re, "\\1 %1;");
// Set the color and background based on entropy
// colors are taking from the KDE breeze palette
// <https://community.kde.org/KDE_Visual_Design_Group/HIG/Color>
if (entropy < 35) {
m_ui->entropyProgressBar->setStyleSheet(style.arg("#c0392b"));
m_ui->strengthLabel->setText(tr("Password Quality: %1").arg(tr("Poor")));
} else if (entropy >= 35 && entropy < 55) {
m_ui->entropyProgressBar->setStyleSheet(style.arg("#f39c1f"));
m_ui->strengthLabel->setText(tr("Password Quality: %1").arg(tr("Weak")));
} else if (entropy >= 55 && entropy < 100) {
m_ui->entropyProgressBar->setStyleSheet(style.arg("#11d116"));
m_ui->strengthLabel->setText(tr("Password Quality: %1").arg(tr("Good")));
} else {
m_ui->entropyProgressBar->setStyleSheet(style.arg("#27ae60"));
m_ui->strengthLabel->setText(tr("Password Quality: %1").arg(tr("Excellent")));
}
}
PasswordGenerator::CharClasses PasswordGeneratorWidget::charClasses()
{
PasswordGenerator::CharClasses classes;

View File

@ -20,6 +20,7 @@
#include <QWidget>
#include <QComboBox>
#include <QLabel>
#include "core/PasswordGenerator.h"
@ -37,19 +38,25 @@ public:
explicit PasswordGeneratorWidget(QWidget* parent = nullptr);
~PasswordGeneratorWidget();
void loadSettings();
void saveSettings();
void reset();
void setStandaloneMode(bool standalone);
void regeneratePassword();
Q_SIGNALS:
void newPassword(const QString& password);
void appliedPassword(const QString& password);
void dialogTerminated();
private Q_SLOTS:
void applyPassword();
void generatePassword();
void updateApplyEnabled(const QString& password);
void updatePasswordStrength(const QString& password);
void togglePasswordShown(bool hidden);
void emitNewPassword();
void saveSettings();
void sliderMoved();
void spinBoxChanged();
void colorStrengthIndicator(double entropy);
void updateGenerator();

View File

@ -6,60 +6,197 @@
<rect>
<x>0</x>
<y>0</y>
<width>434</width>
<height>250</height>
<width>500</width>
<height>278</height>
</rect>
</property>
<property name="sizePolicy">
<sizepolicy hsizetype="Preferred" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="windowTitle">
<string/>
</property>
<layout class="QVBoxLayout" name="verticalLayout_2">
<item>
<layout class="QGridLayout" name="gridLayout">
<layout class="QGridLayout" name="passwordFieldLayout">
<property name="bottomMargin">
<number>10</number>
</property>
<property name="verticalSpacing">
<number>0</number>
</property>
<item row="1" column="1">
<widget class="QProgressBar" name="entropyProgressBar">
<property name="minimumSize">
<size>
<width>50</width>
<height>5</height>
</size>
</property>
<property name="maximumSize">
<size>
<width>16777215</width>
<height>5</height>
</size>
</property>
<property name="styleSheet">
<string notr="true">QProgressBar {
border: none;
height: 2px;
font-size: 1px;
background-color: transparent;
padding: 0 1px;
}
QProgressBar::chunk {
background-color: #c0392b;
border-radius: 2px;
}</string>
</property>
<property name="maximum">
<number>200</number>
</property>
<property name="value">
<number>100</number>
</property>
<property name="textVisible">
<bool>false</bool>
</property>
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="invertedAppearance">
<bool>false</bool>
</property>
<property name="textDirection">
<enum>QProgressBar::TopToBottom</enum>
</property>
<property name="format">
<string>%p%</string>
</property>
</widget>
</item>
<item row="0" column="0">
<widget class="QLabel" name="labelNewPassword">
<property name="text">
<string>Password:</string>
</property>
<property name="buddy">
<cstring>editNewPassword</cstring>
</property>
</widget>
</item>
<item row="0" column="1">
<layout class="QHBoxLayout" name="horizontalLayout_2">
<property name="sizeConstraint">
<enum>QLayout::SetNoConstraint</enum>
</property>
<item row="2" column="1">
<layout class="QHBoxLayout" name="passwordStrengthTextLayout">
<item>
<widget class="PasswordComboBox" name="editNewPassword">
<property name="editable">
<bool>true</bool>
<widget class="QLabel" name="strengthLabel">
<property name="minimumSize">
<size>
<width>70</width>
<height>0</height>
</size>
</property>
<property name="maximumSize">
<size>
<width>16777215</width>
<height>30</height>
</size>
</property>
<property name="font">
<font>
<pointsize>8</pointsize>
</font>
</property>
<property name="text">
<string>strength</string>
</property>
<property name="textFormat">
<enum>Qt::PlainText</enum>
</property>
<property name="alignment">
<set>Qt::AlignLeading|Qt::AlignLeft|Qt::AlignTop</set>
</property>
<property name="margin">
<number>3</number>
</property>
</widget>
</item>
<item>
<widget class="QToolButton" name="togglePasswordButton">
<property name="checkable">
<bool>true</bool>
<spacer name="horizontalSpacer_2">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>40</width>
<height>20</height>
</size>
</property>
</spacer>
</item>
<item>
<widget class="QLabel" name="entropyLabel">
<property name="minimumSize">
<size>
<width>70</width>
<height>0</height>
</size>
</property>
<property name="font">
<font>
<pointsize>8</pointsize>
</font>
</property>
<property name="text">
<string>entropy</string>
</property>
<property name="alignment">
<set>Qt::AlignRight|Qt::AlignTop|Qt::AlignTrailing</set>
</property>
<property name="margin">
<number>3</number>
</property>
</widget>
</item>
</layout>
</item>
<item row="1" column="0">
<widget class="QLabel" name="labelLength">
<property name="text">
<string>Length:</string>
<item row="0" column="1">
<widget class="PasswordEdit" name="editNewPassword">
<property name="maxLength">
<number>999</number>
</property>
</widget>
</item>
<item row="1" column="1">
<layout class="QHBoxLayout" name="horizontalLayout_4">
<item row="3" column="0">
<widget class="QLabel" name="labelLength">
<property name="text">
<string>&amp;Length:</string>
</property>
<property name="buddy">
<cstring>spinBoxLength</cstring>
</property>
</widget>
</item>
<item row="3" column="1" colspan="2">
<layout class="QHBoxLayout" name="passwordLengthSliderLayout">
<property name="spacing">
<number>15</number>
</property>
<property name="topMargin">
<number>6</number>
</property>
<item>
<widget class="QSlider" name="sliderLength">
<property name="minimum">
<number>1</number>
</property>
<property name="maximum">
<number>64</number>
<number>128</number>
</property>
<property name="sliderPosition">
<number>20</number>
</property>
<property name="orientation">
<enum>Qt::Horizontal</enum>
@ -72,7 +209,7 @@
</property>
</widget>
</item>
<item>
<item alignment="Qt::AlignRight">
<widget class="QSpinBox" name="spinBoxLength">
<property name="minimum">
<number>1</number>
@ -80,30 +217,139 @@
<property name="maximum">
<number>999</number>
</property>
<property name="value">
<number>20</number>
</property>
</widget>
</item>
</layout>
</item>
<item row="0" column="2">
<widget class="QToolButton" name="togglePasswordButton">
<property name="checkable">
<bool>true</bool>
</property>
</widget>
</item>
</layout>
</item>
<item>
<widget class="QGroupBox" name="groupBox">
<property name="title">
<string>Character Types</string>
</property>
<layout class="QVBoxLayout" name="verticalLayout">
<item>
<layout class="QHBoxLayout" name="horizontalLayout_5">
<layout class="QHBoxLayout" name="optionsLayout">
<item>
<widget class="QGroupBox" name="groupBox">
<property name="title">
<string>Character Types</string>
</property>
<layout class="QVBoxLayout" name="verticalLayout">
<item>
<widget class="QToolButton" name="checkBoxUpper">
<property name="toolTip">
<string>Upper Case Letters</string>
</property>
<layout class="QHBoxLayout" name="alphabetLayout">
<item>
<widget class="QToolButton" name="checkBoxUpper">
<property name="minimumSize">
<size>
<width>0</width>
<height>26</height>
</size>
</property>
<property name="focusPolicy">
<enum>Qt::StrongFocus</enum>
</property>
<property name="toolTip">
<string>Upper Case Letters</string>
</property>
<property name="text">
<string notr="true">A-Z</string>
</property>
<property name="checkable">
<bool>true</bool>
</property>
<attribute name="buttonGroup">
<string notr="true">optionButtons</string>
</attribute>
</widget>
</item>
<item>
<widget class="QToolButton" name="checkBoxLower">
<property name="minimumSize">
<size>
<width>0</width>
<height>26</height>
</size>
</property>
<property name="focusPolicy">
<enum>Qt::StrongFocus</enum>
</property>
<property name="toolTip">
<string>Lower Case Letters</string>
</property>
<property name="text">
<string notr="true">a-z</string>
</property>
<property name="checkable">
<bool>true</bool>
</property>
<attribute name="buttonGroup">
<string notr="true">optionButtons</string>
</attribute>
</widget>
</item>
<item>
<widget class="QToolButton" name="checkBoxNumbers">
<property name="focusPolicy">
<enum>Qt::StrongFocus</enum>
</property>
<property name="toolTip">
<string>Numbers</string>
</property>
<property name="text">
<string notr="true">0-9</string>
</property>
<property name="checkable">
<bool>true</bool>
</property>
<attribute name="buttonGroup">
<string notr="true">optionButtons</string>
</attribute>
</widget>
</item>
<item>
<widget class="QToolButton" name="checkBoxSpecialChars">
<property name="focusPolicy">
<enum>Qt::StrongFocus</enum>
</property>
<property name="toolTip">
<string>Special Characters</string>
</property>
<property name="text">
<string notr="true">/*_&amp; ...</string>
</property>
<property name="checkable">
<bool>true</bool>
</property>
<attribute name="buttonGroup">
<string notr="true">optionButtons</string>
</attribute>
</widget>
</item>
<item>
<spacer name="horizontalSpacer">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>40</width>
<height>20</height>
</size>
</property>
</spacer>
</item>
</layout>
</item>
<item>
<widget class="QCheckBox" name="checkBoxExcludeAlike">
<property name="text">
<string notr="true">A-Z</string>
</property>
<property name="checkable">
<bool>true</bool>
<string>Exclude look-alike characters</string>
</property>
<attribute name="buttonGroup">
<string notr="true">optionButtons</string>
@ -111,115 +357,38 @@
</widget>
</item>
<item>
<widget class="QToolButton" name="checkBoxLower">
<property name="toolTip">
<string>Lower Case Letters</string>
</property>
<widget class="QCheckBox" name="checkBoxEnsureEvery">
<property name="text">
<string notr="true">a-z</string>
</property>
<property name="checkable">
<bool>true</bool>
<string>Pick characters from every group</string>
</property>
<attribute name="buttonGroup">
<string notr="true">optionButtons</string>
</attribute>
</widget>
</item>
<item>
<widget class="QToolButton" name="checkBoxNumbers">
<property name="toolTip">
<string>Numbers</string>
</property>
<property name="text">
<string notr="true">0-9</string>
</property>
<property name="checkable">
<bool>true</bool>
</property>
<attribute name="buttonGroup">
<string notr="true">optionButtons</string>
</attribute>
</widget>
</item>
<item>
<widget class="QToolButton" name="checkBoxSpecialChars">
<property name="toolTip">
<string>Special Characters</string>
</property>
<property name="text">
<string notr="true">/*_&amp; ...</string>
</property>
<property name="checkable">
<bool>true</bool>
</property>
<attribute name="buttonGroup">
<string notr="true">optionButtons</string>
</attribute>
</widget>
</item>
<item>
<spacer name="horizontalSpacer">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>40</width>
<height>20</height>
</size>
</property>
</spacer>
</item>
</layout>
</item>
<item>
<widget class="QCheckBox" name="checkBoxExcludeAlike">
<property name="text">
<string>Exclude look-alike characters</string>
</property>
<attribute name="buttonGroup">
<string notr="true">optionButtons</string>
</attribute>
</widget>
</item>
<item>
<widget class="QCheckBox" name="checkBoxEnsureEvery">
<property name="text">
<string>Ensure that the password contains characters from every group</string>
</property>
<attribute name="buttonGroup">
<string notr="true">optionButtons</string>
</attribute>
</widget>
</item>
</layout>
</widget>
</item>
<item>
<layout class="QHBoxLayout" name="horizontalLayout_3">
<item>
<spacer name="horizontalSpacer_2">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>40</width>
<height>20</height>
</size>
</property>
</spacer>
</widget>
</item>
<item>
<widget class="QPushButton" name="buttonApply">
<property name="enabled">
<bool>false</bool>
</property>
<property name="text">
<string>Accept</string>
</property>
</widget>
<layout class="QVBoxLayout" name="globalButtonsLayout">
<item>
<widget class="QPushButton" name="buttonGenerate">
<property name="text">
<string>Generate</string>
</property>
</widget>
</item>
<item>
<widget class="QPushButton" name="buttonApply">
<property name="enabled">
<bool>false</bool>
</property>
<property name="text">
<string>Accept</string>
</property>
</widget>
</item>
</layout>
</item>
</layout>
</item>
@ -227,9 +396,9 @@
</widget>
<customwidgets>
<customwidget>
<class>PasswordComboBox</class>
<extends>QComboBox</extends>
<header location="global">gui/PasswordComboBox.h</header>
<class>PasswordEdit</class>
<extends>QLineEdit</extends>
<header>gui/PasswordEdit.h</header>
</customwidget>
</customwidgets>
<tabstops>
@ -243,6 +412,7 @@
<tabstop>checkBoxSpecialChars</tabstop>
<tabstop>checkBoxExcludeAlike</tabstop>
<tabstop>checkBoxEnsureEvery</tabstop>
<tabstop>buttonGenerate</tabstop>
<tabstop>buttonApply</tabstop>
</tabstops>
<resources/>

View File

@ -137,6 +137,7 @@ void SettingsWidget::loadSettings()
m_secUi->lockDatabaseMinimizeCheckBox->setChecked(config()->get("security/lockdatabaseminimize").toBool());
m_secUi->passwordCleartextCheckBox->setChecked(config()->get("security/passwordscleartext").toBool());
m_secUi->passwordRepeatCheckBox->setChecked(config()->get("security/passwordsrepeat").toBool());
m_secUi->autoTypeAskCheckBox->setChecked(config()->get("security/autotypeask").toBool());
@ -181,6 +182,7 @@ void SettingsWidget::saveSettings()
config()->set("security/lockdatabaseminimize", m_secUi->lockDatabaseMinimizeCheckBox->isChecked());
config()->set("security/passwordscleartext", m_secUi->passwordCleartextCheckBox->isChecked());
config()->set("security/passwordsrepeat", m_secUi->passwordRepeatCheckBox->isChecked());
config()->set("security/autotypeask", m_secUi->autoTypeAskCheckBox->isChecked());

View File

@ -72,6 +72,13 @@
</widget>
</item>
<item row="4" column="0">
<widget class="QCheckBox" name="passwordRepeatCheckBox">
<property name="text">
<string>Don't require password repeat when it is visible</string>
</property>
</widget>
</item>
<item row="5" column="0">
<widget class="QCheckBox" name="autoTypeAskCheckBox">
<property name="text">
<string>Always ask before performing auto-type</string>

View File

@ -93,7 +93,7 @@ void EditEntryWidget::setupMain()
connect(m_mainUi->tooglePasswordGeneratorButton, SIGNAL(toggled(bool)), SLOT(togglePasswordGeneratorButton(bool)));
connect(m_mainUi->expireCheck, SIGNAL(toggled(bool)), m_mainUi->expireDatePicker, SLOT(setEnabled(bool)));
m_mainUi->passwordRepeatEdit->enableVerifyMode(m_mainUi->passwordEdit);
connect(m_mainUi->passwordGenerator, SIGNAL(newPassword(QString)), SLOT(setGeneratedPassword(QString)));
connect(m_mainUi->passwordGenerator, SIGNAL(appliedPassword(QString)), SLOT(setGeneratedPassword(QString)));
m_mainUi->expirePresets->setMenu(createPresetsMenu());
connect(m_mainUi->expirePresets->menu(), SIGNAL(triggered(QAction*)), this, SLOT(useExpiryPreset(QAction*)));

View File

@ -7,7 +7,7 @@
<x>0</x>
<y>0</y>
<width>372</width>
<height>301</height>
<height>364</height>
</rect>
</property>
<layout class="QFormLayout" name="formLayout">
@ -78,7 +78,7 @@
<item>
<widget class="QToolButton" name="tooglePasswordGeneratorButton">
<property name="text">
<string>Gen.</string>
<string>Generate</string>
</property>
<property name="checkable">
<bool>true</bool>

24872
src/zxcvbn/dict-src.h Normal file

File diff suppressed because it is too large Load Diff

1772
src/zxcvbn/zxcvbn.cpp Normal file

File diff suppressed because it is too large Load Diff

139
src/zxcvbn/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

View File

@ -21,6 +21,7 @@
#include <QApplication>
#include <QDialogButtonBox>
#include <QLineEdit>
#include <QLabel>
#include <QMimeData>
#include <QPushButton>
#include <QSpinBox>
@ -228,6 +229,80 @@ void TestGui::testAddEntry()
QTRY_COMPARE(entryView->model()->rowCount(), 4);
}
void TestGui::testEntryEntropy()
{
QToolBar* toolBar = m_mainWindow->findChild<QToolBar*>("toolBar");
// Find the new entry action
QAction* entryNewAction = m_mainWindow->findChild<QAction*>("actionEntryNew");
QVERIFY(entryNewAction->isEnabled());
// Find the button associated with the new entry action
QWidget* entryNewWidget = toolBar->widgetForAction(entryNewAction);
QVERIFY(entryNewWidget->isVisible());
QVERIFY(entryNewWidget->isEnabled());
// Click the new entry button and check that we enter edit mode
QTest::mouseClick(entryNewWidget, Qt::LeftButton);
QCOMPARE(m_dbWidget->currentMode(), DatabaseWidget::EditMode);
// Add entry "test" and confirm added
EditEntryWidget* editEntryWidget = m_dbWidget->findChild<EditEntryWidget*>("editEntryWidget");
QLineEdit* titleEdit = editEntryWidget->findChild<QLineEdit*>("titleEdit");
QTest::keyClicks(titleEdit, "test");
// Open the password generator
QToolButton* generatorButton = editEntryWidget->findChild<QToolButton*>("tooglePasswordGeneratorButton");
QTest::mouseClick(generatorButton, Qt::LeftButton);
// Type in some password
QLineEdit* editNewPassword = editEntryWidget->findChild<QLineEdit*>("editNewPassword");
QLabel* entropyLabel = editEntryWidget->findChild<QLabel*>("entropyLabel");
QLabel* strengthLabel = editEntryWidget->findChild<QLabel*>("strengthLabel");
editNewPassword->setText("");
QTest::keyClicks(editNewPassword, "hello");
QCOMPARE(entropyLabel->text(), QString("Entropy: 6.38 bit"));
QCOMPARE(strengthLabel->text(), QString("Password Quality: Poor"));
editNewPassword->setText("");
QTest::keyClicks(editNewPassword, "helloworld");
QCOMPARE(entropyLabel->text(), QString("Entropy: 13.10 bit"));
QCOMPARE(strengthLabel->text(), QString("Password Quality: Poor"));
editNewPassword->setText("");
QTest::keyClicks(editNewPassword, "password1");
QCOMPARE(entropyLabel->text(), QString("Entropy: 4.00 bit"));
QCOMPARE(strengthLabel->text(), QString("Password Quality: Poor"));
editNewPassword->setText("");
QTest::keyClicks(editNewPassword, "D0g..................");
QCOMPARE(entropyLabel->text(), QString("Entropy: 19.02 bit"));
QCOMPARE(strengthLabel->text(), QString("Password Quality: Poor"));
editNewPassword->setText("");
QTest::keyClicks(editNewPassword, "Tr0ub4dour&3");
QCOMPARE(entropyLabel->text(), QString("Entropy: 30.87 bit"));
QCOMPARE(strengthLabel->text(), QString("Password Quality: Poor"));
editNewPassword->setText("");
QTest::keyClicks(editNewPassword, "correcthorsebatterystaple");
QCOMPARE(entropyLabel->text(), QString("Entropy: 47.98 bit"));
QCOMPARE(strengthLabel->text(), QString("Password Quality: Weak"));
editNewPassword->setText("");
QTest::keyClicks(editNewPassword, "YQC3kbXbjC652dTDH");
QCOMPARE(entropyLabel->text(), QString("Entropy: 96.07 bit"));
QCOMPARE(strengthLabel->text(), QString("Password Quality: Good"));
editNewPassword->setText("");
QTest::keyClicks(editNewPassword, "Bs5ZFfthWzR8DGFEjaCM6bGqhmCT4km");
QCOMPARE(entropyLabel->text(), QString("Entropy: 174.59 bit"));
QCOMPARE(strengthLabel->text(), QString("Password Quality: Excellent"));
// We are done
}
void TestGui::testSearch()
{
// Add canned entries for consistent testing

View File

@ -42,6 +42,7 @@ private Q_SLOTS:
void testTabs();
void testEditEntry();
void testAddEntry();
void testEntryEntropy();
void testSearch();
void testDeleteEntry();
void testCloneEntry();

View File

@ -24,3 +24,7 @@ target_link_libraries(kdbx-extract
Qt5::Widgets
${GCRYPT_LIBRARIES}
${ZLIB_LIBRARIES})
add_executable(entropy-meter entropy-meter.cpp)
target_link_libraries(entropy-meter zxcvbn)

116
utils/entropy-meter.cpp Normal file
View File

@ -0,0 +1,116 @@
/*
Part of this code come from zxcvbn-c example.
Copyright (c) 2015, Tony Evans
Copyright (c) 2016, KeePassXC Team
See zxcvbn/zxcvbn.cpp for complete COPYRIGHT Notice
*/
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include "zxcvbn/zxcvbn.h"
/* For pre-compiled headers under windows */
#ifdef _WIN32
#include "stdafx.h"
#endif
static void calculate(const char *pwd, int advanced)
{
double e;
int len = strlen(pwd);
if (advanced == 0){
e = ZxcvbnMatch(pwd, 0, 0);
printf("Pass '%s' \tLength %d\tEntropy %.3f\tLog10 %.3f\n", pwd, len, e, e * 0.301029996);
} else {
int ChkLen;
ZxcMatch_t *info, *p;
double m = 0.0;
e = ZxcvbnMatch(pwd, 0, &info);
for(p = info; p; p = p->Next) {
m += p->Entrpy;
}
m = e - m;
printf("Pass '%s' \tLength %d\tEntropy %.3f\tLog10 %.3f\n Multi-word extra bits %.1f\n", pwd, len, e, e * 0.301029996, m);
p = info;
ChkLen = 0;
while(p) {
int n;
switch(static_cast<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);
if (ChkLen != len)
printf("*** Password length (%d) != sum of length of parts (%d) ***\n", len, ChkLen);
}
}
int main(int argc, char **argv)
{
printf("KeePassXC Entropy Meter, based on zxcvbn-c.\nEnter your password below or pass it as argv\n");
printf(" Usage: entropy-meter [-a] [pwd1 pwd2 ...]\n> ");
int i, advanced;
if ((argc > 1) && (argv[1][0] == '-') && (!strcmp(argv[1], "-a")))
{
advanced = 1;
}
i = 2;
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 < static_cast<int>(sizeof line - 1); ++i)
{
if (line[i] < ' ')
{
line[i] = 0;
break;
}
}
if (line[0])
calculate(line,advanced);
printf("> ");
}
}
else
{
/* Do the test passwords on the command line */
for(; i < argc; ++i)
{
calculate(argv[i],advanced);
}
}
return 0;
}