├── .gitattributes ├── .gitignore ├── ChangeLog.md ├── Forms ├── PasswordUnit.dfm └── PasswordUnit.pas ├── KeePass.dpr ├── KeePass.dproj ├── KeePass.res ├── KeePassLib ├── KeePassLib.BCrypt.pas ├── KeePassLib.Wincrypt.pas ├── KeePassLib.pas └── System.Security.Cryptography.pas ├── LICENSE.md ├── MainUnit.dfm ├── MainUnit.pas ├── README.md └── TODO.md /.gitattributes: -------------------------------------------------------------------------------- 1 | # Auto detect text files and perform LF normalization 2 | * text=auto 3 | 4 | # Custom for Visual Studio 5 | *.cs diff=csharp 6 | 7 | # Standard to msysgit 8 | *.doc diff=astextplain 9 | *.DOC diff=astextplain 10 | *.docx diff=astextplain 11 | *.DOCX diff=astextplain 12 | *.dot diff=astextplain 13 | *.DOT diff=astextplain 14 | *.pdf diff=astextplain 15 | *.PDF diff=astextplain 16 | *.rtf diff=astextplain 17 | *.RTF diff=astextplain 18 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Uncomment these types if you want even more clean repository. But be careful. 2 | # It can make harm to an existing project source. Read explanations below. 3 | # 4 | # Resource files are binaries containing manifest, project icon and version info. 5 | # They can not be viewed as text or compared by diff-tools. Consider replacing them with .rc files. 6 | #*.res 7 | # 8 | # Type library file (binary). In old Delphi versions it should be stored. 9 | # Since Delphi 2009 it is produced from .ridl file and can safely be ignored. 10 | #*.tlb 11 | # 12 | # Diagram Portfolio file. Used by the diagram editor up to Delphi 7. 13 | # Uncomment this if you are not using diagrams or use newer Delphi version. 14 | #*.ddp 15 | # 16 | # Visual LiveBindings file. Added in Delphi XE2. 17 | # Uncomment this if you are not using LiveBindings Designer. 18 | #*.vlb 19 | # 20 | # Deployment Manager configuration file for your project. Added in Delphi XE2. 21 | # Uncomment this if it is not mobile development and you do not use remote debug feature. 22 | #*.deployproj 23 | # 24 | # C++ object files produced when C/C++ Output file generation is configured. 25 | # Uncomment this if you are not using external objects (zlib library for example). 26 | #*.obj 27 | # 28 | 29 | # Delphi compiler-generated binaries (safe to delete) 30 | *.exe 31 | *.dll 32 | *.bpl 33 | *.bpi 34 | *.dcp 35 | *.so 36 | *.apk 37 | *.drc 38 | *.map 39 | *.dres 40 | *.rsm 41 | *.tds 42 | *.dcu 43 | *.lib 44 | *.a 45 | *.o 46 | *.ocx 47 | 48 | # Delphi autogenerated files (duplicated info) 49 | *.cfg 50 | *.hpp 51 | *Resource.rc 52 | 53 | # Delphi local files (user-specific info) 54 | *.local 55 | *.identcache 56 | *.projdata 57 | *.tvsconfig 58 | *.dsk 59 | 60 | # Delphi history and backups 61 | __history/ 62 | __recovery/ 63 | *.~* 64 | 65 | # Castalia statistics file (since XE7 Castalia is distributed with Delphi) 66 | *.stat 67 | 68 | # ========================= 69 | # Operating System Files 70 | # ========================= 71 | 72 | # OSX 73 | # ========================= 74 | 75 | .DS_Store 76 | .AppleDouble 77 | .LSOverride 78 | 79 | # Thumbnails 80 | ._* 81 | 82 | # Files that might appear in the root of a volume 83 | .DocumentRevisions-V100 84 | .fseventsd 85 | .Spotlight-V100 86 | .TemporaryItems 87 | .Trashes 88 | .VolumeIcon.icns 89 | 90 | # Directories potentially created on remote AFP share 91 | .AppleDB 92 | .AppleDesktop 93 | Network Trash Folder 94 | Temporary Items 95 | .apdisk 96 | 97 | # Windows 98 | # ========================= 99 | 100 | # Windows image file caches 101 | Thumbs.db 102 | ehthumbs.db 103 | 104 | # Folder config file 105 | Desktop.ini 106 | 107 | # Recycle Bin used on file shares 108 | $RECYCLE.BIN/ 109 | 110 | # Windows Installer files 111 | *.cab 112 | *.msi 113 | *.msm 114 | *.msp 115 | 116 | # Windows shortcuts 117 | *.lnk 118 | -------------------------------------------------------------------------------- /ChangeLog.md: -------------------------------------------------------------------------------- 1 | # ChangeLog 2 | 3 | ## v0.1 4 | 5 | * Opens Kdbx files and reads meta information (Parsing of and XML tag is not implemented yet) 6 | -------------------------------------------------------------------------------- /Forms/PasswordUnit.dfm: -------------------------------------------------------------------------------- 1 | object PasswordForm: TPasswordForm 2 | Left = 0 3 | Top = 0 4 | BorderStyle = bsDialog 5 | Caption = 'Enter password' 6 | ClientHeight = 221 7 | ClientWidth = 385 8 | Color = clBtnFace 9 | Font.Charset = DEFAULT_CHARSET 10 | Font.Color = clWindowText 11 | Font.Height = -11 12 | Font.Name = 'Tahoma' 13 | Font.Style = [] 14 | OldCreateOrder = False 15 | Position = poMainFormCenter 16 | PixelsPerInch = 96 17 | TextHeight = 13 18 | object lblPassword: TLabel 19 | Left = 8 20 | Top = 8 21 | Width = 79 22 | Height = 13 23 | Caption = 'Enter password:' 24 | end 25 | object edPassword: TMaskEdit 26 | Left = 8 27 | Top = 27 28 | Width = 369 29 | Height = 21 30 | PasswordChar = '*' 31 | TabOrder = 0 32 | Text = '' 33 | end 34 | object btnOK: TButton 35 | Left = 216 36 | Top = 188 37 | Width = 75 38 | Height = 25 39 | Caption = '&OK' 40 | Default = True 41 | ModalResult = 1 42 | TabOrder = 1 43 | end 44 | object btnCancel: TButton 45 | Left = 302 46 | Top = 188 47 | Width = 75 48 | Height = 25 49 | Cancel = True 50 | Caption = '&Cancel' 51 | ModalResult = 2 52 | TabOrder = 2 53 | end 54 | end 55 | -------------------------------------------------------------------------------- /Forms/PasswordUnit.pas: -------------------------------------------------------------------------------- 1 | { This file is part of KeePass4D. 2 | 3 | KeePass4D is free software: you can redistribute it and/or modify 4 | it under the terms of the GNU General Public License as published by 5 | the Free Software Foundation, either version 3 of the License, or 6 | (at your option) any later version. 7 | 8 | KeePass4D is distributed in the hope that it will be useful, 9 | but WITHOUT ANY WARRANTY; without even the implied warranty of 10 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 11 | GNU General Public License for more details. 12 | 13 | You should have received a copy of the GNU General Public License 14 | along with KeePass4D. If not, see . } 15 | 16 | unit PasswordUnit; 17 | 18 | interface 19 | 20 | uses 21 | Winapi.Windows, Winapi.Messages, System.SysUtils, System.Variants, System.Classes, Vcl.Graphics, 22 | Vcl.Controls, Vcl.Forms, Vcl.Dialogs, Vcl.StdCtrls, Vcl.Mask; 23 | 24 | resourcestring 25 | SPasswordIsEmpty = 'Password cannot be empty!'; 26 | 27 | type 28 | TPasswordForm = class(TForm) 29 | lblPassword: TLabel; 30 | edPassword: TMaskEdit; 31 | btnOK: TButton; 32 | btnCancel: TButton; 33 | private 34 | function GetPassword: string; 35 | { Private declarations } 36 | public 37 | { Public declarations } 38 | property Password: string read GetPassword; 39 | end; 40 | 41 | var 42 | PasswordForm: TPasswordForm; 43 | 44 | implementation 45 | 46 | {$R *.dfm} 47 | 48 | { TPasswordForm } 49 | 50 | function TPasswordForm.GetPassword: string; 51 | begin 52 | Result := edPassword.Text; 53 | end; 54 | 55 | end. 56 | -------------------------------------------------------------------------------- /KeePass.dpr: -------------------------------------------------------------------------------- 1 | program KeePass; 2 | 3 | uses 4 | Vcl.Forms, 5 | MainUnit in 'MainUnit.pas' {MainForm}, 6 | KeePassLib in 'KeePassLib\KeePassLib.pas', 7 | KeePassLib.Wincrypt in 'KeePassLib\KeePassLib.Wincrypt.pas', 8 | System.Security.Cryptography in 'KeePassLib\System.Security.Cryptography.pas', 9 | KeePassLib.BCrypt in 'KeePassLib\KeePassLib.BCrypt.pas', 10 | PasswordUnit in 'Forms\PasswordUnit.pas' {PasswordForm}; 11 | 12 | {$R *.res} 13 | 14 | begin 15 | Application.Initialize; 16 | Application.MainFormOnTaskbar := True; 17 | Application.CreateForm(TMainForm, MainForm); 18 | Application.Run; 19 | end. 20 | -------------------------------------------------------------------------------- /KeePass.dproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | {769A615B-6A44-4F28-BD43-CB1692D63D74} 4 | 17.2 5 | VCL 6 | KeePass.dpr 7 | True 8 | Debug 9 | Win32 10 | 1 11 | Application 12 | 13 | 14 | true 15 | 16 | 17 | true 18 | Base 19 | true 20 | 21 | 22 | true 23 | Base 24 | true 25 | 26 | 27 | true 28 | Base 29 | true 30 | 31 | 32 | true 33 | Cfg_1 34 | true 35 | true 36 | 37 | 38 | true 39 | Base 40 | true 41 | 42 | 43 | $(BDS)\bin\delphi_PROJECTICON.ico 44 | System;Xml;Data;Datasnap;Web;Soap;Vcl;Vcl.Imaging;Vcl.Touch;Vcl.Samples;Vcl.Shell;$(DCC_Namespace) 45 | KeePass 46 | .\$(Platform)\$(Config) 47 | .\$(Platform)\$(Config) 48 | 49 | 50 | CompanyName=;FileDescription=;FileVersion=1.0.0.0;InternalName=;LegalCopyright=;LegalTrademarks=;OriginalFilename=;ProductName=;ProductVersion=1.0.0.0;Comments= 51 | 1033 52 | true 53 | $(BDS)\bin\default_app.manifest 54 | FireDACTDataDriver;FireDACSqliteDriver;FireDACDSDriver;DBXSqliteDriver;FireDACPgDriver;fmx;IndySystem;TeeDB;tethering;vclib;DBXInterBaseDriver;DataSnapClient;DataSnapCommon;DataSnapServer;DataSnapProviderClient;DBXSybaseASEDriver;DbxCommonDriver;vclimg;DUnitXRuntime;dbxcds;DatasnapConnectorsFreePascal;appanalytics;vcldb;vcldsnap;fmxFireDAC;DBXDb2Driver;DBXOracleDriver;CustomIPTransport;vclribbon;dsnap;IndyIPServer;fmxase;vcl;IndyCore;DBXMSSQLDriver;CloudService;IndyIPCommon;FmxTeeUI;FireDACIBDriver;DataSnapFireDAC;FireDACDBXDriver;soapserver;inetdbxpress;dsnapxml;FireDACInfxDriver;FireDACDb2Driver;adortl;FireDACASADriver;bindcompfmx;FireDACODBCDriver;RESTBackendComponents;emsclientfiredac;rtl;dbrtl;DbxClientDriver;FireDACCommon;bindcomp;inetdb;Tee;DBXOdbcDriver;ibmonitor;vclFireDAC;xmlrtl;DataSnapNativeClient;ibxpress;svnui;IndyProtocols;DBXMySQLDriver;FireDACCommonDriver;bindcompdbx;bindengine;vclactnband;FMXTee;soaprtl;TeeUI;bindcompvcl;vclie;FireDACADSDriver;vcltouch;emsclient;VCLRESTComponents;FireDAC;DBXInformixDriver;FireDACMSSQLDriver;Intraweb;VclSmp;DataSnapConnectors;DataSnapServerMidas;DBXFirebirdDriver;dsnapcon;inet;fmxobj;FireDACMySQLDriver;soapmidas;vclx;svn;DBXSybaseASADriver;FireDACOracleDriver;fmxdae;RESTComponents;VirtualTreesR;dbexpress;FireDACMSAccDriver;DataSnapIndy10ServerTransport;IndyIPClient;$(DCC_UsePackage) 55 | Winapi;System.Win;Data.Win;Datasnap.Win;Web.Win;Soap.Win;Xml.Win;Bde;$(DCC_Namespace) 56 | 57 | 58 | FireDACTDataDriver;FireDACSqliteDriver;FireDACDSDriver;DBXSqliteDriver;FireDACPgDriver;fmx;IndySystem;TeeDB;tethering;vclib;DBXInterBaseDriver;DataSnapClient;DataSnapCommon;DataSnapServer;DataSnapProviderClient;DBXSybaseASEDriver;DbxCommonDriver;vclimg;dbxcds;DatasnapConnectorsFreePascal;appanalytics;vcldb;vcldsnap;fmxFireDAC;DBXDb2Driver;DBXOracleDriver;CustomIPTransport;vclribbon;dsnap;IndyIPServer;fmxase;vcl;IndyCore;DBXMSSQLDriver;CloudService;IndyIPCommon;FmxTeeUI;FireDACIBDriver;DataSnapFireDAC;FireDACDBXDriver;soapserver;inetdbxpress;dsnapxml;FireDACInfxDriver;FireDACDb2Driver;adortl;FireDACASADriver;bindcompfmx;FireDACODBCDriver;RESTBackendComponents;emsclientfiredac;rtl;dbrtl;DbxClientDriver;FireDACCommon;bindcomp;inetdb;Tee;DBXOdbcDriver;ibmonitor;vclFireDAC;xmlrtl;DataSnapNativeClient;ibxpress;IndyProtocols;DBXMySQLDriver;FireDACCommonDriver;bindcompdbx;bindengine;vclactnband;FMXTee;soaprtl;TeeUI;bindcompvcl;vclie;FireDACADSDriver;vcltouch;emsclient;VCLRESTComponents;FireDAC;DBXInformixDriver;FireDACMSSQLDriver;Intraweb;VclSmp;DataSnapConnectors;DataSnapServerMidas;DBXFirebirdDriver;dsnapcon;inet;fmxobj;FireDACMySQLDriver;soapmidas;vclx;DBXSybaseASADriver;FireDACOracleDriver;fmxdae;RESTComponents;VirtualTreesR;dbexpress;FireDACMSAccDriver;DataSnapIndy10ServerTransport;IndyIPClient;$(DCC_UsePackage) 59 | 60 | 61 | DEBUG;$(DCC_Define) 62 | true 63 | false 64 | true 65 | true 66 | true 67 | 68 | 69 | 1033 70 | true 71 | false 72 | 73 | 74 | false 75 | RELEASE;$(DCC_Define) 76 | 0 77 | 0 78 | 79 | 80 | 81 | MainSource 82 | 83 | 84 |
MainForm
85 | dfm 86 |
87 | 88 | 89 | 90 | 91 | 92 |
PasswordForm
93 | dfm 94 |
95 | 96 | Cfg_2 97 | Base 98 | 99 | 100 | Base 101 | 102 | 103 | Cfg_1 104 | Base 105 | 106 |
107 | 108 | Delphi.Personality.12 109 | Application 110 | 111 | 112 | 113 | (untitled) 114 | Microsoft Office 2000 Sample Automation Server Wrapper Components 115 | Microsoft Office XP Sample Automation Server Wrapper Components 116 | 117 | 118 | KeePass.dpr 119 | 120 | 121 | 122 | 123 | 124 | KeePass.exe 125 | true 126 | 127 | 128 | 129 | 130 | 1 131 | .dylib 132 | 133 | 134 | 0 135 | .bpl 136 | 137 | 138 | Contents\MacOS 139 | 1 140 | .dylib 141 | 142 | 143 | 1 144 | .dylib 145 | 146 | 147 | 1 148 | .dylib 149 | 150 | 151 | 152 | 153 | 1 154 | .dylib 155 | 156 | 157 | 0 158 | .dll;.bpl 159 | 160 | 161 | Contents\MacOS 162 | 1 163 | .dylib 164 | 165 | 166 | 1 167 | .dylib 168 | 169 | 170 | 1 171 | .dylib 172 | 173 | 174 | 175 | 176 | 1 177 | 178 | 179 | 1 180 | 181 | 182 | 1 183 | 184 | 185 | 186 | 187 | Contents 188 | 1 189 | 190 | 191 | 192 | 193 | ..\$(PROJECTNAME).app.dSYM\Contents\Resources\DWARF 194 | 1 195 | 196 | 197 | ..\$(PROJECTNAME).app.dSYM\Contents\Resources\DWARF 198 | 1 199 | 200 | 201 | 202 | 203 | res\drawable-normal 204 | 1 205 | 206 | 207 | 208 | 209 | library\lib\x86 210 | 1 211 | 212 | 213 | 214 | 215 | 1 216 | 217 | 218 | 1 219 | 220 | 221 | 1 222 | 223 | 224 | 225 | 226 | ../ 227 | 1 228 | 229 | 230 | 231 | 232 | library\lib\armeabi-v7a 233 | 1 234 | 235 | 236 | 237 | 238 | 1 239 | 240 | 241 | 1 242 | 243 | 244 | 1 245 | 246 | 247 | 248 | 249 | res\drawable-xlarge 250 | 1 251 | 252 | 253 | 254 | 255 | res\drawable-xhdpi 256 | 1 257 | 258 | 259 | 260 | 261 | 1 262 | 263 | 264 | 1 265 | 266 | 267 | 1 268 | 269 | 270 | 271 | 272 | res\drawable-xxhdpi 273 | 1 274 | 275 | 276 | 277 | 278 | library\lib\mips 279 | 1 280 | 281 | 282 | 283 | 284 | res\drawable 285 | 1 286 | 287 | 288 | 289 | 290 | Contents\MacOS 291 | 1 292 | 293 | 294 | 1 295 | 296 | 297 | 0 298 | 299 | 300 | 301 | 302 | Contents\MacOS 303 | 1 304 | .framework 305 | 306 | 307 | 0 308 | 309 | 310 | 311 | 312 | res\drawable-small 313 | 1 314 | 315 | 316 | 317 | 318 | ../ 319 | 1 320 | 321 | 322 | ../ 323 | 1 324 | 325 | 326 | 327 | 328 | Contents\MacOS 329 | 1 330 | 331 | 332 | 1 333 | 334 | 335 | Contents\MacOS 336 | 0 337 | 338 | 339 | 340 | 341 | classes 342 | 1 343 | 344 | 345 | 346 | 347 | 1 348 | 349 | 350 | 1 351 | 352 | 353 | 1 354 | 355 | 356 | 357 | 358 | 1 359 | 360 | 361 | 1 362 | 363 | 364 | 1 365 | 366 | 367 | 368 | 369 | res\drawable 370 | 1 371 | 372 | 373 | 374 | 375 | Contents\Resources 376 | 1 377 | 378 | 379 | 380 | 381 | 1 382 | 383 | 384 | 1 385 | 386 | 387 | 388 | 389 | 1 390 | 391 | 392 | 1 393 | 394 | 395 | 1 396 | 397 | 398 | 399 | 400 | library\lib\armeabi-v7a 401 | 1 402 | 403 | 404 | 1 405 | 406 | 407 | 0 408 | 409 | 410 | Contents\MacOS 411 | 1 412 | 413 | 414 | 1 415 | 416 | 417 | 1 418 | 419 | 420 | 421 | 422 | library\lib\armeabi 423 | 1 424 | 425 | 426 | 427 | 428 | res\drawable-large 429 | 1 430 | 431 | 432 | 433 | 434 | 0 435 | 436 | 437 | 0 438 | 439 | 440 | 0 441 | 442 | 443 | Contents\MacOS 444 | 0 445 | 446 | 447 | 0 448 | 449 | 450 | 0 451 | 452 | 453 | 454 | 455 | 1 456 | 457 | 458 | 1 459 | 460 | 461 | 1 462 | 463 | 464 | 465 | 466 | res\drawable-ldpi 467 | 1 468 | 469 | 470 | 471 | 472 | res\values 473 | 1 474 | 475 | 476 | 477 | 478 | 1 479 | 480 | 481 | 1 482 | 483 | 484 | 1 485 | 486 | 487 | 488 | 489 | res\drawable-mdpi 490 | 1 491 | 492 | 493 | 494 | 495 | res\drawable-hdpi 496 | 1 497 | 498 | 499 | 500 | 501 | 1 502 | 503 | 504 | 505 | 506 | 507 | 508 | 509 | 510 | 511 | 512 | 513 | True 514 | False 515 | 516 | 517 | 12 518 | 519 | 520 | 521 | 522 |
523 | -------------------------------------------------------------------------------- /KeePass.res: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/evpobr/KeePass4D/39e5e12867436f9e9b718c50edbaae8c6da99e78/KeePass.res -------------------------------------------------------------------------------- /KeePassLib/KeePassLib.BCrypt.pas: -------------------------------------------------------------------------------- 1 | { This file is part of KeePass4D. 2 | 3 | KeePass4D is free software: you can redistribute it and/or modify 4 | it under the terms of the GNU General Public License as published by 5 | the Free Software Foundation, either version 3 of the License, or 6 | (at your option) any later version. 7 | 8 | KeePass4D is distributed in the hope that it will be useful, 9 | but WITHOUT ANY WARRANTY; without even the implied warranty of 10 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 11 | GNU General Public License for more details. 12 | 13 | You should have received a copy of the GNU General Public License 14 | along with KeePass4D. If not, see . } 15 | 16 | unit KeePassLib.BCrypt; 17 | 18 | interface 19 | 20 | uses 21 | Winapi.Windows; 22 | 23 | const 24 | MS_PRIMITIVE_PROVIDER: PWideChar = 'Microsoft Primitive Provider'; 25 | 26 | BCRYPT_SHA256_ALGORITHM: PWideChar = 'SHA256'; 27 | 28 | BCRYPT_OBJECT_LENGTH: PWideChar = 'ObjectLength'; 29 | BCRYPT_ALGORITHM_NAME: PWideChar = 'AlgorithmName'; 30 | BCRYPT_PROVIDER_HANDLE: PWideChar = 'ProviderHandle'; 31 | BCRYPT_CHAINING_MODE: PWideChar = 'ChainingMode'; 32 | BCRYPT_BLOCK_LENGTH: PWideChar = 'BlockLength'; 33 | BCRYPT_KEY_LENGTH: PWideChar = 'KeyLength'; 34 | BCRYPT_KEY_OBJECT_LENGTH: PWideChar = 'KeyObjectLength'; 35 | BCRYPT_KEY_STRENGTH: PWideChar = 'KeyStrength'; 36 | BCRYPT_KEY_LENGTHS: PWideChar = 'KeyLengths'; 37 | BCRYPT_BLOCK_SIZE_LIST: PWideChar = 'BlockSizeList'; 38 | BCRYPT_EFFECTIVE_KEY_LENGTH: PWideChar = 'EffectiveKeyLength'; 39 | BCRYPT_HASH_LENGTH: PWideChar = 'HashDigestLength'; 40 | BCRYPT_HASH_OID_LIST: PWideChar = 'HashOIDList'; 41 | BCRYPT_PADDING_SCHEMES: PWideChar = 'PaddingSchemes'; 42 | BCRYPT_SIGNATURE_LENGTH: PWideChar = 'SignatureLength'; 43 | BCRYPT_HASH_BLOCK_LENGTH: PWideChar = 'HashBlockLength'; 44 | BCRYPT_AUTH_TAG_LENGTH: PWideChar = 'AuthTagLength'; 45 | BCRYPT_PRIMITIVE_TYPE: PWideChar = 'PrimitiveType'; 46 | BCRYPT_IS_KEYED_HASH: PWideChar = 'IsKeyedHash'; 47 | 48 | type 49 | BCRYPT_ALG_HANDLE = PVOID; 50 | BCRYPT_HANDLE = PVOID; 51 | TBCryptAlgHandle = BCRYPT_ALG_HANDLE; 52 | TBCryptHandle = BCRYPT_HANDLE; 53 | 54 | function BCryptOpenAlgorithmProvider(out hAlgorithm: TBCryptAlgHandle; 55 | const pszAlgId: PWideChar; const pszImplementation: PWideChar; dwFlags: DWORD): LONG; stdcall; 56 | function BCryptCloseAlgorithmProvider(var hAlgorithm: TBCryptAlgHandle; 57 | dwFlags: ULONG): LONG; stdcall; 58 | function BCryptGetProperty(hObject: TBCryptHandle; 59 | const pszProperty: PWideChar; pbOutput: PUCHAR; cbOutput: ULONG; 60 | out cbResult: ULONG; dwFlags: ULONG): LONG; stdcall; 61 | 62 | implementation 63 | 64 | const 65 | bcryptdll = 'Bcrypt.dll'; 66 | 67 | 68 | function BCryptOpenAlgorithmProvider; external bcryptdll; 69 | function BCryptCloseAlgorithmProvider; external bcryptdll; 70 | function BCryptGetProperty; external bcryptdll; 71 | 72 | end. 73 | -------------------------------------------------------------------------------- /KeePassLib/KeePassLib.Wincrypt.pas: -------------------------------------------------------------------------------- 1 | { This file is part of KeePass4D. 2 | 3 | KeePass4D is free software: you can redistribute it and/or modify 4 | it under the terms of the GNU General Public License as published by 5 | the Free Software Foundation, either version 3 of the License, or 6 | (at your option) any later version. 7 | 8 | KeePass4D is distributed in the hope that it will be useful, 9 | but WITHOUT ANY WARRANTY; without even the implied warranty of 10 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 11 | GNU General Public License for more details. 12 | 13 | You should have received a copy of the GNU General Public License 14 | along with KeePass4D. If not, see . } 15 | 16 | unit KeePassLib.Wincrypt; 17 | 18 | {$ALIGN ON} 19 | {$MINENUMSIZE 4} 20 | {$WEAKPACKAGEUNIT} 21 | 22 | interface 23 | 24 | uses 25 | Winapi.Windows; 26 | 27 | // 28 | // Algorithm IDs and Flags 29 | // 30 | 31 | // ALG_ID crackers 32 | function GetAlgClass(x: DWORD): DWORD; inline; 33 | function GetAlgType(x: DWORD): DWORD; inline; 34 | function GetAlgSid(x: DWORD): DWORD; inline; 35 | 36 | const 37 | // Algorithm classes 38 | // certenrolld_begin -- ALG_CLASS_* 39 | ALG_CLASS_ANY = 0; 40 | ALG_CLASS_SIGNATURE = 1 shl 13; 41 | ALG_CLASS_MSG_ENCRYPT = 2 shl 13; 42 | ALG_CLASS_DATA_ENCRYPT = 3 shl 13; 43 | ALG_CLASS_HASH = 4 shl 13; 44 | ALG_CLASS_KEY_EXCHANGE = 5 shl 13; 45 | ALG_CLASS_ALL = 7 shl 13; 46 | // certenrolld_end 47 | 48 | // Algorithm types 49 | ALG_TYPE_ANY = 0; 50 | ALG_TYPE_DSS = 1 shl 9; 51 | ALG_TYPE_RSA = 2 shl 9; 52 | ALG_TYPE_BLOCK = 3 shl 9; 53 | ALG_TYPE_STREAM = 4 shl 9; 54 | ALG_TYPE_DH = 5 shl 9; 55 | ALG_TYPE_SECURECHANNEL = 6 shl 9; 56 | 57 | // Generic sub-ids 58 | ALG_SID_ANY = 0; 59 | 60 | // Some RSA sub-ids 61 | ALG_SID_RSA_ANY = 0; 62 | ALG_SID_RSA_PKCS = 1; 63 | ALG_SID_RSA_MSATWORK = 2; 64 | ALG_SID_RSA_ENTRUST = 3; 65 | ALG_SID_RSA_PGP = 4; 66 | 67 | // Some DSS sub-ids 68 | // 69 | ALG_SID_DSS_ANY = 0; 70 | ALG_SID_DSS_PKCS = 1; 71 | ALG_SID_DSS_DMS = 2; 72 | // #if (NTDDI_VERSION >= NTDDI_VISTA) 73 | ALG_SID_ECDSA = 3; 74 | // #endif //(NTDDI_VERSION >= NTDDI_VISTA) 75 | 76 | // Block cipher sub ids 77 | // DES sub_ids 78 | ALG_SID_DES = 1; 79 | ALG_SID_3DES = 3; 80 | ALG_SID_DESX = 4; 81 | ALG_SID_IDEA = 5; 82 | ALG_SID_CAST = 6; 83 | ALG_SID_SAFERSK64 = 7; 84 | ALG_SID_SAFERSK128 = 8; 85 | ALG_SID_3DES_112 = 9; 86 | ALG_SID_CYLINK_MEK = 12; 87 | ALG_SID_RC5 = 13; 88 | // #if (NTDDI_VERSION >= NTDDI_WINXP) 89 | ALG_SID_AES_128 = 14; 90 | ALG_SID_AES_192 = 15; 91 | ALG_SID_AES_256 = 16; 92 | ALG_SID_AES = 17; 93 | //(NTDDI_VERSION >= NTDDI_WINXP) 94 | 95 | 96 | // Fortezza sub-ids 97 | ALG_SID_SKIPJACK = 10; 98 | ALG_SID_TEK = 11; 99 | 100 | // KP_MODE 101 | CRYPT_MODE_CBCI = 6; // ANSI CBC Interleaved 102 | CRYPT_MODE_CFBP = 7; // ANSI CFB Pipelined 103 | CRYPT_MODE_OFBP = 8; // ANSI OFB Pipelined 104 | CRYPT_MODE_CBCOFM = 9; // ANSI CBC + OF Masking 105 | CRYPT_MODE_CBCOFMI = 10; // ANSI CBC + OFM Interleaved 106 | 107 | 108 | // RC2 sub-ids 109 | ALG_SID_RC2 = 2; 110 | 111 | // Stream cipher sub-ids 112 | ALG_SID_RC4 = 1; 113 | ALG_SID_SEAL = 2; 114 | 115 | // Diffie-Hellman sub-ids 116 | ALG_SID_DH_SANDF = 1; 117 | ALG_SID_DH_EPHEM = 2; 118 | ALG_SID_AGREED_KEY_ANY = 3; 119 | ALG_SID_KEA = 4; 120 | // #if (NTDDI_VERSION >= NTDDI_VISTA) 121 | ALG_SID_ECDH = 5; 122 | //(NTDDI_VERSION >= NTDDI_VISTA) 123 | 124 | // Hash sub ids 125 | ALG_SID_MD2 = 1; 126 | ALG_SID_MD4 = 2; 127 | ALG_SID_MD5 = 3; 128 | ALG_SID_SHA = 4; 129 | ALG_SID_SHA1 = 4; 130 | ALG_SID_MAC = 5; 131 | ALG_SID_RIPEMD = 6; 132 | ALG_SID_RIPEMD160 = 7; 133 | ALG_SID_SSL3SHAMD5 = 8; 134 | ALG_SID_HMAC = 9; 135 | ALG_SID_TLS1PRF = 10; 136 | // #if (NTDDI_VERSION >= NTDDI_WINXP) 137 | ALG_SID_HASH_REPLACE_OWF = 11; 138 | // #endif //(NTDDI_VERSION >= NTDDI_WINXP) 139 | // #if (NTDDI_VERSION > NTDDI_WINXPSP2) 140 | ALG_SID_SHA_256 = 12; 141 | ALG_SID_SHA_384 = 13; 142 | ALG_SID_SHA_512 = 14; 143 | //#endif //(NTDDI_VERSION > NTDDI_WINXPSP2) 144 | 145 | 146 | // secure channel sub ids 147 | ALG_SID_SSL3_MASTER = 1; 148 | ALG_SID_SCHANNEL_MASTER_HASH = 2; 149 | ALG_SID_SCHANNEL_MAC_KEY = 3; 150 | ALG_SID_PCT1_MASTER = 4; 151 | ALG_SID_SSL2_MASTER = 5; 152 | ALG_SID_TLS1_MASTER = 6; 153 | ALG_SID_SCHANNEL_ENC_KEY = 7; 154 | 155 | // #if (NTDDI_VERSION >= NTDDI_VISTA) 156 | // misc ECC sub ids 157 | ALG_SID_ECMQV = 1; 158 | // #endif //(NTDDI_VERSION >= NTDDI_VISTA) 159 | 160 | // Our silly example sub-id 161 | ALG_SID_EXAMPLE = 80; 162 | 163 | type 164 | // certenrolls_begin -- PROV_ENUMALGS_EX 165 | ALG_ID = UINT; 166 | TAlgID = ALG_ID; 167 | // certenrolls_end 168 | 169 | const 170 | // algorithm identifier definitions 171 | CALG_MD2 = ALG_CLASS_HASH or ALG_TYPE_ANY or ALG_SID_MD2; 172 | CALG_MD4 = ALG_CLASS_HASH or ALG_TYPE_ANY or ALG_SID_MD4; 173 | CALG_MD5 = ALG_CLASS_HASH or ALG_TYPE_ANY or ALG_SID_MD5; 174 | CALG_SHA = ALG_CLASS_HASH or ALG_TYPE_ANY or ALG_SID_SHA; 175 | CALG_SHA1 = ALG_CLASS_HASH or ALG_TYPE_ANY or ALG_SID_SHA1; 176 | CALG_MAC = ALG_CLASS_HASH or ALG_TYPE_ANY or ALG_SID_MAC; // Deprecated. Don't use. 177 | CALG_RSA_SIGN = ALG_CLASS_SIGNATURE or ALG_TYPE_RSA or ALG_SID_RSA_ANY; 178 | CALG_DSS_SIGN = ALG_CLASS_SIGNATURE or ALG_TYPE_DSS or ALG_SID_DSS_ANY; 179 | // #if (NTDDI_VERSION >= NTDDI_WINXP) 180 | CALG_NO_SIGN = ALG_CLASS_SIGNATURE or ALG_TYPE_ANY or ALG_SID_ANY; 181 | // #endif //(NTDDI_VERSION >= NTDDI_WINXP) 182 | CALG_RSA_KEYX = ALG_CLASS_KEY_EXCHANGE or ALG_TYPE_RSA or ALG_SID_RSA_ANY; 183 | CALG_DES = ALG_CLASS_DATA_ENCRYPT or ALG_TYPE_BLOCK or ALG_SID_DES; 184 | CALG_3DES_112 = ALG_CLASS_DATA_ENCRYPT or ALG_TYPE_BLOCK or ALG_SID_3DES_112; 185 | CALG_3DES = ALG_CLASS_DATA_ENCRYPT or ALG_TYPE_BLOCK or ALG_SID_3DES; 186 | CALG_DESX = ALG_CLASS_DATA_ENCRYPT or ALG_TYPE_BLOCK or ALG_SID_DESX; 187 | CALG_RC2 = ALG_CLASS_DATA_ENCRYPT or ALG_TYPE_BLOCK or ALG_SID_RC2; 188 | CALG_RC4 = ALG_CLASS_DATA_ENCRYPT or ALG_TYPE_STREAM or ALG_SID_RC4; 189 | CALG_SEAL = ALG_CLASS_DATA_ENCRYPT or ALG_TYPE_STREAM or ALG_SID_SEAL; 190 | CALG_DH_SF = ALG_CLASS_KEY_EXCHANGE or ALG_TYPE_DH or ALG_SID_DH_SANDF; 191 | CALG_DH_EPHEM = ALG_CLASS_KEY_EXCHANGE or ALG_TYPE_DH or ALG_SID_DH_EPHEM; 192 | CALG_AGREEDKEY_ANY = ALG_CLASS_KEY_EXCHANGE or ALG_TYPE_DH or ALG_SID_AGREED_KEY_ANY; 193 | CALG_KEA_KEYX = ALG_CLASS_KEY_EXCHANGE or ALG_TYPE_DH or ALG_SID_KEA; 194 | CALG_HUGHES_MD5 = ALG_CLASS_KEY_EXCHANGE or ALG_TYPE_ANY or ALG_SID_MD5; 195 | CALG_SKIPJACK = ALG_CLASS_DATA_ENCRYPT or ALG_TYPE_BLOCK or ALG_SID_SKIPJACK; 196 | CALG_TEK = ALG_CLASS_DATA_ENCRYPT or ALG_TYPE_BLOCK or ALG_SID_TEK; 197 | CALG_CYLINK_MEK = ALG_CLASS_DATA_ENCRYPT or ALG_TYPE_BLOCK or ALG_SID_CYLINK_MEK; // Deprecated. Do not use 198 | CALG_SSL3_SHAMD5 = ALG_CLASS_HASH or ALG_TYPE_ANY or ALG_SID_SSL3SHAMD5; 199 | CALG_SSL3_MASTER = ALG_CLASS_MSG_ENCRYPT or ALG_TYPE_SECURECHANNEL or ALG_SID_SSL3_MASTER; 200 | CALG_SCHANNEL_MASTER_HASH = ALG_CLASS_MSG_ENCRYPT or ALG_TYPE_SECURECHANNEL or ALG_SID_SCHANNEL_MASTER_HASH; 201 | CALG_SCHANNEL_MAC_KEY = ALG_CLASS_MSG_ENCRYPT or ALG_TYPE_SECURECHANNEL or ALG_SID_SCHANNEL_MAC_KEY; 202 | CALG_SCHANNEL_ENC_KEY = ALG_CLASS_MSG_ENCRYPT or ALG_TYPE_SECURECHANNEL or ALG_SID_SCHANNEL_ENC_KEY; 203 | CALG_PCT1_MASTER = ALG_CLASS_MSG_ENCRYPT or ALG_TYPE_SECURECHANNEL or ALG_SID_PCT1_MASTER; 204 | CALG_SSL2_MASTER = ALG_CLASS_MSG_ENCRYPT or ALG_TYPE_SECURECHANNEL or ALG_SID_SSL2_MASTER; 205 | CALG_TLS1_MASTER = ALG_CLASS_MSG_ENCRYPT or ALG_TYPE_SECURECHANNEL or ALG_SID_TLS1_MASTER; 206 | CALG_RC5 = ALG_CLASS_DATA_ENCRYPT or ALG_TYPE_BLOCK or ALG_SID_RC5; 207 | CALG_HMAC = ALG_CLASS_HASH or ALG_TYPE_ANY or ALG_SID_HMAC; 208 | CALG_TLS1PRF = ALG_CLASS_HASH or ALG_TYPE_ANY or ALG_SID_TLS1PRF; 209 | // #if (NTDDI_VERSION >= NTDDI_WINXP) 210 | CALG_HASH_REPLACE_OWF = ALG_CLASS_HASH or ALG_TYPE_ANY or ALG_SID_HASH_REPLACE_OWF; 211 | CALG_AES_128 = ALG_CLASS_DATA_ENCRYPT or ALG_TYPE_BLOCK or ALG_SID_AES_128; 212 | CALG_AES_192 = ALG_CLASS_DATA_ENCRYPT or ALG_TYPE_BLOCK or ALG_SID_AES_192; 213 | CALG_AES_256 = ALG_CLASS_DATA_ENCRYPT or ALG_TYPE_BLOCK or ALG_SID_AES_256; 214 | CALG_AES = ALG_CLASS_DATA_ENCRYPT or ALG_TYPE_BLOCK or ALG_SID_AES; 215 | // #endif //(NTDDI_VERSION >= NTDDI_WINXP) 216 | // #if (NTDDI_VERSION > NTDDI_WINXPSP2) 217 | CALG_SHA_256 = ALG_CLASS_HASH or ALG_TYPE_ANY or ALG_SID_SHA_256; 218 | CALG_SHA_384 = ALG_CLASS_HASH or ALG_TYPE_ANY or ALG_SID_SHA_384; 219 | CALG_SHA_512 = ALG_CLASS_HASH or ALG_TYPE_ANY or ALG_SID_SHA_512; 220 | // #endif //(NTDDI_VERSION > NTDDI_WINXPSP2) 221 | // #if (NTDDI_VERSION >= NTDDI_VISTA) 222 | CALG_ECDH = ALG_CLASS_KEY_EXCHANGE or ALG_TYPE_DH or ALG_SID_ECDH; 223 | CALG_ECMQV = ALG_CLASS_KEY_EXCHANGE or ALG_TYPE_ANY or ALG_SID_ECMQV; 224 | CALG_ECDSA = ALG_CLASS_SIGNATURE or ALG_TYPE_DSS or ALG_SID_ECDSA; 225 | // #endif //(NTDDI_VERSION >= NTDDI_VISTA) 226 | 227 | 228 | // #if (NTDDI_VERSION < NTDDI_WINXP) 229 | // resource number for signatures in the CSP 230 | SIGNATURE_RESOURCE_NUMBER = $29A; 231 | 232 | type 233 | VTableProvStruc = record 234 | Version : DWORD; 235 | FuncVerifyImage : FARPROC; 236 | FuncReturnhWnd : FARPROC; 237 | dwProvType : DWORD; 238 | pbContextInfo : PBYTE; 239 | cbContextInfo : DWORD; 240 | pszProvName : LPSTR; 241 | end; 242 | PVTableProvStruc = ^VTableProvStruc; 243 | TVTableProvStruc = VTableProvStruc; 244 | // #endif //(NTDDI_VERSION < NTDDI_WINXP) 245 | 246 | // Used for certenroll.idl: 247 | // certenrolls_begin -- HCRYPT* 248 | // #ifndef HCRYPTPROV_DEFINED 249 | // #define HCRYPTPROV_DEFINED 250 | HCRYPTPROV = ULONG_PTR; 251 | HCRYPTKEY = ULONG_PTR; 252 | HCRYPTHASH = ULONG_PTR; 253 | // #endif 254 | // certenrolls_end 255 | 256 | 257 | 258 | const 259 | // dwFlags definitions for CryptAcquireContext 260 | CRYPT_VERIFYCONTEXT = $F0000000; 261 | CRYPT_NEWKEYSET = $00000008; 262 | CRYPT_DELETEKEYSET = $00000010; 263 | CRYPT_MACHINE_KEYSET = $00000020; 264 | CRYPT_SILENT = $00000040; 265 | // #if (NTDDI_VERSION >= NTDDI_VISTA) 266 | CRYPT_DEFAULT_CONTAINER_OPTIONAL = $00000080; 267 | // #endif //(NTDDI_VERSION >= NTDDI_VISTA) 268 | 269 | // dwFlag definitions for CryptGenKey 270 | CRYPT_EXPORTABLE = $00000001; 271 | CRYPT_USER_PROTECTED = $00000002; 272 | CRYPT_CREATE_SALT = $00000004; 273 | CRYPT_UPDATE_KEY = $00000008; 274 | CRYPT_NO_SALT = $00000010; 275 | CRYPT_PREGEN = $00000040; 276 | CRYPT_RECIPIENT = $00000010; 277 | CRYPT_INITIATOR = $00000040; 278 | CRYPT_ONLINE = $00000080; 279 | CRYPT_SF = $00000100; 280 | CRYPT_CREATE_IV = $00000200; 281 | CRYPT_KEK = $00000400; 282 | CRYPT_DATA_KEY = $00000800; 283 | CRYPT_VOLATILE = $00001000; 284 | CRYPT_SGCKEY = $00002000; 285 | //PKCS12_ALLOW_OVERWRITE_KEY 0x00004000 286 | //PKCS12_NO_PERSIST_KEY 0x00008000 287 | //should use other than these two 288 | CRYPT_USER_PROTECTED_STRONG = $00100000; 289 | // #if (NTDDI_VERSION >= NTDDI_WINXP) 290 | CRYPT_ARCHIVABLE = $00004000; 291 | // #endif //(NTDDI_VERSION >= NTDDI_WINXP) 292 | // #if (NTDDI_VERSION >= NTDDI_VISTA) 293 | CRYPT_FORCE_KEY_PROTECTION_HIGH = $00008000; 294 | // #endif //(NTDDI_VERSION >= NTDDI_VISTA) 295 | 296 | RSA1024BIT_KEY = $04000000; 297 | 298 | // dwFlags definitions for CryptDeriveKey 299 | CRYPT_SERVER = $00000400; 300 | 301 | KEY_LENGTH_MASK = $FFFF0000; 302 | 303 | // dwFlag definitions for CryptExportKey 304 | CRYPT_Y_ONLY = $00000001; 305 | CRYPT_SSL2_FALLBACK = $00000002; 306 | CRYPT_DESTROYKEY = $00000004; 307 | CRYPT_OAEP = $00000040; // used with RSA encryptions/decryptions 308 | // CryptExportKey, CryptImportKey, 309 | // CryptEncrypt and CryptDecrypt 310 | 311 | CRYPT_BLOB_VER3 = $00000080; // export version 3 of a blob type 312 | // #if (NTDDI_VERSION >= NTDDI_WINXP) 313 | CRYPT_IPSEC_HMAC_KEY = $00000100; // CryptImportKey only 314 | // #endif //(NTDDI_VERSION >= NTDDI_WINXP) 315 | 316 | // #if (NTDDI_VERSION >= NTDDI_WS03) 317 | // dwFlags definitions for CryptDecrypt 318 | // See also CRYPT_OAEP, above. 319 | // Note, the following flag is not supported for CryptEncrypt 320 | CRYPT_DECRYPT_RSA_NO_PADDING_CHECK = $00000020; 321 | // #endif //(NTDDI_VERSION >= NTDDI_WS03) 322 | 323 | // dwFlags definitions for CryptCreateHash 324 | CRYPT_SECRETDIGEST = $00000001; 325 | 326 | // #if (NTDDI_VERSION >= NTDDI_WINXP) 327 | // dwFlags definitions for CryptHashData 328 | CRYPT_OWF_REPL_LM_HASH = $00000001; // this is only for the OWF replacement CSP 329 | // #endif //(NTDDI_VERSION >= NTDDI_WINXP) 330 | 331 | // dwFlags definitions for CryptHashSessionKey 332 | CRYPT_LITTLE_ENDIAN = $00000001; 333 | 334 | // dwFlags definitions for CryptSignHash and CryptVerifySignature 335 | CRYPT_NOHASHOID = $00000001; 336 | CRYPT_TYPE2_FORMAT = $00000002; // Not supported 337 | CRYPT_X931_FORMAT = $00000004; // Not supported 338 | 339 | // dwFlag definitions for CryptSetProviderEx and CryptGetDefaultProvider 340 | CRYPT_MACHINE_DEFAULT = $00000001; 341 | CRYPT_USER_DEFAULT = $00000002; 342 | CRYPT_DELETE_DEFAULT = $00000004; 343 | 344 | // exported key blob definitions 345 | // certenrolld_begin -- *BLOB 346 | SIMPLEBLOB = $1; 347 | PUBLICKEYBLOB = $6; 348 | PRIVATEKEYBLOB = $7; 349 | PLAINTEXTKEYBLOB = $8; 350 | OPAQUEKEYBLOB = $9; 351 | PUBLICKEYBLOBEX = $A; 352 | SYMMETRICWRAPKEYBLOB = $B; 353 | // #if (NTDDI_VERSION >= NTDDI_WS03) 354 | KEYSTATEBLOB = $C; 355 | // #endif //(NTDDI_VERSION >= NTDDI_WS03) 356 | // certenrolld_end 357 | 358 | // certenrolld_begin -- AT_* 359 | AT_KEYEXCHANGE = 1; 360 | AT_SIGNATURE = 2; 361 | // certenrolld_end 362 | 363 | CRYPT_USERDATA = 1; 364 | 365 | // dwParam 366 | KP_IV = 1; // Initialization vector 367 | KP_SALT = 2; // Salt value 368 | KP_PADDING = 3; // Padding values 369 | KP_MODE = 4; // Mode of the cipher 370 | KP_MODE_BITS = 5; // Number of bits to feedback 371 | KP_PERMISSIONS = 6; // Key permissions DWORD 372 | KP_ALGID = 7; // Key algorithm 373 | KP_BLOCKLEN = 8; // Block size of the cipher 374 | KP_KEYLEN = 9; // Length of key in bits 375 | KP_SALT_EX = 10; // Length of salt in bytes 376 | KP_P = 11; // DSS/Diffie-Hellman P value 377 | KP_G = 12; // DSS/Diffie-Hellman G value 378 | KP_Q = 13; // DSS Q value 379 | KP_X = 14; // Diffie-Hellman X value 380 | KP_Y = 15; // Y value 381 | KP_RA = 16; // Fortezza RA value 382 | KP_RB = 17; // Fortezza RB value 383 | KP_INFO = 18; // for putting information into an RSA envelope 384 | KP_EFFECTIVE_KEYLEN = 19; // setting and getting RC2 effective key length 385 | KP_SCHANNEL_ALG = 20; // for setting the Secure Channel algorithms 386 | KP_CLIENT_RANDOM = 21; // for setting the Secure Channel client random data 387 | KP_SERVER_RANDOM = 22; // for setting the Secure Channel server random data 388 | KP_RP = 23; 389 | KP_PRECOMP_MD5 = 24; 390 | KP_PRECOMP_SHA = 25; 391 | KP_CERTIFICATE = 26; // for setting Secure Channel certificate data (PCT1) 392 | KP_CLEAR_KEY = 27; // for setting Secure Channel clear key data (PCT1) 393 | KP_PUB_EX_LEN = 28; 394 | KP_PUB_EX_VAL = 29; 395 | KP_KEYVAL = 30; 396 | KP_ADMIN_PIN = 31; 397 | KP_KEYEXCHANGE_PIN = 32; 398 | KP_SIGNATURE_PIN = 33; 399 | KP_PREHASH = 34; 400 | // #if (NTDDI_VERSION >= NTDDI_WS03) 401 | KP_ROUNDS = 35; 402 | // #endif //(NTDDI_VERSION >= NTDDI_WS03) 403 | KP_OAEP_PARAMS = 36; // for setting OAEP params on RSA keys 404 | KP_CMS_KEY_INFO = 37; 405 | KP_CMS_DH_KEY_INFO = 38; 406 | KP_PUB_PARAMS = 39; // for setting public parameters 407 | KP_VERIFY_PARAMS = 40; // for verifying DSA and DH parameters 408 | KP_HIGHEST_VERSION = 41; // for TLS protocol version setting 409 | // #if (NTDDI_VERSION >= NTDDI_WS03) 410 | KP_GET_USE_COUNT = 42; // for use with PP_CRYPT_COUNT_KEY_USE contexts 411 | // #endif //(NTDDI_VERSION >= NTDDI_WS03) 412 | KP_PIN_ID = 43; 413 | KP_PIN_INFO = 44; 414 | 415 | // KP_PADDING 416 | PKCS5_PADDING = 1; // PKCS 5 (sec 6.2) padding method 417 | RANDOM_PADDING = 2; 418 | ZERO_PADDING = 3; 419 | 420 | // KP_MODE 421 | CRYPT_MODE_CBC = 1; // Cipher block chaining 422 | CRYPT_MODE_ECB = 2; // Electronic code book 423 | CRYPT_MODE_OFB = 3; // Output feedback mode 424 | CRYPT_MODE_CFB = 4; // Cipher feedback mode 425 | CRYPT_MODE_CTS = 5; // Ciphertext stealing mode 426 | 427 | // KP_PERMISSIONS 428 | CRYPT_ENCRYPT = $0001; // Allow encryption 429 | CRYPT_DECRYPT = $0002; // Allow decryption 430 | CRYPT_EXPORT = $0004; // Allow key to be exported 431 | CRYPT_READ = $0008; // Allow parameters to be read 432 | CRYPT_WRITE = $0010; // Allow parameters to be set 433 | CRYPT_MAC = $0020; // Allow MACs to be used with key 434 | CRYPT_EXPORT_KEY = $0040; // Allow key to be used for exporting keys 435 | CRYPT_IMPORT_KEY = $0080; // Allow key to be used for importing keys 436 | // #if (NTDDI_VERSION >= NTDDI_WINXP) 437 | CRYPT_ARCHIVE = $0100; // Allow key to be exported at creation only 438 | // #endif //(NTDDI_VERSION >= NTDDI_WINXP) 439 | 440 | HP_ALGID = $0001; // Hash algorithm 441 | HP_HASHVAL = $0002; // Hash value 442 | HP_HASHSIZE = $0004; // Hash value size 443 | HP_HMAC_INFO = $0005; // information for creating an HMAC 444 | HP_TLS1PRF_LABEL = $0006; // label for TLS1 PRF 445 | HP_TLS1PRF_SEED = $0007; // seed for TLS1 PRF 446 | 447 | CRYPT_FAILED = BOOL(FALSE); 448 | CRYPT_SUCCEED = BOOL(TRUE); 449 | 450 | function RCrypt_Succeeded(rt: BOOL): Boolean; inline; 451 | function RCrypt_Failed(rt: BOOL): Boolean; inline; 452 | 453 | const 454 | // 455 | // CryptGetProvParam 456 | // 457 | PP_ENUMALGS = 1; 458 | PP_ENUMCONTAINERS = 2; 459 | PP_IMPTYPE = 3; 460 | PP_NAME = 4; 461 | PP_VERSION = 5; 462 | PP_CONTAINER = 6; 463 | PP_CHANGE_PASSWORD = 7; 464 | PP_KEYSET_SEC_DESCR = 8; // get/set security descriptor of keyset 465 | PP_CERTCHAIN = 9; // for retrieving certificates from tokens 466 | PP_KEY_TYPE_SUBTYPE = 10; 467 | PP_PROVTYPE = 16; 468 | PP_KEYSTORAGE = 17; 469 | PP_APPLI_CERT = 18; 470 | PP_SYM_KEYSIZE = 19; 471 | PP_SESSION_KEYSIZE = 20; 472 | PP_UI_PROMPT = 21; 473 | PP_ENUMALGS_EX = 22; 474 | PP_ENUMMANDROOTS = 25; 475 | PP_ENUMELECTROOTS = 26; 476 | PP_KEYSET_TYPE = 27; 477 | PP_ADMIN_PIN = 31; 478 | PP_KEYEXCHANGE_PIN = 32; 479 | PP_SIGNATURE_PIN = 33; 480 | PP_SIG_KEYSIZE_INC = 34; 481 | PP_KEYX_KEYSIZE_INC = 35; 482 | PP_UNIQUE_CONTAINER = 36; 483 | PP_SGC_INFO = 37; 484 | PP_USE_HARDWARE_RNG = 38; 485 | PP_KEYSPEC = 39; 486 | PP_ENUMEX_SIGNING_PROT = 40; 487 | // #if (NTDDI_VERSION >= NTDDI_WS03) 488 | PP_CRYPT_COUNT_KEY_USE = 41; 489 | // #endif //(NTDDI_VERSION >= NTDDI_WS03) 490 | // #if (NTDDI_VERSION >= NTDDI_VISTA) 491 | PP_USER_CERTSTORE = 42; 492 | PP_SMARTCARD_READER = 43; 493 | PP_SMARTCARD_GUID = 45; 494 | PP_ROOT_CERTSTORE = 46; 495 | // #endif //(NTDDI_VERSION >= NTDDI_VISTA) 496 | // #if (NTDDI_VERSION >= NTDDI_WIN8) 497 | PP_SMARTCARD_READER_ICON = 47; 498 | // #endif // (NTDDI_VERSION >= NTDDI_WIN8) 499 | 500 | CRYPT_FIRST = 1; 501 | CRYPT_NEXT = 2; 502 | CRYPT_SGC_ENUM = 4; 503 | 504 | CRYPT_IMPL_HARDWARE = 1; 505 | CRYPT_IMPL_SOFTWARE = 2; 506 | CRYPT_IMPL_MIXED = 3; 507 | CRYPT_IMPL_UNKNOWN = 4; 508 | CRYPT_IMPL_REMOVABLE = 8; 509 | 510 | // key storage flags 511 | CRYPT_SEC_DESCR = $00000001; 512 | CRYPT_PSTORE = $00000002; 513 | CRYPT_UI_PROMPT = $00000004; 514 | 515 | // protocol flags 516 | CRYPT_FLAG_PCT1 = $0001; 517 | CRYPT_FLAG_SSL2 = $0002; 518 | CRYPT_FLAG_SSL3 = $0004; 519 | CRYPT_FLAG_TLS1 = $0008; 520 | CRYPT_FLAG_IPSEC = $0010; 521 | CRYPT_FLAG_SIGNING = $0020; 522 | 523 | // SGC flags 524 | CRYPT_SGC = $0001; 525 | CRYPT_FASTSGC = $0002; 526 | 527 | // 528 | // CryptSetProvParam 529 | // 530 | PP_CLIENT_HWND = 1; 531 | PP_CONTEXT_INFO = 11; 532 | PP_KEYEXCHANGE_KEYSIZE = 12; 533 | PP_SIGNATURE_KEYSIZE = 13; 534 | PP_KEYEXCHANGE_ALG = 14; 535 | PP_SIGNATURE_ALG = 15; 536 | PP_DELETEKEY = 24; 537 | // #if (NTDDI_VERSION >= NTDDI_VISTA) 538 | PP_PIN_PROMPT_STRING = 44; 539 | PP_SECURE_KEYEXCHANGE_PIN = 47; 540 | PP_SECURE_SIGNATURE_PIN = 48; 541 | // #endif //(NTDDI_VERSION >= NTDDI_VISTA) 542 | 543 | // certenrolld_begin -- PROV_RSA_* 544 | PROV_RSA_FULL = 1; 545 | PROV_RSA_SIG = 2; 546 | PROV_DSS = 3; 547 | PROV_FORTEZZA = 4; 548 | PROV_MS_EXCHANGE = 5; 549 | PROV_SSL = 6; 550 | PROV_RSA_SCHANNEL = 12; 551 | PROV_DSS_DH = 13; 552 | PROV_EC_ECDSA_SIG = 14; 553 | PROV_EC_ECNRA_SIG = 15; 554 | PROV_EC_ECDSA_FULL = 16; 555 | PROV_EC_ECNRA_FULL = 17; 556 | PROV_DH_SCHANNEL = 18; 557 | PROV_SPYRUS_LYNKS = 20; 558 | PROV_RNG = 21; 559 | PROV_INTEL_SEC = 22; 560 | // #if (NTDDI_VERSION >= NTDDI_WINXP) 561 | PROV_REPLACE_OWF = 23; 562 | PROV_RSA_AES = 24; 563 | // #endif //(NTDDI_VERSION >= NTDDI_WINXP) 564 | // certenrolld_end 565 | 566 | // #if (NTDDI_VERSION <= NTDDI_WINXP) 567 | // 568 | // STT defined Providers 569 | // 570 | PROV_STT_MER = 7; 571 | PROV_STT_ACQ = 8; 572 | PROV_STT_BRND = 9; 573 | PROV_STT_ROOT = 10; 574 | PROV_STT_ISS = 11; 575 | // #endif //(NTDDI_VERSION <= NTDDI_WINXP) 576 | 577 | // 578 | // Provider friendly names 579 | // 580 | MS_DEF_PROV : PChar = 'Microsoft Base Cryptographic Provider v1.0'; 581 | MS_ENHANCED_PROV : PChar = 'Microsoft Enhanced Cryptographic Provider v1.0'; 582 | MS_STRONG_PROV : PChar = 'Microsoft Strong Cryptographic Provider'; 583 | MS_DEF_RSA_SIG_PROV : PChar = 'Microsoft RSA Signature Cryptographic Provider'; 584 | MS_DEF_RSA_SCHANNEL_PROV: PChar = 'Microsoft RSA SChannel Cryptographic Provider'; 585 | MS_DEF_DSS_PROV : PChar = 'Microsoft Base DSS Cryptographic Provider'; 586 | MS_DEF_DSS_DH_PROV : PChar = 'Microsoft Base DSS and Diffie-Hellman Cryptographic Provider'; 587 | MS_ENH_DSS_DH_PROV : PChar = 'Microsoft Enhanced DSS and Diffie-Hellman Cryptographic Provider'; 588 | MS_DEF_DH_SCHANNEL_PROV : PChar = 'Microsoft DH SChannel Cryptographic Provider'; 589 | MS_SCARD_PROV : PChar = 'Microsoft Base Smart Card Crypto Provider'; 590 | 591 | // #if (NTDDI_VERSION >= NTDDI_WINXP) 592 | MS_ENH_RSA_AES_PROV: PChar = 'Microsoft Enhanced RSA and AES Cryptographic Provider'; 593 | MS_ENH_RSA_AES_PROV_XP_A: PChar = 'Microsoft Enhanced RSA and AES Cryptographic Provider (Prototype)'; 594 | // #endif //(NTDDI_VERSION >= NTDDI_WINXP) 595 | 596 | MAXUIDLEN = 64; 597 | 598 | // Exponentiation Offload Reg Location 599 | EXPO_OFFLOAD_REG_VALUE = 'ExpoOffload'; 600 | EXPO_OFFLOAD_FUNC_NAME = 'OffloadModExpo'; 601 | 602 | // 603 | // Registry key in which the following private key-related 604 | // values are created. 605 | // 606 | szKEY_CRYPTOAPI_PRIVATE_KEY_OPTIONS: PChar = 607 | 'Software\\Policies\\Microsoft\\Cryptography'; 608 | 609 | 610 | // 611 | // Registry values for enabling and controlling the caching (and timeout) 612 | // of private keys. This feature is intended for UI-protected private 613 | // keys. 614 | // 615 | // Note that in Windows 2000 and later, private keys, once read from storage, 616 | // are cached in the associated HCRYPTPROV structure for subsequent use. 617 | // 618 | // In Server 2003 and XP SP1, new key caching behavior is available. Keys 619 | // that have been read from storage and cached may now be considered "stale" 620 | // if a period of time has elapsed since the key was last used. This forces 621 | // the key to be re-read from storage (which will make the DPAPI UI appear 622 | // again). 623 | // 624 | // Optional Key Timeouts: 625 | // 626 | // In Windows Server 2003, XP SP1, and later, new key caching behavior is 627 | // available. Keys that have been read from storage and cached per-context 628 | // may now be considered "stale" if a period of time has elapsed since the 629 | // key was last used. This forces the key to be re-read from storage (which 630 | // will make the Data Protection API dialog appear again if the key is 631 | // UI-protected). 632 | // 633 | // To enable the new behavior, create the registry DWORD value 634 | // szKEY_CACHE_ENABLED and set it to 1. The registry DWORD value 635 | // szKEY_CACHE_SECONDS must also be created and set to the number of seconds 636 | // that a cached private key may still be considered usable. 637 | // 638 | szKEY_CACHE_ENABLED: PChar = 'CachePrivateKeys'; 639 | szKEY_CACHE_SECONDS: PChar = 'PrivateKeyLifetimeSeconds'; 640 | 641 | // #if (NTDDI_VERSION >= NTDDI_WINXP) 642 | // 643 | // In platforms later than (and not including) Windows Server 2003, private 644 | // keys are always cached for a period of time per-process, even when 645 | // not being used in any context. 646 | // 647 | // The differences between the process-wide caching settings described below 648 | // and the Optional Key Timeouts described above are subtle. 649 | // 650 | // - The Optional Key Timeout policy is applied only when an attempt is made 651 | // to use a specific private key with an open context handle (HCRYPTPROV). 652 | // If szKEY_CACHE_SECONDS have elapsed since the key was last used, the 653 | // private key will be re-read from storage. 654 | // 655 | // - The Cache Purge Interval policy, below, is applied whenever any 656 | // non-ephemeral private key is used or read from storage. If 657 | // szPRIV_KEY_CACHE_PURGE_INTERVAL_SECONDS have elapsed since the last 658 | // purge occurred, all cached keys that have not been referenced since the 659 | // last purge will be removed from the cache. 660 | // 661 | // If a private key that is purged from the cache is currently 662 | // referenced in an open context, then the key will be re-read from storage 663 | // the next time an attempt is made to use it (via any context). 664 | // 665 | // The following two registry DWORD values control this behavior. 666 | // 667 | 668 | // 669 | // Registry value for controlling the maximum number of persisted 670 | // (non-ephemeral) private keys that can be cached per-process. If the cache 671 | // fills up, keys will be replaced on a least-recently-used basis. If the 672 | // maximum number of cached keys is set to zero, no keys will be globally 673 | // cached. 674 | // 675 | szPRIV_KEY_CACHE_MAX_ITEMS: PChar = 'PrivKeyCacheMaxItems'; 676 | cPRIV_KEY_CACHE_MAX_ITEMS_DEFAULT = 20; 677 | 678 | // 679 | // Registry value for controlling the interval at which the private key 680 | // cache is proactively purged of outdated keys. 681 | // 682 | szPRIV_KEY_CACHE_PURGE_INTERVAL_SECONDS: PChar = 'PrivKeyCachePurgeIntervalSeconds'; 683 | cPRIV_KEY_CACHE_PURGE_INTERVAL_SECONDS_DEFAULT = 86400; // 1 day 684 | // #endif //(NTDDI_VERSION >= NTDDI_WINXP) 685 | 686 | CUR_BLOB_VERSION = 2; 687 | 688 | type 689 | // structure for use with CryptSetKeyParam for CMS keys 690 | // DO NOT USE THIS STRUCTURE!!!!! 691 | _CMS_KEY_INFO = record 692 | dwVersion : DWORD; // sizeof(CMS_KEY_INFO) 693 | Algid : ALG_ID; // algorithmm id for the key to be converted 694 | pbOID : PBYTE; // pointer to OID to hash in with Z 695 | cbOID : DWORD; // length of OID to hash in with Z 696 | end; 697 | CMS_KEY_INFO = _CMS_KEY_INFO; 698 | PCMS_KEY_INFO = ^CMS_KEY_INFO; 699 | TCmsKeyInfo = CMS_KEY_INFO; 700 | PCmsKeyInfo = ^TCmsKeyInfo; 701 | 702 | // structure for use with CryptSetHashParam with CALG_HMAC 703 | _HMAC_Info = record 704 | HashAlgid : ALG_ID; 705 | pbInnerString : PBYTE; 706 | cbInnerString : DWORD; 707 | pbOuterString : BYTE; 708 | cbOuterString : DWORD; 709 | end; 710 | HMAC_INFO = _HMAC_Info; 711 | PHMAC_INFO = ^HMAC_INFO; 712 | THMACInfo = HMAC_INFO; 713 | PHMACInfo = ^THMACInfo; 714 | 715 | // structure for use with CryptSetKeyParam with KP_SCHANNEL_ALG 716 | _SCHANNEL_ALG = record 717 | dwUse : DWORD; 718 | Algid : ALG_ID; 719 | cBits : DWORD; 720 | dwFlags : DWORD; 721 | dwReserved: DWORD; 722 | end; 723 | SCHANNEL_ALG = _SCHANNEL_ALG; 724 | PSCHANNEL_ALG = ^SCHANNEL_ALG; 725 | TSchannelAlg = SCHANNEL_ALG; 726 | PSchannelAlg = ^TSchannelAlg; 727 | 728 | const 729 | // uses of algortihms for SCHANNEL_ALG structure 730 | SCHANNEL_MAC_KEY = $00000000; 731 | SCHANNEL_ENC_KEY = $00000001; 732 | 733 | // uses of dwFlags SCHANNEL_ALG structure 734 | INTERNATIONAL_USAGE = $00000001; 735 | 736 | type 737 | _PROV_ENUMALGS = record 738 | aiAlgid: ALG_ID; 739 | dwBitLen: DWORD; 740 | dwNameLen: DWORD; 741 | szName: array[0..19] of CHAR; 742 | end; 743 | PROV_ENUMALGS = _PROV_ENUMALGS; 744 | TProvEnumAlgs = PROV_ENUMALGS; 745 | PProvEnumAlgs = ^TProvEnumAlgs; 746 | 747 | // certenrolls_begin -- PROV_ENUMALGS_EX 748 | _PROV_ENUMALGS_EX = record 749 | aiAlgid: ALG_ID; 750 | dwDefaultLen: DWORD; 751 | dwMinLen: DWORD; 752 | dwMaxLen: DWORD; 753 | dwProtocols: DWORD; 754 | dwNameLen: DWORD; 755 | szName: array[0..19] of CHAR; 756 | dwLongNameLen: DWORD; 757 | szLongName: array[0..39] of CHAR; 758 | end; 759 | PROV_ENUMALGS_EX = _PROV_ENUMALGS_EX; 760 | TProvEnumAlgsEx = PROV_ENUMALGS_EX; 761 | PProvEnumAlgsEx = ^TProvEnumAlgsEx; 762 | // certenrolls_end 763 | 764 | _PUBLICKEYSTRUC = record 765 | bType : BYTE; 766 | bVersion: BYTE; 767 | reserved: WORD; 768 | aiKeyAlg: ALG_ID; 769 | end; 770 | BLOBHEADER = _PUBLICKEYSTRUC; 771 | PUBLICKEYSTRUC = _PUBLICKEYSTRUC; 772 | TPublicKeyStruc = _PUBLICKEYSTRUC; 773 | PPublicKeyStruc = TPublicKeyStruc; 774 | 775 | _RSAPUBKEY = record 776 | magic : DWORD; // Has to be RSA1 777 | bitlen: DWORD; // # of bits in modulus 778 | pubexp: DWORD; // public exponent 779 | // Modulus data follows 780 | end; 781 | RSAPUBKEY = _RSAPUBKEY; 782 | TRSAPubKey = _RSAPUBKEY; 783 | PRSAPubKey = TRSAPubKey; 784 | 785 | _PUBKEY = record 786 | magic : DWORD; 787 | bitlen: DWORD; // # of bits in modulus 788 | end; 789 | DHPUBKEY = _PUBKEY; 790 | TDHPubKey = _PUBKEY; 791 | DSSPUBKEY = _PUBKEY; 792 | TDSSPubKey = _PUBKEY; 793 | KEAPUBKEY = _PUBKEY; 794 | TKEAPubKey = _PUBKEY; 795 | TEKPUBKEY = _PUBKEY; 796 | 797 | _DSSSEED = record 798 | counter: DWORD; 799 | seed: array[0..19] of BYTE; 800 | end; 801 | DSSSEED = _DSSSEED; 802 | TDSSSeed = DSSSEED; 803 | 804 | _PUBKEYVER3 = record 805 | magic: DWORD; 806 | bitlenP: DWORD; // # of bits in prime modulus 807 | bitlenQ: DWORD; // # of bits in prime q, 0 if not available 808 | bitlenJ: DWORD; // # of bits in (p-1)/q, 0 if not available 809 | DSSSeed: TDSSSeed; 810 | end; 811 | DHPUBKEY_VER3 = _PUBKEYVER3; 812 | TDHPubKeyVer3 = DHPUBKEY_VER3; 813 | DSSPUBKEY_VER3 = _PUBKEYVER3; 814 | TDSSPubKeyVer3 = DSSPUBKEY_VER3; 815 | 816 | _PRIVKEYVER3 = record 817 | magic : DWORD; 818 | bitlenP: DWORD; // # of bits in prime modulus 819 | bitlenQ: DWORD; // # of bits in prime q, 0 if not available 820 | bitlenJ: DWORD; // # of bits in (p-1)/q, 0 if not available 821 | bitlenX: DWORD; // # of bits in X 822 | DSSSeed: TDSSSeed; 823 | end; 824 | DHPRIVKEY_VER3 = _PRIVKEYVER3; 825 | TDHPrivKeyVer3 = DHPRIVKEY_VER3; 826 | DSSPRIVKEY_VER3 = _PRIVKEYVER3; 827 | TDSSPrivKeyVer3 = DSSPRIVKEY_VER3; 828 | 829 | _KEY_TYPE_SUBTYPE = record 830 | dwKeySpec: DWORD; 831 | &Type : TGUID; 832 | Subtype : TGUID; 833 | end; 834 | KEY_TYPE_SUBTYPE = _KEY_TYPE_SUBTYPE; 835 | PKEY_TYPE_SUBTYPE = ^_KEY_TYPE_SUBTYPE; 836 | TKeyTypeSubtype = KEY_TYPE_SUBTYPE; 837 | PKeyTypeSubtype = ^TKeyTypeSubtype; 838 | 839 | _CERT_FORTEZZA_DATA_PROP = record 840 | SerialNumber: array[0..7] of Byte; 841 | CertIndex : Integer; 842 | CertLabel : array[0..35] of Byte; 843 | end; 844 | CERT_FORTEZZA_DATA_PROP = _CERT_FORTEZZA_DATA_PROP; 845 | TCertFortezzaDataProp = CERT_FORTEZZA_DATA_PROP; 846 | 847 | // #if (NTDDI_VERSION >= NTDDI_WS03) 848 | _CRYPT_RC4_KEY_STATE = record 849 | Key : array[0..15] of Byte; 850 | SBox: array[0..255] of Byte; 851 | i: Byte; 852 | j: Byte; 853 | end; 854 | CRYPT_RC4_KEY_STATE = _CRYPT_RC4_KEY_STATE; 855 | PCRYPT_RC4_KEY_STATE = ^CRYPT_RC4_KEY_STATE; 856 | TCryptRC4KeyState = CRYPT_RC4_KEY_STATE; 857 | PCryptRC4KeyState = ^TCryptRC4KeyState; 858 | 859 | _CRYPT_DES_KEY_STATE = record 860 | Key : array[0..7] of Byte; 861 | IV : array[0..7] of Byte; 862 | Feedback: array[0..7] of Byte; 863 | end; 864 | CRYPT_DES_KEY_STATE = _CRYPT_DES_KEY_STATE; 865 | PCRYPT_DES_KEY_STATE = ^CRYPT_DES_KEY_STATE; 866 | TCryptDESKeyState = CRYPT_DES_KEY_STATE; 867 | PCryptDESKeyState = ^TCryptDESKeyState; 868 | 869 | _CRYPT_3DES_KEY_STATE = record 870 | Key : array[0..23] of Byte; 871 | IV : array[0..7] of Byte; 872 | Feedback: array[0..7] of Byte; 873 | end; 874 | CRYPT_3DES_KEY_STATE = _CRYPT_3DES_KEY_STATE; 875 | PCRYPT_3DES_KEY_STATE = ^CRYPT_3DES_KEY_STATE; 876 | TCrypt3DESKeyState = CRYPT_3DES_KEY_STATE; 877 | PCrypt3DESKeyState = ^TCrypt3DESKeyState; 878 | // #endif //(NTDDI_VERSION >= NTDDI_WS03) 879 | 880 | // #if (NTDDI_VERSION >= NTDDI_VISTA) 881 | _CRYPT_AES_128_KEY_STATE = record 882 | Key : array[0..15] of Byte; 883 | IV : array[0..15] of Byte; 884 | EncryptionState : array[0..10, 0..15] of Byte; // 10 rounds + 1 885 | DecryptionState : array[0..10, 0..15] of Byte; 886 | Feedback : array[0..15] of Byte; 887 | end; 888 | CRYPT_AES_128_KEY_STATE = _CRYPT_AES_128_KEY_STATE; 889 | PCRYPT_AES_128_KEY_STATE = ^CRYPT_AES_128_KEY_STATE; 890 | TCryptAES128KeyState = CRYPT_AES_128_KEY_STATE; 891 | PCryptAES128KeyState = ^TCryptAES128KeyState; 892 | 893 | _CRYPT_AES_256_KEY_STATE = record 894 | Key: array[0..31] of Byte; 895 | IV: array[0..15] of Byte; 896 | EncryptionState: array[0..14, 0..15] of Byte; // 14 rounds + 1 897 | DecryptionState: array[0..14, 0..15] of Byte; 898 | Feedback: array[0..15] of Byte; 899 | end; 900 | CRYPT_AES_256_KEY_STATE = _CRYPT_AES_256_KEY_STATE; 901 | PCRYPT_AES_256_KEY_STATE = ^CRYPT_AES_256_KEY_STATE; 902 | TCryptAES256KeyState = ^CRYPT_AES_256_KEY_STATE; 903 | PCryptAES256KeyState = ^TCryptAES256KeyState; 904 | // #endif //(NTDDI_VERSION >= NTDDI_VISTA) 905 | 906 | // #endif /* WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_DESKTOP) */ 907 | // #pragma endregion 908 | 909 | 910 | // #pragma region Application Family 911 | // #if WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_APP) 912 | 913 | //+------------------------------------------------------------------------- 914 | // CRYPTOAPI BLOB definitions 915 | //-------------------------------------------------------------------------- 916 | // certenrolls_begin -- *_BLOB 917 | _CRYPTOAPI_BLOB = record 918 | cbData: DWORD; 919 | pbData: PBYTE; 920 | end; 921 | TCryptoApiBlob = _CRYPTOAPI_BLOB; 922 | PCryptoApiBlob = ^TCryptoApiBlob; 923 | TCryptIntegerBlob = TCryptoApiBlob; 924 | PCryptIntegerBlob = ^TCryptIntegerBlob; 925 | TCryptUIntBlob = TCryptoApiBlob; 926 | PCryptUIntBlob = ^TCryptUIntBlob; 927 | TCryptObjIDBlob = TCryptoApiBlob; 928 | PCryptObjIDBlob = ^TCryptObjIDBlob; 929 | TCertNameBlob = TCryptoApiBlob; 930 | PCertNameBlob = ^TCertNameBlob; 931 | TCertRdnValueBlob = TCryptoApiBlob; 932 | PCertRdnValueBlob = ^TCertRdnValueBlob; 933 | TCertBlob = TCryptoApiBlob; 934 | PCertBlob = ^TCertBlob; 935 | TCrlBlob = TCryptoApiBlob; 936 | TDataBlob = TCryptoApiBlob; 937 | PDataBlob = ^TDataBlob; 938 | TCryptDataBlob = TCryptoApiBlob; 939 | PCryptDataBlob = ^TCryptDataBlob; 940 | TCryptHashBlob = TCryptoApiBlob; 941 | PCryptHashBlob = ^TCryptHashBlob; 942 | TCryptDigestBlob = TCryptoApiBlob; 943 | PCryptDigestBlob = ^TCryptDigestBlob; 944 | TCryptDerBlob = TCryptoApiBlob; 945 | PCryptDerBlob = ^TCryptDerBlob; 946 | TCryptAttrBlob = TCryptoApiBlob; 947 | PCryptAttrBlob = ^TCryptAttrBlob; 948 | // certenrolls_end 949 | 950 | // #endif /* WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_APP) */ 951 | // #pragma endregion 952 | 953 | // #pragma region Desktop Family 954 | // #if WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_DESKTOP) 955 | 956 | // structure for use with CryptSetKeyParam for CMS keys 957 | _CMS_DH_KEY_INFO = record 958 | dwVersion: DWORD; // sizeof(CMS_DH_KEY_INFO) 959 | Algid: ALG_ID; // algorithmm id for the key to be converted 960 | pszContentEncObjId: LPSTR; // pointer to OID to hash in with Z 961 | PubInfo: TCryptDataBlob; // OPTIONAL - public information 962 | pReserved: Pointer; // reserved - should be NULL 963 | end; 964 | CMS_DH_KEY_INFO = _CMS_DH_KEY_INFO; 965 | PCMS_DH_KEY_INFO = ^CMS_DH_KEY_INFO; 966 | TCmsDHKeyInfo = CMS_DH_KEY_INFO; 967 | PCmsDHKeyInfo = ^TCmsDHKeyInfo; 968 | 969 | // #if (NTDDI_VERSION >= NTDDI_VISTA) 970 | function CryptAcquireContextA(out phProv: HCRYPTPROV; const pszContainer: LPCSTR; 971 | const pszProvider: LPCSTR; dwProvType: DWORD; dwFlags: DWORD): BOOL stdcall; 972 | function CryptAcquireContextW(out phProv: HCRYPTPROV; const pszContainer: LPCWSTR; 973 | const pszProvider: LPCWSTR; dwProvType: DWORD; dwFlags: DWORD): BOOL stdcall; 974 | function CryptAcquireContext(out phProv: HCRYPTPROV; const pszContainer: LPCTSTR; 975 | const pszProvider: LPCTSTR; dwProvType: DWORD; dwFlags: DWORD): BOOL stdcall; 976 | // #endif //(NTDDI_VERSION >= NTDDI_VISTA) 977 | 978 | // #if (NTDDI_VERSION >= NTDDI_WINXP) 979 | function CryptReleaseContext(hProv: HCRYPTPROV; dwFlags: DWORD): BOOL stdcall; 980 | // #endif //(NTDDI_VERSION >= NTDDI_WINXP) 981 | 982 | function CryptGenKey(hProv: HCRYPTPROV; Algid: TAlgID; dwFlags: DWORD; 983 | out phKey: HCRYPTKEY): BOOL; stdcall; 984 | 985 | function CryptDeriveKey(hProv: HCRYPTPROV; Algid: TAlgID; 986 | hBaseData: HCRYPTHASH; dwFlags: DWORD; out phKey: HCRYPTKEY): BOOL; stdcall; 987 | 988 | function CryptDestroyKey(hKey: HCRYPTKEY): BOOL; stdcall; 989 | 990 | // #if (NTDDI_VERSION >= NTDDI_WINXP) 991 | function CryptSetKeyParam(hKey: HCRYPTKEY; dwParam: DWORD; pbData: PBYTE; 992 | dwFlags: DWORD): BOOL; stdcall; 993 | // #endif //(NTDDI_VERSION >= NTDDI_WINXP) 994 | 995 | function CryptGetKeyParam(hKey: HCRYPTKEY; dwParam: DWORD; pbData: PBYTE; 996 | pdwDataLen: PDWORD; dwFlags: DWORD): BOOL; stdcall; 997 | 998 | // #if (NTDDI_VERSION >= NTDDI_WINXP) 999 | function CryptSetHashParam(hHash: HCRYPTHASH; dwParam: DWORD; 1000 | const pbData: PBYTE; dwFlags: DWORD): BOOL; stdcall; 1001 | // #endif //(NTDDI_VERSION >= NTDDI_WINXP) 1002 | 1003 | function CryptGetHashParam(hHash: HCRYPTHASH; dwParam: DWORD; 1004 | out pbData: PBYTE; var pdwDataLen: DWORD; dwFlags: DWORD): BOOL; stdcall; 1005 | 1006 | // #if (NTDDI_VERSION >= NTDDI_WINXP) 1007 | function CryptSetProvParam(hProv: HCRYPTPROV; dwParam: DWORD; 1008 | const pbData: PBYTE; dwFlags: DWORD): BOOL; stdcall; 1009 | // #endif //(NTDDI_VERSION >= NTDDI_WINXP) 1010 | 1011 | function CryptGetProvParam(hProv: HCRYPTPROV; dwParam: DWORD;out pbData: PBYTE; 1012 | pdwDataLen: PDWORD; dwFlags: DWORD): BOOL; stdcall; 1013 | 1014 | function CryptGenRandom(hProv: HCRYPTPROV; dwLen: DWORD; 1015 | pbBuffer: PBYTE): BOOL; stdcall; 1016 | 1017 | function CryptGetUserKey(hProv: HCRYPTPROV; dwKeySpec: DWORD; 1018 | out phUserKey: HCRYPTKEY): BOOL; stdcall; 1019 | 1020 | function CryptExportKey(hKey: HCRYPTKEY; hExpKey: HCRYPTKEY; dwBlobType: DWORD; 1021 | dwFlags: DWORD; out pbData: PBYTE; pdwDataLen: PDWORD): BOOL; stdcall; 1022 | 1023 | function CryptImportKey(hProv: HCRYPTPROV; const pbData: PBYTE; dwDataLen: DWORD; 1024 | hPubKey: HCRYPTKEY; dwFlags: DWORD; out phKey: HCRYPTKEY): BOOL; stdcall; 1025 | 1026 | function CryptEncrypt(hKey: HCRYPTKEY; hHash: HCRYPTHASH; &Final: BOOL; 1027 | dwFlags: DWORD; pbData: PBYTE; pdwDataLen: PDWORD; 1028 | dwBufLen: DWORD): BOOL; stdcall; 1029 | 1030 | function CryptDecrypt(hKey: HCRYPTKEY; hHash: HCRYPTHASH; &Final: BOOL; 1031 | dwFlags: DWORD; pbData: PBYTE; pdwDataLen: PDWORD): BOOL; stdcall; 1032 | 1033 | function CryptCreateHash(hProv: HCRYPTPROV; Algid: TAlgID; hKey: HCRYPTKEY; 1034 | dwFlags: DWORD; out phHash: HCRYPTHASH): BOOL stdcall; 1035 | 1036 | function CryptHashData(hHash: HCRYPTHASH; const pbData: PBYTE; dwDataLen: DWORD; 1037 | dwFlags: DWORD): BOOL; stdcall; 1038 | 1039 | function CryptHashSessionKey(hHash: HCRYPTHASH; hKey: HCRYPTKEY; 1040 | dwFlags: DWORD): BOOL; stdcall; 1041 | 1042 | function CryptDestroyHash(hHash: HCRYPTHASH): BOOL; stdcall; 1043 | 1044 | // #if (NTDDI_VERSION >= NTDDI_VISTA) 1045 | function CryptSignHashA(hHash: HCRYPTHASH; dwKeySpec: DWORD; 1046 | const sDescription: LPCSTR; dwFlags: DWORD; out pbSignature: PBYTE; 1047 | pdwSigLen: PDWORD): BOOL; stdcall; 1048 | function CryptSignHashW(hHash: HCRYPTHASH; dwKeySpec: DWORD; 1049 | const sDescription: LPCWSTR; dwFlags: DWORD; out pbSignature: PBYTE; 1050 | pdwSigLen: PDWORD): BOOL; stdcall; 1051 | function CryptSignHash(hHash: HCRYPTHASH; dwKeySpec: DWORD; 1052 | const sDescription: LPCTSTR; dwFlags: DWORD; out pbSignature: PBYTE; 1053 | pdwSigLen: PDWORD): BOOL; stdcall; 1054 | // #endif //(NTDDI_VERSION >= NTDDI_VISTA) 1055 | 1056 | // #if (NTDDI_VERSION >= NTDDI_VISTA) 1057 | function CryptVerifySignatureA(hHash: HCRYPTHASH; const pbSignature: PBYTE; 1058 | dwSigLen: DWORD; hPubKey: HCRYPTKEY; const sDescription: LPCSTR; 1059 | dwFlags: DWORD): BOOL; stdcall; 1060 | function CryptVerifySignatureW(hHash: HCRYPTHASH; const pbSignature: PBYTE; 1061 | dwSigLen: DWORD; hPubKey: HCRYPTKEY; const sDescription: LPCWSTR; 1062 | dwFlags: DWORD): BOOL; stdcall; 1063 | function CryptVerifySignature(hHash: HCRYPTHASH; const pbSignature: PBYTE; 1064 | dwSigLen: DWORD; hPubKey: HCRYPTKEY; const sDescription: LPCTSTR; 1065 | dwFlags: DWORD): BOOL; stdcall; 1066 | // #endif //(NTDDI_VERSION >= NTDDI_VISTA) 1067 | 1068 | // #if (NTDDI_VERSION >= NTDDI_VISTA) 1069 | function CryptSetProviderA(const pszProvName: LPCSTR; 1070 | dwProvType: DWORD): BOOL; stdcall; 1071 | function CryptSetProviderW(const pszProvName: LPCWSTR; 1072 | dwProvType: DWORD): BOOL; stdcall; 1073 | function CryptSetProvider(const pszProvName: LPCTSTR; 1074 | dwProvType: DWORD): BOOL; stdcall; 1075 | // #endif //(NTDDI_VERSION >= NTDDI_VISTA) 1076 | 1077 | // #if (NTDDI_VERSION >= NTDDI_VISTA) 1078 | 1079 | 1080 | 1081 | type 1082 | PCryptUIWizDigitalSighBlobInfo = ^TCryptUIWizDigitalSighBlobInfo; 1083 | CRYPTUI_WIZ_DIGITAL_SIGN_BLOB_INFO = record 1084 | dwSize : DWORD; 1085 | pGuidSubject : PGUID; 1086 | cbBlob : DWORD; 1087 | pbBlob : Pointer; 1088 | pwszDisplayName : LPCWSTR; 1089 | end; 1090 | TCryptUIWizDigitalSighBlobInfo = CRYPTUI_WIZ_DIGITAL_SIGN_BLOB_INFO; 1091 | 1092 | PCryptBitBlob = ^TCryptBitBlob; 1093 | CRYPT_BIT_BLOB = record 1094 | cbData : DWORD; 1095 | pbData : Pointer; 1096 | cUnusedBits : DWORD; 1097 | end; 1098 | TCryptBitBlob = CRYPT_BIT_BLOB; 1099 | 1100 | PCertExtension = ^TCertExtension; 1101 | CERT_EXTENSION = record 1102 | pszObjId : LPSTR; 1103 | fCritical : BOOL; 1104 | Value : TCryptObjIDBlob; 1105 | end; 1106 | TCertExtension = CERT_EXTENSION; 1107 | 1108 | PCryptAlgoithmIdentifier = ^TCryptAlgoithmIdentifier; 1109 | CRYPT_ALGORITHM_IDENTIFIER = record 1110 | pszObjId : LPSTR; 1111 | Parameters : TCryptObjIDBlob; 1112 | end; 1113 | TCryptAlgoithmIdentifier = CRYPT_ALGORITHM_IDENTIFIER; 1114 | 1115 | PCertPublicKeyInfo = ^TCertPublicKeyInfo; 1116 | CERT_PUBLIC_KEY_INFO = record 1117 | Algorithm: TCryptAlgoithmIdentifier; 1118 | PublicKey: TCryptBitBlob; 1119 | end; 1120 | TCertPublicKeyInfo = CERT_PUBLIC_KEY_INFO; 1121 | 1122 | PCertInfo = ^TCertInfo; 1123 | CERT_INFO = record 1124 | dwVersion : DWORD; 1125 | SerialNumber : TCryptIntegerBlob; 1126 | SignatureAlgorithm : TCryptAlgoithmIdentifier; 1127 | Issuer : TCertNameBlob; 1128 | NotBefore : TFileTime; 1129 | NotAfter : TFileTime; 1130 | Subject : TCertNameBlob; 1131 | SubjectPublicKeyInfo : TCertPublicKeyInfo; 1132 | IssuerUniqueId : TCryptBitBlob; 1133 | SubjectUniqueId : TCryptBitBlob; 1134 | cExtension : DWORD; 1135 | rgExtension : PCertExtension; 1136 | end; 1137 | TCertInfo = ^CERT_INFO; 1138 | 1139 | CERT_CONTEXT = record 1140 | dwCertEncodingType: DWORD; 1141 | pbCertEncoded : Pointer; 1142 | cbCertEncoded : DWORD; 1143 | pCertInfo : PCertInfo; 1144 | hCertStore : HCERTSTORE; 1145 | end; 1146 | 1147 | function CryptContextAddRef(hProv: HCRYPTPROV; pdwReserved: PDWORD; dwFlags: DWORD): BOOL; stdcall; 1148 | 1149 | 1150 | function CryptDuplicateHash(hHash: HCRYPTHASH; pdwReserved: PDWORD; 1151 | dwFlags: DWORD; out phHash: HCRYPTHASH): BOOL; stdcall; 1152 | function CryptVerifySignatureW(hHash: HCRYPTHASH; pbSignature: Pointer; 1153 | dwSigLen: DWORD; hPubKey: HCRYPTKEY; const sDescription: LPCWSTR; 1154 | dwFlags: DWORD): BOOL; stdcall; 1155 | 1156 | function CryptDuplicateKey(hKey: HCRYPTKEY; pdwReserved: PDWORD; dwFlags: DWORD; 1157 | out phKey: HCRYPTKEY): BOOL; stdcall; 1158 | 1159 | { dpapi.h } 1160 | 1161 | const 1162 | 1163 | // 1164 | // Registry value for controlling Data Protection API (DPAPI) UI settings. 1165 | // 1166 | 1167 | szFORCE_KEY_PROTECTION: PAnsiChar = 'ForceKeyProtection'; 1168 | 1169 | dwFORCE_KEY_PROTECTION_DISABLED = $0; 1170 | dwFORCE_KEY_PROTECTION_USER_SELECT = $1; 1171 | dwFORCE_KEY_PROTECTION_HIGH = $2; 1172 | 1173 | // 1174 | // Data protection APIs enable applications to easily secure data. 1175 | // 1176 | // The base provider provides protection based on the users' logon 1177 | // credentials. The data secured with these APIs follow the same 1178 | // roaming characteristics as HKCU -- if HKCU roams, the data 1179 | // protected by the base provider may roam as well. This makes 1180 | // the API ideal for the munging of data stored in the registry. 1181 | // 1182 | 1183 | // 1184 | // Prompt struct -- what to tell users about the access 1185 | // 1186 | type 1187 | CRYPTPROTECT_PROMPTSTRUCT = record 1188 | cbSize : DWORD; 1189 | dwPromptFlags : DWORD; 1190 | hwndApp : HWND; 1191 | szPrompt : LPCWSTR; 1192 | end; 1193 | TCryptProtectPromptStruct = CRYPTPROTECT_PROMPTSTRUCT; 1194 | PCryptProtectPromptStruct = ^TCryptProtectPromptStruct; 1195 | 1196 | 1197 | // 1198 | // base provider action 1199 | // 1200 | // CRYPTPROTECT_DEFAULT_PROVIDER { 0xdf9d8cd0, 0x1501, 0x11d1, {0x8c, 0x7a, 0x00, 0xc0, 0x4f, 0xc2, 0x97, 0xeb} } 1201 | 1202 | // 1203 | // CryptProtect PromptStruct dwPromtFlags 1204 | // 1205 | // 1206 | // prompt on unprotect 1207 | const 1208 | CRYPTPROTECT_PROMPT_ON_UNPROTECT = $1; // 1<<0 1209 | // 1210 | // prompt on protect 1211 | CRYPTPROTECT_PROMPT_ON_PROTECT = $2; // 1<<1 1212 | CRYPTPROTECT_PROMPT_RESERVED = $04; // reserved, do not use. 1213 | 1214 | // 1215 | // default to strong variant UI protection (user supplied password currently). 1216 | CRYPTPROTECT_PROMPT_STRONG = $08; // 1<<3 1217 | 1218 | // 1219 | // require strong variant UI protection (user supplied password currently). 1220 | CRYPTPROTECT_PROMPT_REQUIRE_STRONG = $10; // 1<<4 1221 | 1222 | // 1223 | // CryptProtectData and CryptUnprotectData dwFlags 1224 | // 1225 | // for remote-access situations where ui is not an option 1226 | // if UI was specified on protect or unprotect operation, the call 1227 | // will fail and GetLastError() will indicate ERROR_PASSWORD_RESTRICTION 1228 | CRYPTPROTECT_UI_FORBIDDEN = $1; 1229 | 1230 | // 1231 | // per machine protected data -- any user on machine where CryptProtectData 1232 | // took place may CryptUnprotectData 1233 | CRYPTPROTECT_LOCAL_MACHINE = $4; 1234 | 1235 | // 1236 | // force credential synchronize during CryptProtectData() 1237 | // Synchronize is only operation that occurs during this operation 1238 | CRYPTPROTECT_CRED_SYNC = $8; 1239 | 1240 | // 1241 | // Generate an Audit on protect and unprotect operations 1242 | // 1243 | CRYPTPROTECT_AUDIT = $10; 1244 | 1245 | // 1246 | // Protect data with a non-recoverable key 1247 | // 1248 | CRYPTPROTECT_NO_RECOVERY = $20; 1249 | 1250 | 1251 | // 1252 | // Verify the protection of a protected blob 1253 | // 1254 | CRYPTPROTECT_VERIFY_PROTECTION = $40; 1255 | 1256 | // 1257 | // Regenerate the local machine protection 1258 | // 1259 | CRYPTPROTECT_CRED_REGENERATE = $80; 1260 | 1261 | // flags reserved for system use 1262 | CRYPTPROTECT_FIRST_RESERVED_FLAGVAL = $0FFFFFFF; 1263 | CRYPTPROTECT_LAST_RESERVED_FLAGVAL = $FFFFFFFF; 1264 | 1265 | // 1266 | // flags specific to base provider 1267 | // 1268 | 1269 | CRYPTPROTECTMEMORY_BLOCK_SIZE = 16; 1270 | 1271 | CRYPTPROTECTMEMORY_SAME_PROCESS = $0; 1272 | CRYPTPROTECTMEMORY_CROSS_PROCESS = $1; 1273 | CRYPTPROTECTMEMORY_SAME_LOGON = $2; 1274 | 1275 | 1276 | function CryptProtectData(pDataIn: PDataBlob; const szDataDescr: LPCWSTR; 1277 | pOptionalEntropy: PDataBlob; pvReserved: PVOID; 1278 | pPromptStruct: PCryptProtectPromptStruct; dwFlags: DWORD; 1279 | pDataOut: PDataBlob): BOOL; stdcall; 1280 | 1281 | function CryptUnprotectData(pDataIn: PDataBlob; const szDataDescr: LPCWSTR; 1282 | pOptionalEntropy: PDataBlob; pvReserved: PVOID; 1283 | pPromptStruct: PCryptProtectPromptStruct; dwFlags: DWORD; 1284 | pDataOut: PDataBlob): BOOL; stdcall; 1285 | 1286 | function CryptProtectMemory(pData: LPVOID; cbData: DWORD; 1287 | dwFlags: DWORD): BOOL; stdcall; 1288 | function CryptUnprotectMemory(pData: LPVOID; cbData: DWORD; 1289 | dwFlags: DWORD): BOOL; stdcall; 1290 | 1291 | implementation 1292 | 1293 | function GetAlgClass(x: DWORD): DWORD; inline; 1294 | begin 1295 | Result := (x and (7 shl 13)); 1296 | end; 1297 | 1298 | function GetAlgType(x: DWORD): DWORD; inline; 1299 | begin 1300 | Result := (X and (15 shl 9)); 1301 | end; 1302 | 1303 | function GetAlgSid(x: DWORD): DWORD; inline; 1304 | begin 1305 | Result := x and 511; 1306 | end; 1307 | 1308 | function RCrypt_Succeeded(rt: BOOL): Boolean; inline; 1309 | begin 1310 | Result := rt = CRYPT_SUCCEED; 1311 | end; 1312 | 1313 | function RCrypt_Failed(rt: BOOL): Boolean; inline; 1314 | begin 1315 | Result := rt = CRYPT_FAILED; 1316 | end; 1317 | 1318 | const 1319 | advapi32 = 'Advapi32.dll'; 1320 | crypt32 = 'Crypt32.dll'; 1321 | 1322 | function CryptAcquireContextA; external advapi32; 1323 | function CryptAcquireContextW; external advapi32; 1324 | {$IFDEF UNICODE} 1325 | function CryptAcquireContext; external advapi32 name 'CryptAcquireContextW'; 1326 | {$ELSE} 1327 | function CryptAcquireContext; external advapi32 name 'CryptAcquireContextA'; 1328 | {$ENDIF} 1329 | function CryptReleaseContext; external advapi32; 1330 | function CryptGenKey; external advapi32; 1331 | function CryptDeriveKey; external advapi32; 1332 | function CryptDestroyKey; external advapi32; 1333 | function CryptSetKeyParam; external advapi32; 1334 | function CryptGetKeyParam; external advapi32; 1335 | function CryptSetHashParam; external advapi32; 1336 | function CryptGetHashParam; external advapi32; 1337 | function CryptSetProvParam; external advapi32; 1338 | function CryptGetProvParam; external advapi32; 1339 | function CryptGenRandom; external advapi32; 1340 | function CryptGetUserKey; external advapi32; 1341 | function CryptExportKey; external advapi32; 1342 | function CryptImportKey; external advapi32; 1343 | function CryptEncrypt; external advapi32; 1344 | function CryptDecrypt; external advapi32; 1345 | function CryptCreateHash; external advapi32; 1346 | function CryptHashData; external advapi32; 1347 | function CryptHashSessionKey; external advapi32; 1348 | function CryptDestroyHash; external advapi32; 1349 | function CryptSignHashA; external advapi32; 1350 | function CryptSignHashW; external advapi32; 1351 | {$IFDEF UNICODE} 1352 | function CryptSignHash; external advapi32 name 'CryptSignHashW'; 1353 | {$ELSE} 1354 | function CryptSignHash; external advapi32 name 'CryptSignHashA'; 1355 | {$ENDIF} 1356 | function CryptVerifySignatureA; external advapi32; 1357 | function CryptVerifySignatureW; external advapi32; 1358 | {$IFDEF UNICODE} 1359 | function CryptVerifySignature; external advapi32 name 'CryptVerifySignatureW'; 1360 | {$ELSE} 1361 | function CryptVerifySignature; external advapi32 name 'CryptVerifySignatureA'; 1362 | {$ENDIF} 1363 | function CryptSetProviderA; external advapi32; 1364 | function CryptSetProviderW; external advapi32; 1365 | {$IFDEF UNICODE} 1366 | function CryptSetProvider; external advapi32 name 'CryptSetProviderW'; 1367 | {$ELSE} 1368 | function CryptSetProvider; external advapi32 name 'CryptSetProviderA'; 1369 | {$ENDIF} 1370 | 1371 | 1372 | function CryptContextAddRef; external advapi32; 1373 | function CryptDuplicateHash; external advapi32; 1374 | function CryptDuplicateKey; external advapi32; 1375 | 1376 | function CryptProtectData; external crypt32; 1377 | function CryptUnprotectData; external crypt32; 1378 | 1379 | function CryptProtectMemory; external crypt32; 1380 | function CryptUnprotectMemory; external crypt32; 1381 | 1382 | end. 1383 | 1384 | 1385 | -------------------------------------------------------------------------------- /KeePassLib/KeePassLib.pas: -------------------------------------------------------------------------------- 1 | unit KeePassLib; 2 | 3 | {$SCOPEDENUMS ON} 4 | {$WARN SYMBOL_PLATFORM OFF} 5 | 6 | interface 7 | 8 | uses 9 | Winapi.Windows, System.Types, System.SysUtils, System.Classes, System.Hash, 10 | Vcl.Dialogs, System.UITypes, System.Generics.Collections; 11 | 12 | const 13 | DefaultTransformRounds = 6000; 14 | 15 | resourcestring 16 | SFailedToParseKeePassXml = 'Failed to parse KeePass XML.'; 17 | SArgument_ArrayCannotBeEmty = 'Array ''%s'' cannot be empty.'; 18 | SArgument_ArraysMustBeTheSameSize = 'Arrays must be the same size.'; 19 | 20 | type 21 | EKdbxError = class(Exception); 22 | EKdbxPasswordError = class(EKdbxError); 23 | 24 | TPwCompressionAlgorithm = (None, GZip); 25 | 26 | TCrsAlgorithm = (None, ArcFourVariant, Salsa20); 27 | 28 | TMemoryProtectionMode = (ProtectTitle, ProtectUserName, ProtectPassword, ProtectURL, ProtectNotes); 29 | 30 | TMemoryProtection = set of TMemoryProtectionMode; 31 | 32 | TKdbxFile = class 33 | private 34 | FStream: TStream; 35 | FOwnsStream: Boolean; 36 | FDataCipherUuid: TGUID; 37 | FCompressionAlgorithm: TPwCompressionAlgorithm; 38 | FMasterSeed: TBytes; 39 | FTransformSeed: TBytes; 40 | FTransformRounds: UInt64; 41 | FEncryptionIV: TBytes; 42 | FProtectedStreamKey: TBytes; 43 | FStreamStartBytes: TBytes; 44 | FInnerRandomStreamID: UInt32; 45 | FHashOfHeader: TBytes; 46 | FGenerator: string; 47 | FName: string; 48 | FNameChanged: TDateTime; 49 | FDescription: TStringList; 50 | FDescriptionChanged: TDateTime; 51 | FDefaultUserName: string; 52 | FDefaultUsernameChanged: TDateTime; 53 | FMaintenanceHistoryDays: Cardinal; 54 | FColor: TColor; 55 | FMasterKeyChanged: TDateTime; 56 | FMasterKeyChangeRec: Int64; 57 | FMasterKeyChangeForce: Int64; 58 | FMemoryProtection: TMemoryProtection; 59 | FCustomIcons: TObjectDictionary; 60 | FRecycleBinEnabled: Boolean; 61 | FRecycleBinUUID: TGUID; 62 | FRecycleBinChanged: TDateTime; 63 | FEntryTemplatesGroup: TGUID; 64 | FEntryTemplatesGroupChanged: TDateTime; 65 | FHistoryMaxItems: Integer; 66 | FHistoryMaxSize: Int64; 67 | FLastSelectedGroup: TGUID; 68 | FLastTopVisibleGroup: TGUID; 69 | FCustomData: TDictionary; 70 | FIsOpen: Boolean; 71 | function GetGenerator: string; 72 | procedure SetGenerator(const Value: string); 73 | function GetName: string; 74 | procedure SetName(const Value: string); 75 | function GetNameChanged: TDateTime; 76 | function GetDescription: TStringList; 77 | function GetDescriptionChanged: TDateTime; 78 | procedure OnDescriptionChanged(Sender: TObject); 79 | function GetDefaultUserName: string; 80 | procedure SetDefaultUserName(const Value: string); 81 | function GetDefaultUsernameChanged: TDateTime; 82 | function GetMaintenanceHistoryDays: Cardinal; 83 | procedure SetMaintenanceHistoryDays(const Value: Cardinal); 84 | function GetColor: TColor; 85 | procedure SetColor(const Value: TColor); 86 | function GetMasterKeyChanged: TDateTime; 87 | function GetMasterKeyChangeRec: Int64; 88 | procedure SetMasterKeyChangeRec(const Value: Int64); 89 | function GetMasterKeyChangeForce: Int64; 90 | procedure SetMasterKeyChangeForce(const Value: Int64); 91 | function GetMemoryProtection: TMemoryProtection; 92 | procedure SetMemoryProtection(const Value: TMemoryProtection); 93 | function GetCustomIcons: TObjectDictionary; 94 | function GetRecycleBinEnabled: Boolean; 95 | procedure SetRecycleBinEnabled(const Value: Boolean); 96 | function GetRecycleBinUUID: TGUID; 97 | procedure SetRecycleBinUUID(const Value: TGUID); 98 | function GetRecycleBinChanged: TDateTime; 99 | function GetEntryTemplatesGroup: TGUID; 100 | procedure SetEntryTemplatesGroup(const Value: TGUID); 101 | function GetEntryTemplatesGroupChanged: TDateTime; 102 | function GetHistoryMaxItems: Integer; 103 | procedure SetHistoryMaxItems(const Value: Integer); 104 | function GetHistoryMaxSize: Int64; 105 | procedure SetHistoryMaxSize(const Value: Int64); 106 | function GetLastSelectedGroup: TGUID; 107 | procedure SetLastSelectedGroup(const Value: TGUID); 108 | function GetLastTopVisibleGroup: TGUID; 109 | procedure SetLastTopVisibleGroup(const Value: TGUID); 110 | function GetCustomData: TDictionary; 111 | 112 | procedure ReadHeader; 113 | function ReadHeaderField: Boolean; 114 | function GetCompositeKey(const APassword: string): TBytes; 115 | function TransformKey(const CompositeKey: TBytes; Seed: TBytes; Rounds: UInt64): TBytes; 116 | function GetMasterKey(const MasterSeed: TBytes; const TransformedKey: TBytes): TBytes; 117 | function DecryptDataStream(const AMasterKey: TBytes): TStream; 118 | function GetSHA256WinCrypt(const Data: TBytes): TBytes; 119 | procedure Deserialize(const Stream: TStream); 120 | function GetIsOpen: Boolean; 121 | 122 | public 123 | property Generator: string read GetGenerator write SetGenerator; 124 | property Name: string read GetName write SetName; 125 | property NameChanged: TDateTime read GetNameChanged; 126 | property Description: TStringList read GetDescription; 127 | property DescriptionChanged: TDateTime read GetDescriptionChanged; 128 | property DefaultUserName: string read GetDefaultUserName write SetDefaultUserName; 129 | property DefaultUsernameChanged: TDateTime read GetDefaultUsernameChanged; 130 | property MaintenanceHistoryDays: Cardinal read GetMaintenanceHistoryDays write SetMaintenanceHistoryDays; 131 | property Color: TColor read GetColor write SetColor; 132 | property MasterKeyChanged: TDateTime read GetMasterKeyChanged; 133 | property MasterKeyChangeRec: Int64 read GetMasterKeyChangeRec write SetMasterKeyChangeRec; 134 | property MasterKeyChangeForce: Int64 read GetMasterKeyChangeForce write SetMasterKeyChangeForce; 135 | property TMemoryProtection: TMemoryProtection read GetMemoryProtection write SetMemoryProtection; 136 | property CustomIcons: TObjectDictionary read GetCustomIcons; 137 | property RecycleBinEnabled: Boolean read GetRecycleBinEnabled write SetRecycleBinEnabled; 138 | property RecycleBinUUID: TGUID read GetRecycleBinUUID write SetRecycleBinUUID; 139 | property RecycleBinChanged: TDateTime read GetRecycleBinChanged; 140 | property EntryTemplatesGroup: TGUID read GetEntryTemplatesGroup write SetEntryTemplatesGroup; 141 | property EntryTemplatesGroupChanged: TDateTime read GetEntryTemplatesGroupChanged; 142 | property HistoryMaxItems: Integer read GetHistoryMaxItems write SetHistoryMaxItems; 143 | property HistoryMaxSize: Int64 read GetHistoryMaxSize write SetHistoryMaxSize; 144 | property LastSelectedGroup: TGUID read GetLastSelectedGroup write SetLastSelectedGroup; 145 | property LastTopVisibleGroup: TGUID read GetLastTopVisibleGroup write SetLastTopVisibleGroup; 146 | property CustomData: TDictionary read GetCustomData; 147 | 148 | property IsOpen: Boolean read GetIsOpen; 149 | 150 | constructor Create; overload; 151 | constructor Create(const APassword: string; Stream: TStream; AOwnsStream: Boolean = False); overload; 152 | procedure LoadFromStream(const APassword: string; Stream: TStream; AOwnsStream: Boolean = True); 153 | procedure LoadFromFile(const APassword: string; const FileName: string; AOwnStream: Boolean = True); 154 | procedure Close; 155 | function GetSHA256(const Data: TBytes): TBytes; 156 | destructor Destroy; override; 157 | end; 158 | 159 | TXorredBuffer = class 160 | private 161 | FData: TBytes; 162 | FXorPad: TBytes; 163 | function GetLength: NativeInt; 164 | public 165 | property Length: NativeInt read GetLength; 166 | constructor Create(ProtectedData: TBytes; XorPad: TBytes); 167 | function ReadPlainText: TBytes; 168 | end; 169 | 170 | implementation 171 | 172 | uses 173 | idGlobal, idHashSha, idZLib, KeePassLib.Wincrypt, System.Security.Cryptography, 174 | Xml.XmlDoc, Xml.XmlDom, Xml.XmlIntf, System.Variants, System.DateUtils, 175 | Vcl.GraphUtil, System.NetEncoding, System.StrUtils; 176 | 177 | const 178 | kfEndOfHeader = 0; 179 | kfComment = 1; 180 | kfCipherID = 2; 181 | kfCompressionFlags = 3; 182 | kfMasterSeed = 4; 183 | kfTransformSeed = 5; 184 | kfTransformRounds = 6; 185 | kfEncryptionIV = 7; 186 | kfProtectedStreamKey = 8; 187 | kfStreamStartBytes = 9; 188 | kfInnerRandomStreamID = 10; 189 | 190 | type 191 | TAes256KeyBlob = record 192 | Header : TBlobHeader; 193 | KeySize : DWORD; 194 | KeyData : array[0..31] of Byte; 195 | end; 196 | 197 | TKdbxPayloadAreaBlockHeader = packed record 198 | ID : DWORD; 199 | Hash : packed array[0..31] of Byte; 200 | Size : DWORD; 201 | end; 202 | 203 | { TKdbxFile } 204 | 205 | procedure TKdbxFile.Close; 206 | var 207 | NowDate: TDateTime; 208 | begin 209 | FIsOpen := False; 210 | 211 | NowDate := Now; 212 | 213 | if FOwnsStream then 214 | FreeAndNil(FStream); 215 | FOwnsStream := False; 216 | 217 | FDataCipherUuid := TGUID.Empty; 218 | FCompressionAlgorithm := TPwCompressionAlgorithm.None; 219 | 220 | FillChar(FMasterSeed, Length(FMasterSeed), 0); 221 | FMasterSeed := nil; 222 | 223 | FillChar(FTransformSeed, Length(FTransformSeed), 0); 224 | FTransformSeed := nil; 225 | 226 | FTransformRounds := 6000; 227 | 228 | FillChar(FEncryptionIV, Length(FEncryptionIV), 0); 229 | FEncryptionIV := nil; 230 | 231 | FillChar(FProtectedStreamKey, Length(FProtectedStreamKey), 0); 232 | FProtectedStreamKey := nil; 233 | 234 | FillChar(FStreamStartBytes, Length(FStreamStartBytes), 0); 235 | FStreamStartBytes := nil; 236 | 237 | FInnerRandomStreamID := 0; 238 | 239 | FillChar(FHashOfHeader, Length(FHashOfHeader), 0); 240 | FHashOfHeader := nil; 241 | 242 | FGenerator := ''; 243 | FName := ''; 244 | FNameChanged := NowDate; 245 | FDescription.Clear; 246 | FDescriptionChanged := NowDate; 247 | FDefaultUserName := ''; 248 | FDefaultUsernameChanged := NowDate; 249 | FMaintenanceHistoryDays := 365; 250 | FColor := 0; 251 | FMasterKeyChanged := NowDate; 252 | FMasterKeyChangeRec := -1; 253 | FMasterKeyChangeForce := -1; 254 | FMemoryProtection := [TMemoryProtectionMode.ProtectPassword]; 255 | FCustomIcons.Clear; 256 | FRecycleBinEnabled := True; 257 | FRecycleBinUUID := TGUID.Empty; 258 | FRecycleBinChanged := NowDate; 259 | FEntryTemplatesGroup := TGUID.Empty; 260 | FEntryTemplatesGroupChanged := NowDate; 261 | FHistoryMaxItems := -1; 262 | FHistoryMaxSize := -1; 263 | FLastSelectedGroup := TGUID.Empty; 264 | FLastTopVisibleGroup := TGUID.Empty; 265 | FCustomData.Clear; 266 | end; 267 | 268 | constructor TKdbxFile.Create; 269 | var 270 | DataStream : TStream; 271 | CreationTime : TDateTime; 272 | begin 273 | inherited; 274 | 275 | CreationTime := Now; 276 | FNameChanged := CreationTime; 277 | FDescription := TStringList.Create; 278 | FDescription.OnChange := OnDescriptionChanged; 279 | FCustomIcons := TObjectDictionary.Create; 280 | FCustomData := TDictionary.Create; 281 | 282 | DataStream := nil; 283 | end; 284 | 285 | constructor TKdbxFile.Create(const APassword: string; Stream: TStream; AOwnsStream: Boolean); 286 | begin 287 | Create; 288 | 289 | LoadFromStream(APassword, Stream, AOwnsStream); 290 | end; 291 | 292 | procedure TKdbxFile.Deserialize(const Stream: TStream); 293 | 294 | /// 295 | /// Checks is given string is valid web color. 296 | /// 297 | function IsWebColorString(const WebColor: string): Boolean; 298 | var 299 | I: Integer; 300 | begin 301 | Result := False; 302 | 303 | if (Length(WebColor) < 6) or (Length(WebColor) > 7) then 304 | Exit; 305 | for I := 1 to Length(WebColor) do 306 | if not CharInSet(WebColor[I], ['#', 'a'..'f', 'A'..'F', '0'..'9']) then 307 | Exit; 308 | 309 | Result := True; 310 | end; 311 | 312 | 313 | var 314 | Xml: IXMLDocument; 315 | Root: IXMLNode; 316 | Meta: IXMLNode; 317 | MemoryProtectionNode: IXMLNode; 318 | vColor: OleVariant; 319 | OldNullStrictConvert: Boolean; 320 | begin 321 | Xml := TXMLDocument.Create(nil); 322 | Xml.LoadFromStream(Stream); 323 | Root := Xml.DocumentElement; 324 | Meta := Root.ChildNodes['Meta']; 325 | if (Meta = nil) or (Meta.NodeName <> 'Meta') then 326 | raise EKdbxError.Create(SFailedToParseKeePassXml); 327 | 328 | OldNullStrictConvert := NullStrictConvert; 329 | try 330 | // To avoid exceptions when OleVariant value is Null. 331 | NullStrictConvert := False; 332 | 333 | Generator := Meta.ChildValues['Generator']; 334 | FName := Meta.ChildValues['DatabaseName']; 335 | FNameChanged := ISO8601ToDate(Meta.ChildValues['DatabaseNameChanged']); 336 | FDescription.Text := Meta.ChildValues['DatabaseDescription']; 337 | FDescriptionChanged := ISO8601ToDate(Meta.ChildValues['DatabaseDescriptionChanged']); 338 | FDefaultUserName := Meta.ChildValues['DefaultUserName']; 339 | FDefaultUsernameChanged := ISO8601ToDate(Meta.ChildValues['DefaultUserNameChanged']); 340 | FMaintenanceHistoryDays := StrToUInt64Def(Meta.ChildValues['MaintenanceHistoryDays'], 365); 341 | vColor := Meta.ChildValues['Color']; 342 | // To avoid exception when string is empty or in invalid format 343 | if IsWebColorString(vColor) then 344 | FColor := WebColorStrToColor(vColor); 345 | 346 | FMasterKeyChanged := ISO8601ToDate(Meta.ChildValues['MasterKeyChanged']); 347 | FMasterKeyChangeRec := StrToIntDef(Meta.ChildValues['MasterKeyChanged'], -1); 348 | FMasterKeyChangeForce := StrToInt64Def(Meta.ChildValues['MasterKeyChangeForce'], -1); 349 | 350 | MemoryProtectionNode := Meta.ChildNodes['MemoryProtection']; 351 | if MemoryProtectionNode <> nil then 352 | begin 353 | if StrToBoolDef(MemoryProtectionNode.ChildValues['ProtectTitle'], False) then 354 | Include(FMemoryProtection, TMemoryProtectionMode.ProtectTitle); 355 | if StrToBoolDef(MemoryProtectionNode.ChildValues['ProtectUserName'], False) then 356 | Include(FMemoryProtection, TMemoryProtectionMode.ProtectUserName); 357 | if StrToBoolDef(MemoryProtectionNode.ChildValues['ProtectPassword'], True) then 358 | Include(FMemoryProtection, TMemoryProtectionMode.ProtectPassword); 359 | if StrToBoolDef(MemoryProtectionNode.ChildValues['ProtectURL'], False) then 360 | Include(FMemoryProtection, TMemoryProtectionMode.ProtectURL); 361 | if StrToBoolDef(MemoryProtectionNode.ChildValues['ProtectNotes'], False) then 362 | Include(FMemoryProtection, TMemoryProtectionMode.ProtectNotes); 363 | end; 364 | MemoryProtectionNode := nil; 365 | 366 | FRecycleBinEnabled := StrToBoolDef(Meta.ChildValues['RecycleBinEnabled'], True); 367 | FRecycleBinUUID := TGUID.Create(TNetEncoding.Base64.DecodeStringToBytes(Meta.ChildValues['RecycleBinUUID'])); 368 | FRecycleBinChanged := ISO8601ToDate(Meta.ChildValues['RecycleBinChanged']); 369 | FEntryTemplatesGroup := TGUID.Create(TNetEncoding.Base64.DecodeStringToBytes(Meta.ChildValues['EntryTemplatesGroup'])); 370 | FEntryTemplatesGroupChanged := ISO8601ToDate(Meta.ChildValues['EntryTemplatesGroupChanged']); 371 | FHistoryMaxItems := StrToIntDef(Meta.ChildValues['HistoryMaxItems'], -1); 372 | FHistoryMaxSize := StrToIntDef(Meta.ChildValues['HistoryMaxSize'], -1); 373 | FLastSelectedGroup := TGUID.Create(TNetEncoding.Base64.DecodeStringToBytes(Meta.ChildValues['LastSelectedGroup'])); 374 | FLastTopVisibleGroup := TGUID.Create(TNetEncoding.Base64.DecodeStringToBytes(Meta.ChildValues['LastTopVisibleGroup'])); 375 | finally 376 | NullStrictConvert := OldNullStrictConvert; 377 | end; 378 | end; 379 | 380 | destructor TKdbxFile.Destroy; 381 | begin 382 | FDescription.Free; 383 | FCustomIcons.Free; 384 | FCustomData.Free; 385 | 386 | if FOwnsStream then 387 | FStream.Free; 388 | 389 | inherited; 390 | end; 391 | 392 | function TKdbxFile.GetColor: TColor; 393 | begin 394 | Result := FColor; 395 | end; 396 | 397 | function TKdbxFile.GetCompositeKey(const APassword: string): TBytes; 398 | var 399 | PasswordUTF8Bytes: TBytes; 400 | PasswordHash : TBytes; 401 | Sha256: TSHA256CryptoServiceProvider; 402 | begin 403 | // Calculate hash of password 404 | PasswordUTF8Bytes := TEncoding.UTF8.GetBytes(APassword); 405 | 406 | Sha256 := TSHA256CryptoServiceProvider.Create; 407 | try 408 | PasswordHash := Sha256.ComputeHash(PasswordUTF8Bytes); 409 | Result := Sha256.ComputeHash(PasswordHash); 410 | finally 411 | Sha256.Free; 412 | end; 413 | end; 414 | 415 | function TKdbxFile.GetCustomData: TDictionary; 416 | begin 417 | Result := FCustomData; 418 | end; 419 | 420 | function TKdbxFile.GetCustomIcons: TObjectDictionary; 421 | begin 422 | Result := FCustomIcons; 423 | end; 424 | 425 | function TKdbxFile.GetDefaultUserName: string; 426 | begin 427 | Result := FDefaultUserName; 428 | end; 429 | 430 | function TKdbxFile.GetDefaultUsernameChanged: TDateTime; 431 | begin 432 | Result := FDefaultUsernameChanged; 433 | end; 434 | 435 | function TKdbxFile.GetDescription: TStringList; 436 | begin 437 | Result := FDescription; 438 | end; 439 | 440 | function TKdbxFile.GetDescriptionChanged: TDateTime; 441 | begin 442 | Result := FDescriptionChanged; 443 | end; 444 | 445 | function TKdbxFile.GetEntryTemplatesGroup: TGUID; 446 | begin 447 | Result := FEntryTemplatesGroup; 448 | end; 449 | 450 | function TKdbxFile.GetEntryTemplatesGroupChanged: TDateTime; 451 | begin 452 | Result := FEntryTemplatesGroupChanged; 453 | end; 454 | 455 | function TKdbxFile.GetGenerator: string; 456 | begin 457 | Result := FGenerator; 458 | end; 459 | 460 | function TKdbxFile.GetHistoryMaxItems: Integer; 461 | begin 462 | Result := FHistoryMaxItems; 463 | end; 464 | 465 | function TKdbxFile.GetHistoryMaxSize: Int64; 466 | begin 467 | Result := FHistoryMaxSize; 468 | end; 469 | 470 | function TKdbxFile.GetIsOpen: Boolean; 471 | begin 472 | Result := FIsOpen; 473 | end; 474 | 475 | function TKdbxFile.GetLastSelectedGroup: TGUID; 476 | begin 477 | Result := FLastSelectedGroup; 478 | end; 479 | 480 | function TKdbxFile.GetLastTopVisibleGroup: TGUID; 481 | begin 482 | Result := FLastTopVisibleGroup; 483 | end; 484 | 485 | function TKdbxFile.GetMaintenanceHistoryDays: Cardinal; 486 | begin 487 | Result := FMaintenanceHistoryDays; 488 | end; 489 | 490 | function TKdbxFile.GetMasterKey(const MasterSeed, 491 | TransformedKey: TBytes): TBytes; 492 | var 493 | ConcatKey : TBytes; 494 | Sha256: TSHA256CryptoServiceProvider; 495 | begin 496 | if not Assigned(TransformedKey) then 497 | raise EKdbxError.Create(''); 498 | if not Assigned(MasterSeed) then 499 | raise EKdbxError.Create(''); 500 | if Length(TransformedKey) <> 32 then 501 | raise EKdbxError.Create(''); 502 | if Length(MasterSeed) <> 32 then 503 | raise EKdbxError.Create(''); 504 | 505 | ConcatKey := TransformedKey + MasterSeed; 506 | 507 | 508 | Result := nil; 509 | 510 | Sha256 := TSHA256CryptoServiceProvider.Create; 511 | try 512 | Result := Sha256.ComputeHash(ConcatKey); 513 | finally 514 | Sha256.Free; 515 | end; 516 | end; 517 | 518 | function TKdbxFile.GetMasterKeyChanged: TDateTime; 519 | begin 520 | Result := FMasterKeyChanged; 521 | end; 522 | 523 | function TKdbxFile.GetMasterKeyChangeForce: Int64; 524 | begin 525 | Result := FMasterKeyChangeForce; 526 | end; 527 | 528 | function TKdbxFile.GetMasterKeyChangeRec: Int64; 529 | begin 530 | Result := FMasterKeyChangeRec; 531 | end; 532 | 533 | function TKdbxFile.GetName: string; 534 | begin 535 | Result := FName; 536 | end; 537 | 538 | function TKdbxFile.GetNameChanged: TDateTime; 539 | begin 540 | Result := FNameChanged; 541 | end; 542 | 543 | function TKdbxFile.GetRecycleBinChanged: TDateTime; 544 | begin 545 | Result := FRecycleBinChanged; 546 | end; 547 | 548 | function TKdbxFile.GetRecycleBinEnabled: Boolean; 549 | begin 550 | Result := FRecycleBinEnabled; 551 | end; 552 | 553 | function TKdbxFile.GetRecycleBinUUID: TGUID; 554 | begin 555 | Result := FRecycleBinUUID; 556 | end; 557 | 558 | function TKdbxFile.GetSHA256(const Data: TBytes): TBytes; 559 | begin 560 | Result := GetSHA256WinCrypt(Data); 561 | end; 562 | 563 | function TKdbxFile.GetSHA256WinCrypt(const Data: TBytes): TBytes; 564 | var 565 | hProv : HCRYPTPROV; 566 | hHash : HCRYPTHASH; 567 | dwDataLen : DWORD; 568 | dwHashSize: DWORD; 569 | begin 570 | Result := nil; 571 | 572 | try 573 | Win32Check(CryptAcquireContext(hProv, nil, nil, PROV_RSA_AES, CRYPT_VERIFYCONTEXT)); 574 | Win32Check(CryptCreateHash(hProv, CALG_SHA_256, 0, 0, hHash)); 575 | dwDataLen := Length(Data); 576 | Win32Check(CryptHashData(hHash, Data[0], dwDataLen, 0)); 577 | try 578 | dwDataLen := SizeOf(DWORD); 579 | Win32Check(CryptGetHashParam(hHash, HP_HASHSIZE, dwHashSize, dwDataLen, 0)); 580 | SetLength(Result, dwHashSize); 581 | Win32Check(CryptGetHashParam(hHash, HP_HASHVAL, Result[0], dwHashSize, 0)); 582 | except 583 | Result := nil; 584 | end; 585 | finally 586 | if hHash <> 0 then 587 | CryptDestroyHash(hHash); 588 | if hProv <> 0 then 589 | CryptReleaseContext(hProv, 0); 590 | end; 591 | end; 592 | 593 | procedure TKdbxFile.LoadFromFile(const APassword, FileName: string; 594 | AOwnStream: Boolean); 595 | var 596 | FS: TFileStream; 597 | begin 598 | Close; 599 | FS := TFileStream.Create(FileName, fmOpenRead); 600 | LoadFromStream(APassword, FS, True); 601 | end; 602 | 603 | procedure TKdbxFile.LoadFromStream(const APassword: string; Stream: TStream; 604 | AOwnsStream: Boolean); 605 | var 606 | CompositeKey : TBytes; 607 | TransformedKey : TBytes; 608 | MasterKey : TBytes; 609 | DataStream : TStream; 610 | begin 611 | try 612 | Close; 613 | DataStream := nil; 614 | 615 | if not Assigned(Stream) then 616 | raise EArgumentNilException.Create('Input stream is nil!'); 617 | 618 | FStream := Stream; 619 | FOwnsStream := AOwnsStream; 620 | 621 | if APassword = '' then 622 | raise EKdbxPasswordError.Create('Password is empty!'); 623 | 624 | CompositeKey := GetCompositeKey(APassword); 625 | 626 | ReadHeader; 627 | 628 | TransformedKey := TransformKey(CompositeKey, FTransformSeed, FTransformRounds); 629 | 630 | MasterKey := GetMasterKey(TransformedKey, FMasterSeed); 631 | 632 | try 633 | DataStream := DecryptDataStream(MasterKey); 634 | 635 | Deserialize(DataStream); 636 | finally 637 | DataStream.Free; 638 | end; 639 | 640 | FIsOpen := True; 641 | 642 | except 643 | Close; 644 | raise; 645 | end; 646 | end; 647 | 648 | function TKdbxFile.GetMemoryProtection: TMemoryProtection; 649 | begin 650 | Result := FMemoryProtection; 651 | end; 652 | 653 | procedure TKdbxFile.OnDescriptionChanged(Sender: TObject); 654 | begin 655 | FDescriptionChanged := Now; 656 | end; 657 | 658 | procedure TKdbxFile.ReadHeader; 659 | const 660 | // File identifier, first 32-bit value. 661 | FileSignature1 = $9AA2D903; 662 | // File identifier, second 32-bit value. 663 | FileSignature2 = $B54BFB67; 664 | // KeePass 1.x signature 665 | FileSignatureOld1 = $9AA2D903; 666 | FileSignatureOld2 = $B54BFB65; 667 | // KeePass 2.x pre-release (alpha and beta) signature 668 | FileSignaturePreRelease1 = $9AA2D903; 669 | FileSignaturePreRelease2 = $B54BFB66; 670 | 671 | FileVersion32 = $00030001; 672 | FileVersionCriticalMask = $FFFF0000; 673 | var 674 | Sig1, Sig2: UInt32; 675 | BytesRead: Longint; 676 | Version: UInt32; 677 | HeaderSize: Int64; 678 | Sha256: TIdHashSHA256; 679 | Sha256Bytes: TIdBytes; 680 | begin 681 | Assert(Assigned(FStream)); 682 | 683 | BytesRead := FStream.Read(Sig1, SizeOf(Sig1)); 684 | if BytesRead <> SizeOf(Sig1) then 685 | raise EKdbxError.Create('Kdbx file header parse error: Sig1 field size <> 4 bytes.'); 686 | BytesRead := FStream.Read(Sig2, SizeOf(Sig2)); 687 | if BytesRead <> SizeOf(Sig2) then 688 | raise EKdbxError.Create('Kdbx file header parse error: Sig2 field size <> 4 bytes.'); 689 | 690 | 691 | // Check if Kdbx file is of unsupported 1.x version 692 | if (Sig1 = FileSignatureOld1) and (Sig2 = FileSignatureOld2) then 693 | raise EKdbxError.Create('KeePass 1.x files are not supported.'); 694 | 695 | // Check if Kdbx is supported 2.x 696 | if ((Sig1 = FileSignature1) and (Sig2 = FileSignature2)) or 697 | ((Sig1 = FileSignaturePreRelease1) and (Sig2 = FileSignaturePreRelease2)) then 698 | begin 699 | end 700 | else 701 | begin 702 | raise EKdbxError.Create('File is not valid KeePass 2.x file'); 703 | end; 704 | 705 | // Check version 706 | BytesRead := FStream.Read(Version, SizeOf(Version)); 707 | if BytesRead <> SizeOf(Version) then 708 | raise EKdbxError.Create('Kdbx file header parse error: Version field size <> 4 bytes.'); 709 | if (Version and FileVersionCriticalMask) > (FileVersion32 and FileVersionCriticalMask) then 710 | raise EKdbxError.Create('Unsupported KeePass 2.x file.'); 711 | 712 | while ReadHeaderField do 713 | begin 714 | 715 | end; 716 | 717 | // Calculate header hash 718 | 719 | HeaderSize := FStream.Position; 720 | Sha256 := nil; 721 | try 722 | Sha256 := TIdHashSHA256.Create; 723 | Sha256Bytes := Sha256.HashStream(FStream, 0, HeaderSize); 724 | // Stupid TIdBytes... 725 | SetLength(FHashOfHeader, Length(Sha256Bytes)); 726 | Move(Sha256Bytes, FHashOfHeader, Length(Sha256Bytes)); 727 | FStream.Position := HeaderSize; 728 | 729 | finally 730 | Sha256.Free; 731 | end; 732 | 733 | end; 734 | 735 | function TKdbxFile.ReadHeaderField: Boolean; 736 | var 737 | BytesRead: LongInt; 738 | FieldID: Byte; 739 | FieldSize: Word; 740 | FieldData: TBytes; 741 | begin 742 | BytesRead := FStream.Read(FieldID, SizeOf(FieldID)); 743 | if BytesRead <> SizeOf(FieldID) then 744 | raise EKdbxError.Create('Kdbx file header parse error: field ID read failed.'); 745 | BytesRead := FStream.Read(FieldSize, SizeOf(FieldSize)); 746 | if BytesRead <> SizeOf(FieldSize) then 747 | raise EKdbxError.Create('Kdbx file header parse error: field size read failed.'); 748 | SetLength(FieldData, FieldSize); 749 | BytesRead := FStream.Read(FieldData[0], FieldSize); 750 | if BytesRead <> FieldSize then 751 | raise EKdbxError.Create('Kdbx file header parse error: field data read failed.'); 752 | 753 | Result := True; 754 | case FieldID of 755 | kfEndOfHeader: 756 | begin 757 | Result := False; 758 | end; 759 | kfCipherID: 760 | begin 761 | FDataCipherUuid := TGUID.Create(FieldData); 762 | end; 763 | kfCompressionFlags: 764 | begin 765 | if FieldSize <> 4 then 766 | raise EKdbxError.Create('Kdbx file header parse error: CompressionAlgorithm field size <> 4 bytes.'); 767 | case FieldData[0] of 768 | 0: FCompressionAlgorithm := TPwCompressionAlgorithm.None; 769 | 1: FCompressionAlgorithm := TPwCompressionAlgorithm.GZip; 770 | else 771 | raise EKdbxError.Create('Kdbx file header parse error: unknown compression algorithm.'); 772 | end; 773 | end; 774 | kfMasterSeed: 775 | begin 776 | FMasterSeed := Copy(FieldData, 0, FieldSize); 777 | end; 778 | kfTransformSeed: 779 | begin 780 | FTransformSeed := Copy(FieldData, 0, FieldSize); 781 | end; 782 | kfTransformRounds: 783 | begin 784 | if FieldSize <> SizeOf(FTransformRounds) then 785 | raise EKdbxError.Create('Kdbx file header parse error: TransformRounds field size <> 4 bytes.'); 786 | Move(FieldData[0], FTransformRounds, SizeOf(FTransformRounds)); 787 | end; 788 | kfEncryptionIV: 789 | begin 790 | FEncryptionIV := Copy(FieldData, 0, FieldSize); 791 | end; 792 | kfProtectedStreamKey: 793 | begin 794 | FProtectedStreamKey := Copy(FieldData, 0, FieldSize); 795 | end; 796 | kfStreamStartBytes: 797 | begin 798 | FStreamStartBytes := Copy(FieldData, 0, FieldSize); 799 | end; 800 | kfInnerRandomStreamID: 801 | begin 802 | if FieldSize <> 4 then 803 | raise EKdbxError.Create('Kdbx file header parse error: InnerRandomStreamID field size <> 4 bytes.'); 804 | Move(FieldData[0], FInnerRandomStreamID, SizeOf(FInnerRandomStreamID)); 805 | end 806 | else 807 | // Unknown, but correct fields? 808 | begin 809 | end; 810 | end; 811 | end; 812 | 813 | procedure TKdbxFile.SetColor(const Value: TColor); 814 | begin 815 | FColor := Value; 816 | end; 817 | 818 | procedure TKdbxFile.SetDefaultUserName(const Value: string); 819 | begin 820 | if Value <> FDefaultUserName then 821 | begin 822 | FDefaultUserName := Value; 823 | FDefaultUsernameChanged := Now; 824 | end; 825 | end; 826 | 827 | procedure TKdbxFile.SetEntryTemplatesGroup(const Value: TGUID); 828 | begin 829 | FEntryTemplatesGroup := Value; 830 | end; 831 | 832 | procedure TKdbxFile.SetGenerator(const Value: string); 833 | begin 834 | FGenerator := Value; 835 | end; 836 | 837 | procedure TKdbxFile.SetHistoryMaxItems(const Value: Integer); 838 | begin 839 | FHistoryMaxItems := Value; 840 | end; 841 | 842 | procedure TKdbxFile.SetHistoryMaxSize(const Value: Int64); 843 | begin 844 | FHistoryMaxSize := Value; 845 | end; 846 | 847 | procedure TKdbxFile.SetLastSelectedGroup(const Value: TGUID); 848 | begin 849 | FLastSelectedGroup := Value; 850 | end; 851 | 852 | procedure TKdbxFile.SetLastTopVisibleGroup(const Value: TGUID); 853 | begin 854 | FLastTopVisibleGroup := Value; 855 | end; 856 | 857 | procedure TKdbxFile.SetMaintenanceHistoryDays(const Value: Cardinal); 858 | begin 859 | FMaintenanceHistoryDays := Value; 860 | end; 861 | 862 | procedure TKdbxFile.SetMasterKeyChangeForce(const Value: Int64); 863 | begin 864 | FMasterKeyChangeForce := Value; 865 | end; 866 | 867 | procedure TKdbxFile.SetMasterKeyChangeRec(const Value: Int64); 868 | begin 869 | FMasterKeyChangeRec := Value; 870 | end; 871 | 872 | procedure TKdbxFile.SetName(const Value: string); 873 | begin 874 | if Value <> FName then 875 | begin 876 | FName := Value; 877 | FNameChanged := Now; 878 | end; 879 | end; 880 | 881 | procedure TKdbxFile.SetRecycleBinEnabled(const Value: Boolean); 882 | begin 883 | FRecycleBinEnabled := Value; 884 | end; 885 | 886 | procedure TKdbxFile.SetRecycleBinUUID(const Value: TGUID); 887 | begin 888 | FRecycleBinUUID := Value; 889 | end; 890 | 891 | procedure TKdbxFile.SetMemoryProtection(const Value: TMemoryProtection); 892 | begin 893 | FMemoryProtection := Value; 894 | end; 895 | 896 | function TKdbxFile.DecryptDataStream(const AMasterKey: TBytes): TStream; 897 | 898 | function DecryptPayloadArea(const InputStream: TStream; hKey: HCRYPTKEY): TMemoryStream; 899 | var 900 | DecryptedStream: TMemoryStream; 901 | BytesRead : DWORD; 902 | ReadBuffer : packed array[0..65536 - 1] of Byte; 903 | begin 904 | Assert(InputStream <> nil); 905 | Assert(hKey <> 0); 906 | 907 | Result := nil; 908 | 909 | DecryptedStream := TMemoryStream.Create; 910 | try 911 | while True do 912 | begin 913 | BytesRead := InputStream.Read(ReadBuffer[0], SizeOf(ReadBuffer)); 914 | if BytesRead = 0 then 915 | Break; 916 | 917 | if BytesRead = SizeOf(ReadBuffer) then 918 | Win32Check(CryptDecrypt(hKey, 0, False, 0, ReadBuffer[0], BytesRead)) 919 | else 920 | Win32Check(CryptDecrypt(hKey, 0, True, 0, ReadBuffer[0], BytesRead)); 921 | 922 | DecryptedStream.Write(ReadBuffer[0], BytesRead); 923 | end; 924 | 925 | DecryptedStream.Position := 0; 926 | Result := DecryptedStream; 927 | except 928 | DecryptedStream.Free; 929 | end; 930 | end; 931 | 932 | function DecompressPayloadArea(const InputStream: TStream): TMemoryStream; 933 | var 934 | MemoryStream: TMemoryStream; 935 | begin 936 | Assert(InputStream <> nil); 937 | 938 | if InputStream.Position <> 0 then 939 | InputStream.Position := 0; 940 | 941 | MemoryStream := TMemoryStream.Create; 942 | try 943 | DecompressStream(InputStream, MemoryStream); 944 | Result := MemoryStream; 945 | except 946 | MemoryStream.Free; 947 | Result := nil; 948 | end; 949 | end; 950 | 951 | var 952 | hProv : HCRYPTPROV; 953 | hKey : HCRYPTKEY; 954 | KeyBlob : TAes256KeyBlob; 955 | BlockHeader : TKdbxPayloadAreaBlockHeader; 956 | AesMode : DWORD; 957 | 958 | BytesRead : DWORD; 959 | ReadBuffer : packed array[0..65536 - 1] of Byte; 960 | I : NativeInt; 961 | StartBytes : TBytes; 962 | StartBytesFail : Boolean; 963 | DecryptedStream : TMemoryStream; 964 | BlockData : TBytes; 965 | BlockDataHash : TBytes; 966 | DeblockedStream : TMemoryStream; 967 | DecompressedStream: TMemoryStream; 968 | begin 969 | Result := nil; 970 | 971 | try 972 | Win32Check(CryptAcquireContext(hProv, nil, nil, PROV_RSA_AES, CRYPT_VERIFYCONTEXT)); 973 | FillChar(KeyBlob, SizeOf(TAes256KeyBlob), 0); 974 | KeyBlob.Header.bType := PLAINTEXTKEYBLOB; 975 | KeyBlob.Header.bVersion := CUR_BLOB_VERSION; 976 | KeyBlob.Header.aiKeyAlg := CALG_AES_256; 977 | KeyBlob.KeySize := 32; 978 | Move(AMasterKey[0], KeyBlob.KeyData[0], 32); 979 | FillChar(AMasterKey[0], Length(AMasterKey), 0); 980 | Win32Check(CryptImportKey(hProv, KeyBlob, SizeOf(TAes256KeyBlob), 0, 0, hKey)); 981 | 982 | Win32Check(CryptSetKeyParam(hKey, KP_IV, FEncryptionIV[0], 0)); 983 | AesMode := CRYPT_MODE_CBC; 984 | Win32Check(CryptSetKeyParam(hKey, KP_MODE, AesMode, 0)); 985 | 986 | // check pattern 987 | SetLength(StartBytes, Length(FStreamStartBytes)); 988 | BytesRead := FStream.Read(ReadBuffer[0], Length(StartBytes)); 989 | Win32Check(CryptDecrypt(hKey, 0, False, 0, ReadBuffer[0], BytesRead)); 990 | Move(ReadBuffer[0], StartBytes[0], Length(StartBytes)); 991 | 992 | StartBytesFail := False; 993 | for I := 0 to Length(StartBytes) - 1 do 994 | if FStreamStartBytes[I] <> ReadBuffer[I] then 995 | begin 996 | StartBytesFail := True; 997 | Break; 998 | end; 999 | if StartBytesFail then 1000 | raise EKdbxPasswordError.Create('Password incorrect!'); 1001 | 1002 | // Decrypting data 1003 | DecryptedStream := nil; 1004 | try 1005 | DecryptedStream := DecryptPayloadArea(FStream, hKey); 1006 | if DecryptedStream = nil then 1007 | raise EKdbxError.Create('Failed to decrypt data!'); 1008 | 1009 | // Now data is decrypted, but splitted to blocks 1010 | // We must check block header of TKdbxPayloadAreaBlockHeader type, get 1011 | // its length compare its hash and copy to Deblocked stream. 1012 | DeblockedStream := nil; 1013 | try 1014 | DeblockedStream := TMemoryStream.Create; 1015 | 1016 | while True do 1017 | begin 1018 | BytesRead := DecryptedStream.Read(BlockHeader, SizeOf(BlockHeader)); 1019 | // Final block with data size = 0 1020 | if BlockHeader.Size = 0 then 1021 | Break; 1022 | 1023 | // Read block data 1024 | SetLength(BlockData, BlockHeader.Size); 1025 | BytesRead := DecryptedStream.Read(BlockData, BlockHeader.Size); 1026 | 1027 | // Check block hash 1028 | BlockDataHash := GetSHA256(BlockData); 1029 | if not CompareMem(@BlockHeader.Hash[0], @BlockDataHash[0], Length(BlockHeader.Hash)) then 1030 | raise EKdbxError.Create('Kdbx file is damaged, data block hash is incorrect.'); 1031 | 1032 | // Write pure data 1033 | DeblockedStream.Write(BlockData[0], Length(BlockData)); 1034 | DeblockedStream.Position := 0; 1035 | end; 1036 | FreeAndNil(DecryptedStream); 1037 | 1038 | // Last step, if stream is compressed we must decompress it 1039 | if FCompressionAlgorithm = TPwCompressionAlgorithm.None then 1040 | begin 1041 | Result := DeblockedStream; 1042 | end 1043 | else 1044 | begin 1045 | DecompressedStream := DecompressPayloadArea(DeblockedStream); 1046 | 1047 | if DecompressedStream = nil then 1048 | begin 1049 | raise EKdbxError.Create('Failed to decompress stream.'); 1050 | end; 1051 | 1052 | DecompressedStream.Position := 0; 1053 | Result := DecompressedStream; 1054 | end; 1055 | 1056 | except 1057 | DeblockedStream.Free; 1058 | end; 1059 | 1060 | finally 1061 | DecryptedStream.Free; 1062 | end; 1063 | 1064 | finally 1065 | if hKey <> 0 then 1066 | CryptDestroyKey(hKey); 1067 | if hProv <> 0 then 1068 | CryptReleaseContext(hProv, 0); 1069 | end; 1070 | 1071 | end; 1072 | 1073 | function TKdbxFile.TransformKey(const CompositeKey: TBytes; Seed: TBytes; 1074 | Rounds: UInt64): TBytes; 1075 | var 1076 | hProv : HCRYPTPROV; 1077 | hKey : HCRYPTKEY; 1078 | hHash : HCRYPTHASH; 1079 | KeyBlob : TAes256KeyBlob; 1080 | AesMode : DWORD; 1081 | TransformedKey : array[0..31] of Byte; 1082 | i : UInt64; 1083 | dwDataLen : DWORD; 1084 | begin 1085 | if not Assigned(CompositeKey) then 1086 | raise EKdbxError.Create('CompositeKey argument cannot be nil!'); 1087 | if Length(CompositeKey) <> 32 then 1088 | raise EKdbxError.Create('CompositeKey size <> 32 bit!'); 1089 | if not Assigned(Seed) then 1090 | raise EKdbxError.Create('Seed argument cannot be nil!'); 1091 | if Length(Seed) <> 32 then 1092 | raise EKdbxError.Create('Seed size <> 32 bit!'); 1093 | 1094 | Result := nil; 1095 | hProv := 0; 1096 | hKey := 0; 1097 | hHash := 0; 1098 | 1099 | try 1100 | Win32Check(CryptAcquireContext(hProv, nil, nil, PROV_RSA_AES, CRYPT_VERIFYCONTEXT)); 1101 | FillChar(KeyBlob, SizeOf(TAes256KeyBlob), 0); 1102 | KeyBlob.Header.bType := PLAINTEXTKEYBLOB; 1103 | KeyBlob.Header.bVersion := CUR_BLOB_VERSION; 1104 | KeyBlob.Header.aiKeyAlg := CALG_AES_256; 1105 | KeyBlob.KeySize := 32; 1106 | Move(FTransformSeed[0], KeyBlob.KeyData[0], 32); 1107 | Win32Check(CryptImportKey(hProv, KeyBlob, SizeOf(TAes256KeyBlob), 0, 0, hKey)); 1108 | AesMode := CRYPT_MODE_ECB; 1109 | Win32Check(CryptSetKeyParam(hKey, KP_MODE, AesMode, 0)); 1110 | Move(CompositeKey[0], TransformedKey[0], 32); 1111 | dwDataLen := 16; 1112 | for i := 0 to Rounds - 1 do 1113 | begin 1114 | Win32Check(CryptEncrypt(hKey, 0, False, 0, TransformedKey[0], dwDataLen, 16)); 1115 | Win32Check(CryptEncrypt(hKey, 0, False, 0, TransformedKey[16], dwDataLen, 16)); 1116 | end; 1117 | 1118 | try 1119 | Win32Check(CryptCreateHash(hProv, CALG_SHA_256, 0, 0, hHash)); 1120 | Win32Check(CryptHashData(hHash, TransformedKey[0], Length(TransformedKey), 0)); 1121 | dwDataLen := 32; 1122 | CryptGetHashParam(hHash, HP_HASHVAL, TransformedKey[0], dwDataLen, 0); 1123 | SetLength(Result, 32); 1124 | Move(TransformedKey[0], Result[0], 32); 1125 | finally 1126 | CryptDestroyHash(hHash); 1127 | end; 1128 | 1129 | finally 1130 | if hKey <> 0 then 1131 | CryptDestroyKey(hKey); 1132 | if hProv <> 0 then 1133 | CryptReleaseContext(hProv, 0); 1134 | end; 1135 | end; 1136 | 1137 | { TXorredBuffer } 1138 | 1139 | constructor TXorredBuffer.Create(ProtectedData, XorPad: TBytes); 1140 | begin 1141 | if ProtectedData = nil then 1142 | raise EArgumentNilException.Create('ProtectedData'); 1143 | if System.Length(ProtectedData) <= 0 then 1144 | raise EArgumentException.Create(Format(SArgument_ArrayCannotBeEmty, 1145 | ['ProtectedData'])); 1146 | if XorPad = nil then 1147 | raise EArgumentNilException.Create('XorPad'); 1148 | 1149 | if System.Length(ProtectedData) <> System.Length(XorPad) then 1150 | raise EArgumentException.Create(SArgument_ArraysMustBeTheSameSize); 1151 | 1152 | FData := ProtectedData; 1153 | FXorPad := XorPad; 1154 | end; 1155 | 1156 | function TXorredBuffer.GetLength: NativeInt; 1157 | begin 1158 | Result := System.Length(FData); 1159 | end; 1160 | 1161 | function TXorredBuffer.ReadPlainText: TBytes; 1162 | var 1163 | Plain: TBytes; 1164 | I: NativeInt; 1165 | begin 1166 | Plain := Copy(FData); 1167 | 1168 | for I := 0 to System.Length(Plain) - 1 do 1169 | Plain[i] := FData[i] xor FXorPad[i]; 1170 | 1171 | Result := Plain; 1172 | end; 1173 | 1174 | end. 1175 | -------------------------------------------------------------------------------- /KeePassLib/System.Security.Cryptography.pas: -------------------------------------------------------------------------------- 1 | { This file is part of KeePass4D. 2 | 3 | KeePass4D is free software: you can redistribute it and/or modify 4 | it under the terms of the GNU General Public License as published by 5 | the Free Software Foundation, either version 3 of the License, or 6 | (at your option) any later version. 7 | 8 | KeePass4D is distributed in the hope that it will be useful, 9 | but WITHOUT ANY WARRANTY; without even the implied warranty of 10 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 11 | GNU General Public License for more details. 12 | 13 | You should have received a copy of the GNU General Public License 14 | along with KeePass4D. If not, see . } 15 | 16 | unit System.Security.Cryptography; 17 | 18 | interface 19 | 20 | {$WARN SYMBOL_PLATFORM OFF} 21 | 22 | uses 23 | Winapi.Windows, System.SysUtils, System.Classes, RTLConsts, KeePassLib.Wincrypt; 24 | 25 | resourcestring 26 | SCryptographyHashNotYetFinalized = 'Hash not yet finalized.'; 27 | SCryptographyCryptoStreamFlushFinalBlockTwice = ''; 28 | SCryptography_InvalidKeySize = 'Invalid key size.'; 29 | sCryptography_InvalidIVSize = 'Invalid IV size.'; 30 | sCryptography_InvalidFeedbackSize = 'Invalid feedback size.'; 31 | sCryptography_InvalidBlockSize = 'Invalid block size.'; 32 | sCryptography_InvalidCipherMode = 'Invalid cipher mode.'; 33 | sCryptography_InvalidPaddingMode = 'Invalid padding mode.'; 34 | SCryptography_DpApi_InvalidMemoryLength = 'Invalid memory block size.'; 35 | SArg_EnumIllegalVal = 'Illegal enum value.'; 36 | 37 | type 38 | TEncryptionMode = (Encrypt, Decrypt); 39 | 40 | /// 41 | /// Defines the basic operations of cryptographic transformations. 42 | /// 43 | ICryptoTransform = interface 44 | ['{8ABAD867-F515-3CF6-BB62-5F0C88B3BB11}'] 45 | function GetCanReuseTransform: Boolean; 46 | function GetCanTransformMultipleBlocks: Boolean; 47 | function GetInputBlockSize: Integer; 48 | function GetOutputBlockSize: Integer; 49 | 50 | /// 51 | /// Gets the input block size. 52 | /// 53 | property InputBlockSize: Integer read GetInputBlockSize; 54 | 55 | /// 56 | /// Gets the output block size. 57 | /// 58 | property OutputBlockSize: Integer read GetOutputBlockSize; 59 | 60 | /// 61 | /// Gets a value indicating whether multiple blocks can be transformed. 62 | /// 63 | property CanTransformMultipleBlocks: Boolean read GetCanTransformMultipleBlocks; 64 | 65 | /// 66 | /// Gets a value indicating whether the current transform can be reused. 67 | /// 68 | property CanReuseTransform: Boolean read GetCanReuseTransform; 69 | 70 | function TransformBlock(InputBuffer: TBytes; InputOffset: Integer; 71 | InputCount: Integer; out OutputBuffer: TBytes; OutputOffset: Integer): Integer; 72 | 73 | /// 74 | /// Transforms the specified region of the specified byte array. 75 | /// 76 | /// The input for which to compute the transform. 77 | /// 78 | /// 79 | /// The offset into the byte array from which to begin using data. 80 | /// 81 | /// 82 | /// The number of bytes in the byte array to use as data. 83 | /// 84 | /// 85 | /// 86 | /// The computed transform. 87 | /// 88 | /// 89 | /// TransformFinalBlock is a special function for transforming the last 90 | /// block or a partial block in the stream. It returns a new array that 91 | /// contains the remaining transformed bytes. A new array is returned, 92 | /// because the amount of information returned at the end might be larger 93 | /// than a single block when padding is added. 94 | /// 95 | function TransformFinalBlock(InputBuffer: TBytes; InputOffset: Integer; InputCount: Integer): TBytes; 96 | end; 97 | 98 | ECryptographicException = class(Exception); 99 | ECryptographicUnexpectedOperationException = class(ECryptographicException); 100 | 101 | /// 102 | /// Represents the base class from which all implementations of 103 | /// cryptographic hash algorithms must derive. 104 | /// 105 | THashAlgorithm = class abstract(TInterfacedObject, ICryptoTransform) 106 | strict protected 107 | FHashValue: TBytes; 108 | protected 109 | FHashSizeValue: Integer; 110 | FState: Integer; 111 | function GetCanReuseTransform: Boolean; virtual; 112 | function GetCanTransformMultipleBlocks: Boolean; virtual; 113 | function GetInputBlockSize: Integer; virtual; 114 | function GetOutputBlockSize: Integer; virtual; 115 | function GetHash: TBytes; virtual; 116 | function GetHashSize: Integer; virtual; 117 | function HashCore(&Array: TBytes; ibStart: Integer; cbSize: Integer): Integer; virtual; abstract; 118 | function HashFinal: TBytes; virtual; abstract; 119 | public 120 | property CanReuseTransform: Boolean read GetCanReuseTransform; 121 | property CanTransformMultipleBlocks: Boolean read GetCanTransformMultipleBlocks; 122 | property InputBlockSize: Integer read GetInputBlockSize; 123 | property OutputBlockSize: Integer read GetOutputBlockSize; 124 | property Hash: TBytes read GetHash; 125 | property HashSize: Integer read GetHashSize; 126 | constructor Create; 127 | destructor Destroy; override; 128 | procedure Clear; virtual; 129 | function ComputeHash(InputStream: TStream): TBytes; overload; 130 | function ComputeHash(Buffer: TBytes): TBytes; overload; 131 | function ComputeHash(Buffer: TBytes; Offset: Integer; Count: Integer): TBytes; overload; 132 | /// 133 | /// Computes the hash value for the specified region of the input byte 134 | /// array and copies the specified region of the input byte array to the 135 | /// specified region of the output byte array. 136 | /// 137 | /// The input to compute the hash code for. 138 | /// 139 | /// 140 | /// The offset into the input byte array from which to begin using data. 141 | /// 142 | /// 143 | /// The number of bytes in the input byte array to use as data. 144 | /// 145 | /// 146 | /// A copy of the part of the input array used to compute the hash code. 147 | /// 148 | /// 149 | /// The offset into the output byte array from which to begin writing data. 150 | /// 151 | /// 152 | /// 153 | /// The number of bytes written. 154 | /// 155 | /// 156 | /// uses an invalid value or inputBuffer has an invalid length. 157 | /// 158 | function TransformBlock(InputBuffer: TBytes; InputOffset: Integer; 159 | InputCount: Integer; out OutputBuffer: TBytes; OutputOffset: Integer): Integer; 160 | function TransformFinalBlock(InputBuffer: TBytes; InputOffset: Integer; InputCount: Integer): TBytes; 161 | procedure Initialize; virtual; abstract; 162 | end; 163 | 164 | TCipherMode = (CBC, ECB, OFB, CFB, CTS); 165 | 166 | TPaddingMode = (None, PKCS7, Zeroes, ANSIX923, ISO10126); 167 | 168 | TKeySizes = record 169 | private 170 | FMinSize: Integer; 171 | FMaxSize: Integer; 172 | FSkipSize: Integer; 173 | public 174 | property MinSize: Integer read FMinSize; 175 | property MaxSize: Integer read FMaxSize; 176 | property SkipSize: Integer read FSkipSize; 177 | end; 178 | 179 | /// 180 | /// Represents the abstract base class from which all implementations of 181 | /// symmetric algorithms must inherit. 182 | /// 183 | TSymmetricAlgorithm = class abstract 184 | private 185 | function GetBlockSize: Integer; virtual; 186 | procedure SetBlockSize(const Value: Integer); virtual; 187 | function GetFeedbackSize: Integer; virtual; 188 | procedure SetFeedbackSize(const Value: Integer); virtual; 189 | function GetIV: TBytes; virtual; 190 | procedure SetIV(const Value: TBytes); virtual; 191 | function GetKey: TBytes; virtual; 192 | procedure SetKey(const Value: TBytes); virtual; 193 | function GetLegalBlockSizes: TArray; virtual; 194 | function GetLegalKeySizes: TArray; virtual; 195 | function GetKeySize: Integer; virtual; 196 | procedure SetKeySize(const Value: Integer); virtual; 197 | function GetMode: TCipherMode; virtual; 198 | procedure SetMode(const Value: TCipherMode); virtual; 199 | function GetPadding: TPaddingMode; virtual; 200 | procedure SetPadding(const Value: TPaddingMode); virtual; 201 | protected 202 | FBlockSize: Integer; 203 | FFeedbackSize: Integer; 204 | FIV: TBytes; 205 | FKey: TBytes; 206 | FLegalBlockSizes: TArray; 207 | FLegalKeySizes: TArray; 208 | FKeySize: Integer; 209 | FMode: TCipherMode; 210 | FPadding: TPaddingMode; 211 | public 212 | property BlockSize: Integer read GetBlockSize write SetBlockSize; 213 | property FeedbackSize: Integer read GetFeedbackSize write SetFeedbackSize; 214 | property IV: TBytes read GetIV write SetIV; 215 | property Key: TBytes read GetKey write SetKey; 216 | property LegalBlockSizes: TArray read GetLegalBlockSizes; 217 | property LegalKeySizes: TArray read GetLegalKeySizes; 218 | property KeySize: Integer read GetKeySize write SetKeySize; 219 | property Mode: TCipherMode read GetMode write SetMode; 220 | property Padding: TPaddingMode read GetPadding write SetPadding; 221 | function ValidKeySize(BitLength: Integer): Boolean; 222 | function CreateEncryptor: ICryptoTransform;overload; virtual; 223 | function CreateEncryptor(Key: TBytes; IV: TBytes): ICryptoTransform; overload; virtual; abstract; 224 | function CreateDecryptor: ICryptoTransform; overload; virtual; 225 | function CreateDecryptor(Key: TBytes; IV: TBytes): ICryptoTransform; overload; virtual; abstract; 226 | procedure GenerateKey; virtual; abstract; 227 | procedure GenerateIV; virtual; abstract; 228 | 229 | constructor Create; 230 | destructor Destroy; override; 231 | end; 232 | 233 | TCapiSymmetricAlgorithm = class(TInterfacedObject, ICryptoTransform) 234 | private 235 | FBlockSize: Integer; 236 | FDepadBuffer: TBytes; 237 | FEncryptionMode: TEncryptionMode; 238 | FKey: HCRYPTKEY; 239 | FPaddingMode: TPaddingMode; 240 | FProvider: HCRYPTPROV; 241 | 242 | class function SetupKey(Key: HCRYPTKEY; IV: TBytes; CipherMode: TCipherMode; 243 | FeedbackSize: Integer): HCRYPTKEY; static; 244 | function DecryptBlocks(InputBuffer: TBytes; InputOffset: Integer; 245 | InputCount: Integer; out OutputBuffer: TBytes; OutputOffset: Integer): Integer; 246 | function RawDecryptBlocks(Buffer: TBytes; Offset: Integer; Count: Integer): Integer; 247 | function DepadBlock(Block: TBytes; Offset: Integer; Count: Integer): TBytes; 248 | protected 249 | function GetCanReuseTransform: Boolean; 250 | function GetCanTransformMultipleBlocks: Boolean; 251 | function GetInputBlockSize: Integer; 252 | function GetOutputBlockSize: Integer; 253 | public 254 | property InputBlockSize: Integer read GetInputBlockSize; 255 | property OutputBlockSize: Integer read GetOutputBlockSize; 256 | property CanTransformMultipleBlocks: Boolean read GetCanTransformMultipleBlocks; 257 | property CanReuseTransform: Boolean read GetCanReuseTransform; 258 | function TransformBlock(InputBuffer: TBytes; InputOffset: Integer; 259 | InputCount: Integer; out OutputBuffer: TBytes; OutputOffset: Integer): Integer; 260 | function TransformFinalBlock(InputBuffer: TBytes; InputOffset: Integer; InputCount: Integer): TBytes; 261 | 262 | constructor Create(BlockSize: Integer; FeedbackSize: Integer; 263 | Provider: HCRYPTPROV; Key: HCRYPTKEY; IV: TBytes; CipherMode: TCipherMode; 264 | PaddingMode: TPaddingMode; EncryptionMode: TEncryptionMode); 265 | destructor Destroy; override; 266 | end; 267 | 268 | TCapiHash = class(THashAlgorithm, ICryptoTransform) 269 | private 270 | FAlgid: ALG_ID; 271 | FHashHandle: HCRYPTHASH; 272 | FProvHandle: HCRYPTPROV; 273 | protected 274 | function HashCore(&Array: TBytes; ibStart: Integer; cbSize: Integer): Integer; override; 275 | function HashFinal: TBytes; override; 276 | constructor Create(Algid: ALG_ID); 277 | public 278 | procedure Initialize; override; 279 | procedure Clear; override; 280 | end; 281 | 282 | TSHA1CryptoServiceProvider = class(TCapiHash, ICryptoTransform) 283 | public 284 | constructor Create; 285 | end; 286 | 287 | TSHA256CryptoServiceProvider = class(TCapiHash, ICryptoTransform) 288 | public 289 | constructor Create; 290 | end; 291 | 292 | TCryptoStreamMode = (csmRead, csmWrite); 293 | 294 | TCryptoStream = class(TStream) 295 | private 296 | FStream: TStream; 297 | FTransform: ICryptoTransform; 298 | FInputBuffer: TBytes; 299 | FInputBufferIndex: Integer; 300 | FOutputBuffer: TBytes; 301 | FOutputBufferIndex: Integer; 302 | FOutputBlockSize: Integer; 303 | FTransformMode: TCryptoStreamMode; 304 | FFinalBlockTransformed: Boolean; 305 | public 306 | property HasFlushedFinalBlock: Boolean read FFinalBlockTransformed; 307 | 308 | constructor Create(Stream: TStream; Transform: ICryptoTransform; Mode: TCryptoStreamMode); 309 | procedure FlushFinalBlock; 310 | end; 311 | 312 | TDataProtectionScope = 313 | ( 314 | CurrentUser, 315 | LocalMachine 316 | ); 317 | 318 | TMemoryProtectionScope = 319 | ( 320 | SameProcess, 321 | CrossProcess, 322 | SameLogon 323 | ); 324 | 325 | TProtectedData = class 326 | public 327 | class function Protect(UserData: TBytes; OptionalEntropy: TBytes; 328 | Scope: TDataProtectionScope): TBytes; static; 329 | class function Unprotect(EncryptedData: TBytes; OptionalEntropy: TBytes; 330 | Scope: TDataProtectionScope): TBytes; static; 331 | strict protected 332 | constructor Create; 333 | end; 334 | 335 | TProtectedMemory = class 336 | strict private 337 | class procedure VerifyScope(Scope: TMemoryProtectionScope); static; 338 | public 339 | class procedure Protect(UserData: TBytes; 340 | Scope: TMemoryProtectionScope); static; 341 | class procedure Unprotect(EncryptedData: TBytes; 342 | Scope: TMemoryProtectionScope); static; 343 | strict protected 344 | constructor Create; 345 | end; 346 | 347 | TRandomNumberGenerator = class abstract 348 | strict protected 349 | constructor Create; 350 | public 351 | procedure GetBytes(Data: TBytes); overload; virtual; abstract; 352 | procedure GetBytes(Data: TBytes; Offset: Integer; Count: Integer); overload; virtual; 353 | procedure GetNonZeroBytes(Data: TBytes); virtual; 354 | end; 355 | 356 | TRNGCryptoServiceProvider = class(TRandomNumberGenerator) 357 | strict private 358 | FProvHandle: HCRYPTPROV; 359 | public 360 | constructor Create; 361 | destructor Destroy; override; 362 | procedure GetBytes(Data: TBytes); 363 | procedure GetNonZeroBytes(Data: TBytes); override; 364 | end; 365 | 366 | implementation 367 | 368 | { THashAlgorithm } 369 | 370 | procedure THashAlgorithm.Clear; 371 | begin 372 | if Length(FHashValue) <> 0 then 373 | begin 374 | FillChar(FHashValue[0], Length(FHashValue), 0); 375 | FHashValue := nil; 376 | end; 377 | end; 378 | 379 | function THashAlgorithm.ComputeHash(Buffer: TBytes): TBytes; 380 | var 381 | Tmp: TBytes; 382 | begin 383 | if not Assigned(Buffer) then 384 | raise EArgumentNilException.CreateFmt(SParamIsNil, ['Buffer']); 385 | 386 | HashCore(Buffer, 0, Length(Buffer)); 387 | FHashValue := HashFinal; 388 | Tmp := Copy(FHashValue); 389 | Initialize; 390 | Result := Tmp; 391 | end; 392 | 393 | function THashAlgorithm.ComputeHash(Buffer: TBytes; Offset, 394 | Count: Integer): TBytes; 395 | var 396 | Tmp: TBytes; 397 | begin 398 | if not Assigned(Buffer) then 399 | raise EArgumentNilException.CreateFmt(SParamIsNil, ['Buffer']); 400 | if Offset < 0 then 401 | raise EArgumentOutOfRangeException.CreateFmt(SParamIsNegative, ['Offset']); 402 | if (Count < 0) or (Count > Length(Buffer)) then 403 | raise EArgumentException.Create(sArgumentInvalid); 404 | if (Length(Buffer) - Count) < Offset then 405 | raise EArgumentException.Create(sArgumentOutOfRange_OffLenInvalid); 406 | 407 | HashCore(Buffer, Offset, Count); 408 | FHashValue := HashFinal; 409 | Tmp := Copy(FHashValue); 410 | Initialize; 411 | Result := Tmp; 412 | end; 413 | 414 | function THashAlgorithm.ComputeHash(InputStream: TStream): TBytes; 415 | var 416 | BytesRead : Longint; 417 | Buffer : TBytes; 418 | Tmp : TBytes; 419 | begin 420 | BytesRead := 0; 421 | SetLength(Buffer, 4096); 422 | 423 | repeat 424 | BytesRead := InputStream.Read(Buffer[0], BytesRead); 425 | if BytesRead > 0 then 426 | HashCore(Buffer, 0, BytesRead); 427 | until BytesRead > 0; 428 | 429 | FHashValue := HashFinal; 430 | Tmp := Copy(FHashValue); 431 | Initialize; 432 | Result := Tmp; 433 | end; 434 | 435 | constructor THashAlgorithm.Create; 436 | begin 437 | inherited; 438 | Initialize; 439 | end; 440 | 441 | destructor THashAlgorithm.Destroy; 442 | begin 443 | Clear; 444 | inherited; 445 | end; 446 | 447 | function THashAlgorithm.GetCanReuseTransform: Boolean; 448 | begin 449 | Result := True; 450 | end; 451 | 452 | function THashAlgorithm.GetCanTransformMultipleBlocks: Boolean; 453 | begin 454 | Result := True; 455 | end; 456 | 457 | function THashAlgorithm.GetHash: TBytes; 458 | begin 459 | if FState <> 0 then 460 | raise ECryptographicUnexpectedOperationException.Create(SCryptographyHashNotYetFinalized); 461 | 462 | Result := Copy(FHashValue); 463 | end; 464 | 465 | function THashAlgorithm.GetHashSize: Integer; 466 | begin 467 | Result := FHashSizeValue; 468 | end; 469 | 470 | function THashAlgorithm.GetInputBlockSize: Integer; 471 | begin 472 | Result := 1; 473 | end; 474 | 475 | function THashAlgorithm.GetOutputBlockSize: Integer; 476 | begin 477 | Result := 1; 478 | end; 479 | 480 | function THashAlgorithm.TransformBlock(InputBuffer: TBytes; InputOffset, 481 | InputCount: Integer; out OutputBuffer: TBytes; 482 | OutputOffset: Integer): Integer; 483 | begin 484 | if not Assigned(InputBuffer) then 485 | raise EArgumentNilException.CreateFmt(SParamIsNil, ['InputBuffer']); 486 | if InputOffset < 0 then 487 | raise EArgumentOutOfRangeException.CreateFmt(SParamIsNegative, ['InputOffset']); 488 | if (InputCount < 0) or (InputCount > Length(InputBuffer)) then 489 | raise EArgumentException.Create(sArgumentInvalid); 490 | if (Length(InputBuffer) - InputCount) < InputOffset then 491 | raise EArgumentException.Create(sArgumentOutOfRange_OffLenInvalid); 492 | 493 | FState := 1; 494 | 495 | HashCore(InputBuffer, InputOffset, InputCount); 496 | 497 | if Assigned(OutputBuffer) and (InputBuffer <> OutputBuffer) and (InputOffset <> OutputOffset) then 498 | Move(InputBuffer[InputOffset], OutputBuffer[OutputOffset], InputCount); 499 | 500 | Result := InputCount; 501 | end; 502 | 503 | function THashAlgorithm.TransformFinalBlock(InputBuffer: TBytes; InputOffset, 504 | InputCount: Integer): TBytes; 505 | var 506 | OutputBytes: TBytes; 507 | begin 508 | if InputBuffer = nil then 509 | raise EArgumentNilException.CreateFmt(SParamIsNil, ['InputBuffer']); 510 | if InputOffset < 0 then 511 | raise EArgumentOutOfRangeException.CreateFmt(SParamIsNegative, ['InputOffset']); 512 | if (InputCount < 0) or (InputCount > Length(InputBuffer)) then 513 | raise EArgumentException.Create(sArgumentInvalid); 514 | if Length(InputBuffer) - InputCount < InputOffset then 515 | raise EArgumentException.Create(sArgumentOutOfRange_OffLenInvalid); 516 | 517 | HashCore(InputBuffer, InputOffset, InputCount); 518 | FHashValue := HashFinal; 519 | 520 | if InputCount <> 0 then 521 | begin 522 | SetLength(OutputBytes, InputCount); 523 | Move(InputBuffer[InputOffset], OutputBytes, InputCount); 524 | end 525 | else 526 | begin 527 | SetLength(OutputBytes, 0); 528 | end; 529 | FState := 0; 530 | Result := Copy(OutputBytes); 531 | end; 532 | 533 | { TSHA1CryptoServiceProvider } 534 | 535 | constructor TSHA1CryptoServiceProvider.Create; 536 | begin 537 | inherited Create(CALG_SHA1); 538 | end; 539 | 540 | { TCapiHash } 541 | 542 | procedure TCapiHash.Clear; 543 | begin 544 | inherited; 545 | 546 | if FHashHandle <> 0 then 547 | CryptDestroyHash(FHashHandle); 548 | if FProvHandle <> 0 then 549 | CryptReleaseContext(FProvHandle, 0); 550 | end; 551 | 552 | constructor TCapiHash.Create(Algid: ALG_ID); 553 | var 554 | dwDataLen, dwHashSize: DWORD; 555 | begin 556 | FAlgid := Algid; 557 | 558 | inherited Create; 559 | 560 | dwDataLen := SizeOf(DWORD); 561 | Win32Check(CryptGetHashParam(FHashHandle, HP_HASHSIZE, dwHashSize, dwDataLen, 0)); 562 | FHashSizeValue := dwHashSize * 8; 563 | end; 564 | 565 | function TCapiHash.HashCore(&Array: TBytes; ibStart, 566 | cbSize: Integer): Integer; 567 | var 568 | dwDataLen: DWORD; 569 | begin 570 | dwDataLen := cbSize; 571 | Win32Check(CryptHashData(FHashHandle, &Array[ibStart], dwDataLen, 0)); 572 | 573 | Result := cbSize; 574 | end; 575 | 576 | function TCapiHash.HashFinal: TBytes; 577 | var 578 | dwDataLen, dwHashSize: DWORD; 579 | begin 580 | dwDataLen := SizeOf(DWORD); 581 | Win32Check(CryptGetHashParam(FHashHandle, HP_HASHSIZE, dwHashSize, dwDataLen, 0)); 582 | SetLength(FHashValue, dwHashSize); 583 | Win32Check(CryptGetHashParam(FHashHandle, HP_HASHVAL, FHashValue[0], dwHashSize, 0)); 584 | 585 | Result := Copy(FHashValue); 586 | end; 587 | 588 | procedure TCapiHash.Initialize; 589 | begin 590 | Clear; 591 | 592 | Win32Check(CryptAcquireContext(FProvHandle, nil, nil, PROV_RSA_AES, CRYPT_VERIFYCONTEXT)); 593 | Win32Check(CryptCreateHash(FProvHandle, FAlgid, 0, 0, FHashHandle)); 594 | end; 595 | 596 | { TSHA256CryptoServiceProvider } 597 | 598 | constructor TSHA256CryptoServiceProvider.Create; 599 | begin 600 | inherited Create(CALG_SHA_256); 601 | end; 602 | 603 | { TCryptoStream } 604 | 605 | constructor TCryptoStream.Create(Stream: TStream; Transform: ICryptoTransform; 606 | Mode: TCryptoStreamMode); 607 | begin 608 | inherited Create; 609 | 610 | FStream := Stream; 611 | FTransform := Transform; 612 | FTransformMode := Mode; 613 | end; 614 | 615 | procedure TCryptoStream.FlushFinalBlock; 616 | var 617 | FinalBytes: TBytes; 618 | InnerCryptoStream: TCryptoStream; 619 | begin 620 | if FFinalBlockTransformed then 621 | raise ENotSupportedException.Create(SCryptographyCryptoStreamFlushFinalBlockTwice); 622 | 623 | FinalBytes := FTransform.TransformFinalBlock(FInputBuffer, 0,FInputBufferIndex); 624 | FFinalBlockTransformed := True; 625 | 626 | FStream.Write(FOutputBuffer, 0, FOutputBufferIndex); 627 | FOutputBufferIndex := 0; 628 | 629 | FStream.Write(FinalBytes, 0, Length(FinalBytes)); 630 | 631 | InnerCryptoStream := FStream as TCryptoStream; 632 | if InnerCryptoStream <> nil then 633 | begin 634 | if not InnerCryptoStream.HasFlushedFinalBlock then 635 | InnerCryptoStream.FlushFinalBlock; 636 | end 637 | 638 | end; 639 | 640 | { TSymmetricAlgorithm } 641 | 642 | constructor TSymmetricAlgorithm.Create; 643 | begin 644 | FMode := TCipherMode.CBC; 645 | FPadding := TPaddingMode.PKCS7; 646 | end; 647 | 648 | function TSymmetricAlgorithm.CreateDecryptor: ICryptoTransform; 649 | begin 650 | 651 | end; 652 | 653 | function TSymmetricAlgorithm.CreateEncryptor: ICryptoTransform; 654 | begin 655 | 656 | end; 657 | 658 | destructor TSymmetricAlgorithm.Destroy; 659 | begin 660 | if Length(FKey) > 0 then 661 | begin 662 | FillChar(FKey, Length(FKey), 0); 663 | FKey := nil; 664 | end; 665 | if Length(FIV) > 0 then 666 | begin 667 | FillChar(FIV, Length(FIV), 0); 668 | FIV := nil; 669 | end; 670 | 671 | inherited; 672 | end; 673 | 674 | function TSymmetricAlgorithm.GetBlockSize: Integer; 675 | begin 676 | Result := FBlockSize; 677 | end; 678 | 679 | function TSymmetricAlgorithm.GetFeedbackSize: Integer; 680 | begin 681 | Result := FFeedbackSize; 682 | end; 683 | 684 | function TSymmetricAlgorithm.GetKey: TBytes; 685 | begin 686 | if Length(FKey) <= 0 then 687 | GenerateIV; 688 | 689 | Result := Copy(FKey); 690 | end; 691 | 692 | function TSymmetricAlgorithm.GetKeySize: Integer; 693 | begin 694 | Result := FKeySize; 695 | end; 696 | 697 | function TSymmetricAlgorithm.GetLegalBlockSizes: TArray; 698 | begin 699 | Result := Copy(FLegalBlockSizes); 700 | end; 701 | 702 | function TSymmetricAlgorithm.GetLegalKeySizes: TArray; 703 | begin 704 | Result := Copy(FLegalKeySizes); 705 | end; 706 | 707 | function TSymmetricAlgorithm.GetMode: TCipherMode; 708 | begin 709 | Result := FMode; 710 | end; 711 | 712 | function TSymmetricAlgorithm.GetPadding: TPaddingMode; 713 | begin 714 | Result := FPadding; 715 | end; 716 | 717 | function TSymmetricAlgorithm.GetIV: TBytes; 718 | begin 719 | if Length(FIV) <= 0 then 720 | GenerateIV; 721 | 722 | Result := Copy(FIV); 723 | end; 724 | 725 | procedure TSymmetricAlgorithm.SetBlockSize(const Value: Integer); 726 | var 727 | I, J: Integer; 728 | begin 729 | for I := 0 to Length(FLegalBlockSizes) - 1 do 730 | begin 731 | if FLegalBlockSizes[I].SkipSize = 0 then 732 | begin 733 | if FLegalBlockSizes[I].MinSize = Value then 734 | begin 735 | FBlockSize := Value; 736 | FIV := nil; 737 | Exit; 738 | end; 739 | end 740 | else 741 | begin 742 | J := FLegalBlockSizes[i].MinSize; 743 | while J <= FLegalBlockSizes[i].MaxSize do 744 | begin 745 | if J = Value then 746 | begin 747 | if FBlockSize <> Value then 748 | begin 749 | FBlockSize := Value; 750 | FIV := nil; 751 | end; 752 | Exit; 753 | end; 754 | Inc(J, FLegalBlockSizes[i].SkipSize); 755 | end; 756 | end; 757 | end; 758 | 759 | raise ECryptographicException.Create(sCryptography_InvalidBlockSize); 760 | end; 761 | 762 | procedure TSymmetricAlgorithm.SetFeedbackSize(const Value: Integer); 763 | begin 764 | if (Value <= 0) or (Value > FBlockSize) or (Value mod 8 <> 0) then 765 | raise ECryptographicException.Create(sCryptography_InvalidFeedbackSize); 766 | 767 | FFeedbackSize := Value; 768 | end; 769 | 770 | procedure TSymmetricAlgorithm.SetIV(const Value: TBytes); 771 | begin 772 | if Value = nil then 773 | raise EArgumentNilException.Create('Value'); 774 | 775 | if Length(Value) <> (FBlockSize div 8) then 776 | raise ECryptographicException.Create(sCryptography_InvalidIVSize); 777 | 778 | FIV := Copy(Value); 779 | end; 780 | 781 | procedure TSymmetricAlgorithm.SetKey(const Value: TBytes); 782 | begin 783 | if Value = nil then 784 | raise EArgumentNilException.Create('Key'); 785 | 786 | if not ValidKeySize(Length(Value) * 8) then 787 | raise ECryptographicException.Create(sCryptography_InvalidKeySize); 788 | 789 | FKey := Copy(Value); 790 | FKeySize := Length(Value) * 8; 791 | end; 792 | 793 | procedure TSymmetricAlgorithm.SetKeySize(const Value: Integer); 794 | begin 795 | if not ValidKeySize(Value) then 796 | raise ECryptographicException.Create(SCryptography_InvalidKeySize); 797 | 798 | FKeySize := Value; 799 | FKey := nil; 800 | end; 801 | 802 | procedure TSymmetricAlgorithm.SetMode(const Value: TCipherMode); 803 | begin 804 | if (Value < Low(TCipherMode)) or (Value > High(TCipherMode)) then 805 | raise ECryptographicException.Create(sCryptography_InvalidCipherMode); 806 | 807 | FMode := Value; 808 | end; 809 | 810 | procedure TSymmetricAlgorithm.SetPadding(const Value: TPaddingMode); 811 | begin 812 | if (Value < Low(TPaddingMode)) or (Value > High(TPaddingMode)) then 813 | raise ECryptographicException.Create(sCryptography_InvalidPaddingMode); 814 | 815 | FPadding := Value; 816 | end; 817 | 818 | function TSymmetricAlgorithm.ValidKeySize(BitLength: Integer): Boolean; 819 | var 820 | ValidSizes: TArray; 821 | I: NativeInt; 822 | J: Integer; 823 | begin 824 | ValidSizes := FLegalKeySizes; 825 | if Length(ValidSizes) <= 0 then 826 | Exit(False); 827 | 828 | for I := 0 to Length(ValidSizes) - 1 do 829 | begin 830 | if ValidSizes[I].SkipSize = 0 then 831 | begin 832 | if ValidSizes[I].MinSize = BitLength then 833 | Exit(True); 834 | end 835 | else 836 | begin 837 | J := ValidSizes[I].MinSize; 838 | while J <= ValidSizes[I].MaxSize do 839 | begin 840 | if J = BitLength then 841 | Exit(True); 842 | end; 843 | Inc(J, ValidSizes[I].SkipSize); 844 | end; 845 | end; 846 | 847 | Result := False; 848 | end; 849 | 850 | { TCapiSymmetricAlgorithm } 851 | 852 | constructor TCapiSymmetricAlgorithm.Create(BlockSize, FeedbackSize: Integer; 853 | Provider: HCRYPTPROV; Key: HCRYPTKEY; IV: TBytes; CipherMode: TCipherMode; 854 | PaddingMode: TPaddingMode; EncryptionMode: TEncryptionMode); 855 | begin 856 | inherited Create; 857 | 858 | Assert((0 < BlockSize) and (BlockSize mod 8 = 0)); 859 | Assert(0 <= FeedbackSize); 860 | Assert(Provider <> 0); 861 | Assert(Key <> 0); 862 | 863 | FBlockSize := BlockSize; 864 | FEncryptionMode := EncryptionMode; 865 | FPaddingMode := PaddingMode; 866 | if CryptContextAddRef(FProvider, nil, 0) then 867 | FProvider := Provider 868 | else 869 | RaiseLastOSError; 870 | 871 | FKey := SetupKey(Key, IV, CipherMode, FeedbackSize); 872 | end; 873 | 874 | function TCapiSymmetricAlgorithm.DecryptBlocks(InputBuffer: TBytes; InputOffset, 875 | InputCount: Integer; out OutputBuffer: TBytes; 876 | OutputOffset: Integer): Integer; 877 | var 878 | DecryptedBytes: Integer; 879 | DepadDecryptLength: Integer; 880 | begin 881 | Assert(FKey <> 0); 882 | Assert((Length(InputBuffer) > 0) and (InputCount <= Length(InputBuffer) - InputOffset)); 883 | Assert(InputOffset >= 0); 884 | 885 | DecryptedBytes := 0; 886 | 887 | if (FPaddingMode <> TPaddingMode.None) and (FPaddingMode <> TPaddingMode.Zeroes) then 888 | begin 889 | if Length(FDepadBuffer) > 0 then 890 | begin 891 | DepadDecryptLength := RawDecryptBlocks(FDepadBuffer, 0, Length(FDepadBuffer)); 892 | Move(FDepadBuffer[0], OutputBuffer[OutputOffset], DepadDecryptLength); 893 | FillChar(FDepadBuffer[0], Length(FDepadBuffer), 0); 894 | Inc(OutputOffset, DepadDecryptLength); 895 | Inc(DecryptedBytes, DepadDecryptLength); 896 | end 897 | else 898 | begin 899 | SetLength(FDepadBuffer, InputBlockSize); 900 | end; 901 | 902 | Move(InputBuffer[InputOffset + InputCount - Length(FDepadBuffer)], FDepadBuffer[0], Length(FDepadBuffer)); 903 | Dec(InputCount, Length(FDepadBuffer)); 904 | end; 905 | 906 | if InputCount > 0 then 907 | begin 908 | Move(InputBuffer[InputOffset], OutputBuffer[OutputOffset], InputCount); 909 | Inc(DecryptedBytes, RawDecryptBlocks(OutputBuffer, OutputOffset, InputCount)); 910 | end; 911 | 912 | Result := DecryptedBytes; 913 | end; 914 | 915 | function TCapiSymmetricAlgorithm.DepadBlock(Block: TBytes; Offset, 916 | Count: Integer): TBytes; 917 | var 918 | PadBytes: TBytes; 919 | begin 920 | 921 | end; 922 | 923 | destructor TCapiSymmetricAlgorithm.Destroy; 924 | begin 925 | if FKey <> 0 then 926 | CryptDestroyKey(FKey); 927 | if FProvider <> 0 then 928 | CryptReleaseContext(FProvider, 0); 929 | if Length(FDepadBuffer) > 0 then 930 | FillChar(FDepadBuffer, Length(FDepadBuffer), 0); 931 | 932 | inherited; 933 | end; 934 | 935 | function TCapiSymmetricAlgorithm.GetCanReuseTransform: Boolean; 936 | begin 937 | Result := True; 938 | end; 939 | 940 | function TCapiSymmetricAlgorithm.GetCanTransformMultipleBlocks: Boolean; 941 | begin 942 | Result := True; 943 | end; 944 | 945 | function TCapiSymmetricAlgorithm.GetInputBlockSize: Integer; 946 | begin 947 | Result := FBlockSize div 8; 948 | end; 949 | 950 | function TCapiSymmetricAlgorithm.GetOutputBlockSize: Integer; 951 | begin 952 | Result := FBlockSize div 8; 953 | end; 954 | 955 | function TCapiSymmetricAlgorithm.RawDecryptBlocks(Buffer: TBytes; Offset, 956 | Count: Integer): Integer; 957 | var 958 | DataLength: Integer; 959 | begin 960 | DataLength := Count; 961 | 962 | Win32Check(CryptDecrypt(FKey, 0, False, 0, Buffer[Offset], DataLength)); 963 | 964 | Result := DataLength; 965 | end; 966 | 967 | class function TCapiSymmetricAlgorithm.SetupKey(Key: HCRYPTKEY; IV: TBytes; 968 | CipherMode: TCipherMode; FeedbackSize: Integer): HCRYPTKEY; 969 | var 970 | EncryptionKey: HCRYPTKEY; 971 | dwData: DWORD; 972 | begin 973 | Assert(Key <> 0); 974 | Assert((CipherMode = TCipherMode.ECB) or (Length(IV) > 0)); 975 | Assert(0 <= FeedbackSize); 976 | 977 | CryptDuplicateKey(Key, nil, 0, EncryptionKey); 978 | 979 | dwData := DWORD(CipherMode); 980 | CryptSetKeyParam(EncryptionKey, KP_MODE, dwData, 0); 981 | 982 | if CipherMode <> TCipherMode.ECB then 983 | CryptSetKeyParam(EncryptionKey, KP_IV, IV[0], 0); 984 | 985 | if (CipherMode = TCipherMode.CFB) or (CipherMode = TCipherMode.OFB) then 986 | CryptSetKeyParam(EncryptionKey, KP_MODE_BITS, IV[0], 0); 987 | 988 | Result := EncryptionKey; 989 | end; 990 | 991 | function TCapiSymmetricAlgorithm.TransformBlock(InputBuffer: TBytes; 992 | InputOffset, InputCount: Integer; out OutputBuffer: TBytes; 993 | OutputOffset: Integer): Integer; 994 | begin 995 | 996 | end; 997 | 998 | function TCapiSymmetricAlgorithm.TransformFinalBlock(InputBuffer: TBytes; 999 | InputOffset, InputCount: Integer): TBytes; 1000 | var 1001 | OutputData: TBytes; 1002 | begin 1003 | OutputData := nil; 1004 | 1005 | if InputBuffer = nil then 1006 | raise EArgumentNilException.CreateFmt(SParamIsNil, ['InputBuffer']); 1007 | if InputOffset < 0 then 1008 | raise EArgumentOutOfRangeException.CreateFmt(SParamIsNegative, ['InputOffset']); 1009 | if InputCount < 0 then 1010 | raise EArgumentOutOfRangeException.CreateFmt(SParamIsNegative, ['InputCount']); 1011 | if InputCount < Length(InputBuffer) - InputOffset then 1012 | raise EArgumentOutOfRangeException.Create(sArgumentOutOfRange_OffLenInvalid); 1013 | 1014 | end; 1015 | 1016 | { TProtectedData } 1017 | 1018 | constructor TProtectedData.Create; 1019 | begin 1020 | 1021 | end; 1022 | 1023 | class function TProtectedData.Protect(UserData, OptionalEntropy: TBytes; 1024 | Scope: TDataProtectionScope): TBytes; 1025 | var 1026 | DataIn, DataOut, Entropy: TDataBlob; 1027 | EntropyPtr: PDataBlob; 1028 | dwFlags: DWORD; 1029 | begin 1030 | Result := nil; 1031 | 1032 | if UserData = nil then 1033 | raise EArgumentNilException.CreateFmt(SParamIsNil, ['UserData']); 1034 | 1035 | DataIn.cbData := Length(UserData); 1036 | DataIn.pbData := @UserData[0]; 1037 | 1038 | EntropyPtr := nil; 1039 | if Length(OptionalEntropy) > 0 then 1040 | begin 1041 | Entropy.cbData := Length(OptionalEntropy); 1042 | Entropy.pbData := @OptionalEntropy[0]; 1043 | EntropyPtr := @Entropy; 1044 | end; 1045 | 1046 | dwFlags := CRYPTPROTECT_UI_FORBIDDEN; 1047 | if Scope = TDataProtectionScope.LocalMachine then 1048 | dwFlags := dwFlags or CRYPTPROTECT_LOCAL_MACHINE; 1049 | 1050 | FillChar(DataOut, SizeOf(TDataBlob), 0); 1051 | try 1052 | Win32Check(CryptProtectData(@DataIn, nil, EntropyPtr, nil, nil, dwFlags, @DataOut)); 1053 | if DataOut.pbData = nil then 1054 | raise EOutOfMemory.Create(''); 1055 | SetLength(Result, DataOut.cbData); 1056 | Move(PByte(DataOut.pbData)[0], Result[0], DataOut.cbData); 1057 | finally 1058 | if DataOut.pbData <> nil then 1059 | begin 1060 | ZeroMemory(DataOut.pbData, DataOut.cbData); 1061 | LocalFree(HLOCAL(DataOut.pbData)); 1062 | end; 1063 | end; 1064 | end; 1065 | 1066 | class function TProtectedData.Unprotect(EncryptedData, 1067 | OptionalEntropy: TBytes; Scope: TDataProtectionScope): TBytes; 1068 | var 1069 | DataIn, DataOut, Entropy: TDataBlob; 1070 | EntropyPtr: PDataBlob; 1071 | dwFlags: DWORD; 1072 | begin 1073 | Result := nil; 1074 | 1075 | if EncryptedData = nil then 1076 | raise EArgumentNilException.CreateFmt(SParamIsNil, ['EncryptedData']); 1077 | 1078 | DataIn.cbData := Length(EncryptedData); 1079 | DataIn.pbData := @EncryptedData[0]; 1080 | 1081 | EntropyPtr := nil; 1082 | if Length(OptionalEntropy) > 0 then 1083 | begin 1084 | Entropy.cbData := Length(OptionalEntropy); 1085 | Entropy.pbData := @OptionalEntropy[0]; 1086 | EntropyPtr := @Entropy; 1087 | end; 1088 | 1089 | dwFlags := CRYPTPROTECT_UI_FORBIDDEN; 1090 | if Scope = TDataProtectionScope.LocalMachine then 1091 | dwFlags := dwFlags or CRYPTPROTECT_LOCAL_MACHINE; 1092 | 1093 | FillChar(DataOut, SizeOf(TDataBlob), 0); 1094 | try 1095 | Win32Check(CryptUnprotectData(@DataIn, nil, EntropyPtr, nil, nil, dwFlags, @DataOut)); 1096 | if DataOut.pbData = nil then 1097 | raise EOutOfMemory.Create(''); 1098 | SetLength(Result, DataOut.cbData); 1099 | Move(PByte(DataOut.pbData)[0], Result[0], DataOut.cbData); 1100 | finally 1101 | if DataOut.pbData <> nil then 1102 | begin 1103 | ZeroMemory(DataOut.pbData, DataOut.cbData); 1104 | LocalFree(HLOCAL(DataOut.pbData)); 1105 | end; 1106 | end; 1107 | end; 1108 | 1109 | { TRandomNumberGenerator } 1110 | 1111 | constructor TRandomNumberGenerator.Create; 1112 | begin 1113 | 1114 | end; 1115 | 1116 | procedure TRandomNumberGenerator.GetBytes(Data: TBytes; Offset, Count: Integer); 1117 | var 1118 | TempData: TBytes; 1119 | begin 1120 | if Data = nil then 1121 | raise EArgumentNilException.CreateFmt(SParamIsNil, ['Data']); 1122 | if Offset < 0 then 1123 | raise EArgumentOutOfRangeException.CreateFmt(SParamIsNegative, ['Offset']); 1124 | if Count < 0 then 1125 | raise EArgumentOutOfRangeException.CreateFmt(SParamIsNegative, ['Count']); 1126 | if Offset + Count > Length(Data) then 1127 | raise EArgumentException.Create(sArgumentOutOfRange_OffLenInvalid); 1128 | 1129 | if Count > 0 then 1130 | begin 1131 | SetLength(TempData, Count); 1132 | GetBytes(TempData); 1133 | Data := Copy(TempData, Offset, Count); 1134 | end; 1135 | end; 1136 | 1137 | procedure TRandomNumberGenerator.GetNonZeroBytes(Data: TBytes); 1138 | begin 1139 | raise ENotImplemented.Create(''); 1140 | end; 1141 | 1142 | { TRNGCryptoServiceProvider } 1143 | 1144 | constructor TRNGCryptoServiceProvider.Create; 1145 | begin 1146 | inherited; 1147 | 1148 | Win32Check(CryptAcquireContext(FProvHandle, nil, MS_ENHANCED_PROV, PROV_RSA_FULL, CRYPT_VERIFYCONTEXT)); 1149 | end; 1150 | 1151 | destructor TRNGCryptoServiceProvider.Destroy; 1152 | begin 1153 | if FProvHandle <> 0 then 1154 | CryptReleaseContext(FProvHandle, 0); 1155 | 1156 | inherited; 1157 | end; 1158 | 1159 | procedure TRNGCryptoServiceProvider.GetBytes(Data: TBytes); 1160 | begin 1161 | if Data = nil then 1162 | raise EArgumentNilException.CreateFmt(SParamIsNil, ['Data']); 1163 | 1164 | Win32Check(CryptGenRandom(FProvHandle, Length(Data), @Data[0])); 1165 | end; 1166 | 1167 | procedure TRNGCryptoServiceProvider.GetNonZeroBytes(Data: TBytes); 1168 | var 1169 | IndexOfFirst0Byte: Integer; 1170 | I: Integer; 1171 | Tmp: TBytes; 1172 | begin 1173 | GetBytes(Data); 1174 | IndexOfFirst0Byte := Length(Data); 1175 | for I := 0 to Length(Data) - 1 do 1176 | if Data[I] = 0 then 1177 | begin 1178 | IndexOfFirst0Byte := I; 1179 | Break; 1180 | end; 1181 | 1182 | for I := IndexOfFirst0Byte to Length(Data) - 1 do 1183 | if Data[I] <> 0 then 1184 | begin 1185 | Data[IndexOfFirst0Byte] := Data[I]; 1186 | Inc(IndexOfFirst0Byte); 1187 | end; 1188 | 1189 | while IndexOfFirst0Byte < Length(Data) do 1190 | begin 1191 | SetLength(Tmp, 2 * (Length(Data) - IndexOfFirst0Byte)); 1192 | GetBytes(Tmp); 1193 | for I := 0 to Length(Tmp) - 1 do 1194 | if Tmp[I] <> 0 then 1195 | begin 1196 | Data[IndexOfFirst0Byte] := Tmp[I]; 1197 | Inc(IndexOfFirst0Byte); 1198 | if IndexOfFirst0Byte >= Length(Data) then 1199 | Break; 1200 | end; 1201 | end; 1202 | end; 1203 | 1204 | { TProtectedMemory } 1205 | 1206 | constructor TProtectedMemory.Create; 1207 | begin 1208 | 1209 | end; 1210 | 1211 | class procedure TProtectedMemory.Protect(UserData: TBytes; 1212 | Scope: TMemoryProtectionScope); 1213 | begin 1214 | if UserData = nil then 1215 | raise EArgumentNilException.CreateFmt(SParamIsNil, ['UserData']); 1216 | 1217 | TProtectedMemory.VerifyScope(Scope); 1218 | 1219 | if Length(UserData) mod CRYPTPROTECTMEMORY_BLOCK_SIZE <> 0 then 1220 | raise ECryptographicException.Create(SCryptography_DpApi_InvalidMemoryLength); 1221 | 1222 | Win32Check(CryptProtectMemory(@UserData[0], Length(UserData), DWORD(Scope))); 1223 | end; 1224 | 1225 | class procedure TProtectedMemory.Unprotect(EncryptedData: TBytes; 1226 | Scope: TMemoryProtectionScope); 1227 | begin 1228 | if EncryptedData = nil then 1229 | raise EArgumentNilException.CreateFmt(SParamIsNil, ['EncryptedData']); 1230 | 1231 | TProtectedMemory.VerifyScope(Scope); 1232 | 1233 | if Length(EncryptedData) mod CRYPTPROTECTMEMORY_BLOCK_SIZE <> 0 then 1234 | raise ECryptographicException.Create(SCryptography_DpApi_InvalidMemoryLength); 1235 | 1236 | Win32Check(CryptUnprotectMemory(@EncryptedData[0], Length(EncryptedData), DWORD(Scope))); 1237 | end; 1238 | 1239 | class procedure TProtectedMemory.VerifyScope(Scope: TMemoryProtectionScope); 1240 | begin 1241 | if (Scope < Low(TMemoryProtectionScope)) and 1242 | (Scope > High(TMemoryProtectionScope)) then 1243 | raise EArgumentException.Create(SArg_EnumIllegalVal); 1244 | end; 1245 | 1246 | end. 1247 | -------------------------------------------------------------------------------- /LICENSE.md: -------------------------------------------------------------------------------- 1 | ### GNU GENERAL PUBLIC LICENSE 2 | 3 | Version 3, 29 June 2007 4 | 5 | Copyright (C) 2007 Free Software Foundation, Inc. 6 | 7 | 8 | Everyone is permitted to copy and distribute verbatim copies of this 9 | license document, but changing it is not allowed. 10 | 11 | ### Preamble 12 | 13 | The GNU General Public License is a free, copyleft license for 14 | software and other kinds of works. 15 | 16 | The licenses for most software and other practical works are designed 17 | to take away your freedom to share and change the works. By contrast, 18 | the GNU General Public License is intended to guarantee your freedom 19 | to share and change all versions of a program--to make sure it remains 20 | free software for all its users. We, the Free Software Foundation, use 21 | the GNU General Public License for most of our software; it applies 22 | also to any other work released this way by its authors. You can apply 23 | it to your programs, too. 24 | 25 | When we speak of free software, we are referring to freedom, not 26 | price. Our General Public Licenses are designed to make sure that you 27 | have the freedom to distribute copies of free software (and charge for 28 | them if you wish), that you receive source code or can get it if you 29 | want it, that you can change the software or use pieces of it in new 30 | free programs, and that you know you can do these things. 31 | 32 | To protect your rights, we need to prevent others from denying you 33 | these rights or asking you to surrender the rights. Therefore, you 34 | have certain responsibilities if you distribute copies of the 35 | software, or if you modify it: responsibilities to respect the freedom 36 | of others. 37 | 38 | For example, if you distribute copies of such a program, whether 39 | gratis or for a fee, you must pass on to the recipients the same 40 | freedoms that you received. You must make sure that they, too, receive 41 | or can get the source code. And you must show them these terms so they 42 | know their rights. 43 | 44 | Developers that use the GNU GPL protect your rights with two steps: 45 | (1) assert copyright on the software, and (2) offer you this License 46 | giving you legal permission to copy, distribute and/or modify it. 47 | 48 | For the developers' and authors' protection, the GPL clearly explains 49 | that there is no warranty for this free software. For both users' and 50 | authors' sake, the GPL requires that modified versions be marked as 51 | changed, so that their problems will not be attributed erroneously to 52 | authors of previous versions. 53 | 54 | Some devices are designed to deny users access to install or run 55 | modified versions of the software inside them, although the 56 | manufacturer can do so. This is fundamentally incompatible with the 57 | aim of protecting users' freedom to change the software. The 58 | systematic pattern of such abuse occurs in the area of products for 59 | individuals to use, which is precisely where it is most unacceptable. 60 | Therefore, we have designed this version of the GPL to prohibit the 61 | practice for those products. If such problems arise substantially in 62 | other domains, we stand ready to extend this provision to those 63 | domains in future versions of the GPL, as needed to protect the 64 | freedom of users. 65 | 66 | Finally, every program is threatened constantly by software patents. 67 | States should not allow patents to restrict development and use of 68 | software on general-purpose computers, but in those that do, we wish 69 | to avoid the special danger that patents applied to a free program 70 | could make it effectively proprietary. To prevent this, the GPL 71 | assures that patents cannot be used to render the program non-free. 72 | 73 | The precise terms and conditions for copying, distribution and 74 | modification follow. 75 | 76 | ### TERMS AND CONDITIONS 77 | 78 | #### 0. Definitions. 79 | 80 | "This License" refers to version 3 of the GNU General Public License. 81 | 82 | "Copyright" also means copyright-like laws that apply to other kinds 83 | of works, such as semiconductor masks. 84 | 85 | "The Program" refers to any copyrightable work licensed under this 86 | License. Each licensee is addressed as "you". "Licensees" and 87 | "recipients" may be individuals or organizations. 88 | 89 | To "modify" a work means to copy from or adapt all or part of the work 90 | in a fashion requiring copyright permission, other than the making of 91 | an exact copy. The resulting work is called a "modified version" of 92 | the earlier work or a work "based on" the earlier work. 93 | 94 | A "covered work" means either the unmodified Program or a work based 95 | on the Program. 96 | 97 | To "propagate" a work means to do anything with it that, without 98 | permission, would make you directly or secondarily liable for 99 | infringement under applicable copyright law, except executing it on a 100 | computer or modifying a private copy. Propagation includes copying, 101 | distribution (with or without modification), making available to the 102 | public, and in some countries other activities as well. 103 | 104 | To "convey" a work means any kind of propagation that enables other 105 | parties to make or receive copies. Mere interaction with a user 106 | through a computer network, with no transfer of a copy, is not 107 | conveying. 108 | 109 | An interactive user interface displays "Appropriate Legal Notices" to 110 | the extent that it includes a convenient and prominently visible 111 | feature that (1) displays an appropriate copyright notice, and (2) 112 | tells the user that there is no warranty for the work (except to the 113 | extent that warranties are provided), that licensees may convey the 114 | work under this License, and how to view a copy of this License. If 115 | the interface presents a list of user commands or options, such as a 116 | menu, a prominent item in the list meets this criterion. 117 | 118 | #### 1. Source Code. 119 | 120 | The "source code" for a work means the preferred form of the work for 121 | making modifications to it. "Object code" means any non-source form of 122 | a work. 123 | 124 | A "Standard Interface" means an interface that either is an official 125 | standard defined by a recognized standards body, or, in the case of 126 | interfaces specified for a particular programming language, one that 127 | is widely used among developers working in that language. 128 | 129 | The "System Libraries" of an executable work include anything, other 130 | than the work as a whole, that (a) is included in the normal form of 131 | packaging a Major Component, but which is not part of that Major 132 | Component, and (b) serves only to enable use of the work with that 133 | Major Component, or to implement a Standard Interface for which an 134 | implementation is available to the public in source code form. A 135 | "Major Component", in this context, means a major essential component 136 | (kernel, window system, and so on) of the specific operating system 137 | (if any) on which the executable work runs, or a compiler used to 138 | produce the work, or an object code interpreter used to run it. 139 | 140 | The "Corresponding Source" for a work in object code form means all 141 | the source code needed to generate, install, and (for an executable 142 | work) run the object code and to modify the work, including scripts to 143 | control those activities. However, it does not include the work's 144 | System Libraries, or general-purpose tools or generally available free 145 | programs which are used unmodified in performing those activities but 146 | which are not part of the work. For example, Corresponding Source 147 | includes interface definition files associated with source files for 148 | the work, and the source code for shared libraries and dynamically 149 | linked subprograms that the work is specifically designed to require, 150 | such as by intimate data communication or control flow between those 151 | subprograms and other parts of the work. 152 | 153 | The Corresponding Source need not include anything that users can 154 | regenerate automatically from other parts of the Corresponding Source. 155 | 156 | The Corresponding Source for a work in source code form is that same 157 | work. 158 | 159 | #### 2. Basic Permissions. 160 | 161 | All rights granted under this License are granted for the term of 162 | copyright on the Program, and are irrevocable provided the stated 163 | conditions are met. This License explicitly affirms your unlimited 164 | permission to run the unmodified Program. The output from running a 165 | covered work is covered by this License only if the output, given its 166 | content, constitutes a covered work. This License acknowledges your 167 | rights of fair use or other equivalent, as provided by copyright law. 168 | 169 | You may make, run and propagate covered works that you do not convey, 170 | without conditions so long as your license otherwise remains in force. 171 | You may convey covered works to others for the sole purpose of having 172 | them make modifications exclusively for you, or provide you with 173 | facilities for running those works, provided that you comply with the 174 | terms of this License in conveying all material for which you do not 175 | control copyright. Those thus making or running the covered works for 176 | you must do so exclusively on your behalf, under your direction and 177 | control, on terms that prohibit them from making any copies of your 178 | copyrighted material outside their relationship with you. 179 | 180 | Conveying under any other circumstances is permitted solely under the 181 | conditions stated below. Sublicensing is not allowed; section 10 makes 182 | it unnecessary. 183 | 184 | #### 3. Protecting Users' Legal Rights From Anti-Circumvention Law. 185 | 186 | No covered work shall be deemed part of an effective technological 187 | measure under any applicable law fulfilling obligations under article 188 | 11 of the WIPO copyright treaty adopted on 20 December 1996, or 189 | similar laws prohibiting or restricting circumvention of such 190 | measures. 191 | 192 | When you convey a covered work, you waive any legal power to forbid 193 | circumvention of technological measures to the extent such 194 | circumvention is effected by exercising rights under this License with 195 | respect to the covered work, and you disclaim any intention to limit 196 | operation or modification of the work as a means of enforcing, against 197 | the work's users, your or third parties' legal rights to forbid 198 | circumvention of technological measures. 199 | 200 | #### 4. Conveying Verbatim Copies. 201 | 202 | You may convey verbatim copies of the Program's source code as you 203 | receive it, in any medium, provided that you conspicuously and 204 | appropriately publish on each copy an appropriate copyright notice; 205 | keep intact all notices stating that this License and any 206 | non-permissive terms added in accord with section 7 apply to the code; 207 | keep intact all notices of the absence of any warranty; and give all 208 | recipients a copy of this License along with the Program. 209 | 210 | You may charge any price or no price for each copy that you convey, 211 | and you may offer support or warranty protection for a fee. 212 | 213 | #### 5. Conveying Modified Source Versions. 214 | 215 | You may convey a work based on the Program, or the modifications to 216 | produce it from the Program, in the form of source code under the 217 | terms of section 4, provided that you also meet all of these 218 | conditions: 219 | 220 | - a) The work must carry prominent notices stating that you modified 221 | it, and giving a relevant date. 222 | - b) The work must carry prominent notices stating that it is 223 | released under this License and any conditions added under 224 | section 7. This requirement modifies the requirement in section 4 225 | to "keep intact all notices". 226 | - c) You must license the entire work, as a whole, under this 227 | License to anyone who comes into possession of a copy. This 228 | License will therefore apply, along with any applicable section 7 229 | additional terms, to the whole of the work, and all its parts, 230 | regardless of how they are packaged. This License gives no 231 | permission to license the work in any other way, but it does not 232 | invalidate such permission if you have separately received it. 233 | - d) If the work has interactive user interfaces, each must display 234 | Appropriate Legal Notices; however, if the Program has interactive 235 | interfaces that do not display Appropriate Legal Notices, your 236 | work need not make them do so. 237 | 238 | A compilation of a covered work with other separate and independent 239 | works, which are not by their nature extensions of the covered work, 240 | and which are not combined with it such as to form a larger program, 241 | in or on a volume of a storage or distribution medium, is called an 242 | "aggregate" if the compilation and its resulting copyright are not 243 | used to limit the access or legal rights of the compilation's users 244 | beyond what the individual works permit. Inclusion of a covered work 245 | in an aggregate does not cause this License to apply to the other 246 | parts of the aggregate. 247 | 248 | #### 6. Conveying Non-Source Forms. 249 | 250 | You may convey a covered work in object code form under the terms of 251 | sections 4 and 5, provided that you also convey the machine-readable 252 | Corresponding Source under the terms of this License, in one of these 253 | ways: 254 | 255 | - a) Convey the object code in, or embodied in, a physical product 256 | (including a physical distribution medium), accompanied by the 257 | Corresponding Source fixed on a durable physical medium 258 | customarily used for software interchange. 259 | - b) Convey the object code in, or embodied in, a physical product 260 | (including a physical distribution medium), accompanied by a 261 | written offer, valid for at least three years and valid for as 262 | long as you offer spare parts or customer support for that product 263 | model, to give anyone who possesses the object code either (1) a 264 | copy of the Corresponding Source for all the software in the 265 | product that is covered by this License, on a durable physical 266 | medium customarily used for software interchange, for a price no 267 | more than your reasonable cost of physically performing this 268 | conveying of source, or (2) access to copy the Corresponding 269 | Source from a network server at no charge. 270 | - c) Convey individual copies of the object code with a copy of the 271 | written offer to provide the Corresponding Source. This 272 | alternative is allowed only occasionally and noncommercially, and 273 | only if you received the object code with such an offer, in accord 274 | with subsection 6b. 275 | - d) Convey the object code by offering access from a designated 276 | place (gratis or for a charge), and offer equivalent access to the 277 | Corresponding Source in the same way through the same place at no 278 | further charge. You need not require recipients to copy the 279 | Corresponding Source along with the object code. If the place to 280 | copy the object code is a network server, the Corresponding Source 281 | may be on a different server (operated by you or a third party) 282 | that supports equivalent copying facilities, provided you maintain 283 | clear directions next to the object code saying where to find the 284 | Corresponding Source. Regardless of what server hosts the 285 | Corresponding Source, you remain obligated to ensure that it is 286 | available for as long as needed to satisfy these requirements. 287 | - e) Convey the object code using peer-to-peer transmission, 288 | provided you inform other peers where the object code and 289 | Corresponding Source of the work are being offered to the general 290 | public at no charge under subsection 6d. 291 | 292 | A separable portion of the object code, whose source code is excluded 293 | from the Corresponding Source as a System Library, need not be 294 | included in conveying the object code work. 295 | 296 | A "User Product" is either (1) a "consumer product", which means any 297 | tangible personal property which is normally used for personal, 298 | family, or household purposes, or (2) anything designed or sold for 299 | incorporation into a dwelling. In determining whether a product is a 300 | consumer product, doubtful cases shall be resolved in favor of 301 | coverage. For a particular product received by a particular user, 302 | "normally used" refers to a typical or common use of that class of 303 | product, regardless of the status of the particular user or of the way 304 | in which the particular user actually uses, or expects or is expected 305 | to use, the product. A product is a consumer product regardless of 306 | whether the product has substantial commercial, industrial or 307 | non-consumer uses, unless such uses represent the only significant 308 | mode of use of the product. 309 | 310 | "Installation Information" for a User Product means any methods, 311 | procedures, authorization keys, or other information required to 312 | install and execute modified versions of a covered work in that User 313 | Product from a modified version of its Corresponding Source. The 314 | information must suffice to ensure that the continued functioning of 315 | the modified object code is in no case prevented or interfered with 316 | solely because modification has been made. 317 | 318 | If you convey an object code work under this section in, or with, or 319 | specifically for use in, a User Product, and the conveying occurs as 320 | part of a transaction in which the right of possession and use of the 321 | User Product is transferred to the recipient in perpetuity or for a 322 | fixed term (regardless of how the transaction is characterized), the 323 | Corresponding Source conveyed under this section must be accompanied 324 | by the Installation Information. But this requirement does not apply 325 | if neither you nor any third party retains the ability to install 326 | modified object code on the User Product (for example, the work has 327 | been installed in ROM). 328 | 329 | The requirement to provide Installation Information does not include a 330 | requirement to continue to provide support service, warranty, or 331 | updates for a work that has been modified or installed by the 332 | recipient, or for the User Product in which it has been modified or 333 | installed. Access to a network may be denied when the modification 334 | itself materially and adversely affects the operation of the network 335 | or violates the rules and protocols for communication across the 336 | network. 337 | 338 | Corresponding Source conveyed, and Installation Information provided, 339 | in accord with this section must be in a format that is publicly 340 | documented (and with an implementation available to the public in 341 | source code form), and must require no special password or key for 342 | unpacking, reading or copying. 343 | 344 | #### 7. Additional Terms. 345 | 346 | "Additional permissions" are terms that supplement the terms of this 347 | License by making exceptions from one or more of its conditions. 348 | Additional permissions that are applicable to the entire Program shall 349 | be treated as though they were included in this License, to the extent 350 | that they are valid under applicable law. If additional permissions 351 | apply only to part of the Program, that part may be used separately 352 | under those permissions, but the entire Program remains governed by 353 | this License without regard to the additional permissions. 354 | 355 | When you convey a copy of a covered work, you may at your option 356 | remove any additional permissions from that copy, or from any part of 357 | it. (Additional permissions may be written to require their own 358 | removal in certain cases when you modify the work.) You may place 359 | additional permissions on material, added by you to a covered work, 360 | for which you have or can give appropriate copyright permission. 361 | 362 | Notwithstanding any other provision of this License, for material you 363 | add to a covered work, you may (if authorized by the copyright holders 364 | of that material) supplement the terms of this License with terms: 365 | 366 | - a) Disclaiming warranty or limiting liability differently from the 367 | terms of sections 15 and 16 of this License; or 368 | - b) Requiring preservation of specified reasonable legal notices or 369 | author attributions in that material or in the Appropriate Legal 370 | Notices displayed by works containing it; or 371 | - c) Prohibiting misrepresentation of the origin of that material, 372 | or requiring that modified versions of such material be marked in 373 | reasonable ways as different from the original version; or 374 | - d) Limiting the use for publicity purposes of names of licensors 375 | or authors of the material; or 376 | - e) Declining to grant rights under trademark law for use of some 377 | trade names, trademarks, or service marks; or 378 | - f) Requiring indemnification of licensors and authors of that 379 | material by anyone who conveys the material (or modified versions 380 | of it) with contractual assumptions of liability to the recipient, 381 | for any liability that these contractual assumptions directly 382 | impose on those licensors and authors. 383 | 384 | All other non-permissive additional terms are considered "further 385 | restrictions" within the meaning of section 10. If the Program as you 386 | received it, or any part of it, contains a notice stating that it is 387 | governed by this License along with a term that is a further 388 | restriction, you may remove that term. If a license document contains 389 | a further restriction but permits relicensing or conveying under this 390 | License, you may add to a covered work material governed by the terms 391 | of that license document, provided that the further restriction does 392 | not survive such relicensing or conveying. 393 | 394 | If you add terms to a covered work in accord with this section, you 395 | must place, in the relevant source files, a statement of the 396 | additional terms that apply to those files, or a notice indicating 397 | where to find the applicable terms. 398 | 399 | Additional terms, permissive or non-permissive, may be stated in the 400 | form of a separately written license, or stated as exceptions; the 401 | above requirements apply either way. 402 | 403 | #### 8. Termination. 404 | 405 | You may not propagate or modify a covered work except as expressly 406 | provided under this License. Any attempt otherwise to propagate or 407 | modify it is void, and will automatically terminate your rights under 408 | this License (including any patent licenses granted under the third 409 | paragraph of section 11). 410 | 411 | However, if you cease all violation of this License, then your license 412 | from a particular copyright holder is reinstated (a) provisionally, 413 | unless and until the copyright holder explicitly and finally 414 | terminates your license, and (b) permanently, if the copyright holder 415 | fails to notify you of the violation by some reasonable means prior to 416 | 60 days after the cessation. 417 | 418 | Moreover, your license from a particular copyright holder is 419 | reinstated permanently if the copyright holder notifies you of the 420 | violation by some reasonable means, this is the first time you have 421 | received notice of violation of this License (for any work) from that 422 | copyright holder, and you cure the violation prior to 30 days after 423 | your receipt of the notice. 424 | 425 | Termination of your rights under this section does not terminate the 426 | licenses of parties who have received copies or rights from you under 427 | this License. If your rights have been terminated and not permanently 428 | reinstated, you do not qualify to receive new licenses for the same 429 | material under section 10. 430 | 431 | #### 9. Acceptance Not Required for Having Copies. 432 | 433 | You are not required to accept this License in order to receive or run 434 | a copy of the Program. Ancillary propagation of a covered work 435 | occurring solely as a consequence of using peer-to-peer transmission 436 | to receive a copy likewise does not require acceptance. However, 437 | nothing other than this License grants you permission to propagate or 438 | modify any covered work. These actions infringe copyright if you do 439 | not accept this License. Therefore, by modifying or propagating a 440 | covered work, you indicate your acceptance of this License to do so. 441 | 442 | #### 10. Automatic Licensing of Downstream Recipients. 443 | 444 | Each time you convey a covered work, the recipient automatically 445 | receives a license from the original licensors, to run, modify and 446 | propagate that work, subject to this License. You are not responsible 447 | for enforcing compliance by third parties with this License. 448 | 449 | An "entity transaction" is a transaction transferring control of an 450 | organization, or substantially all assets of one, or subdividing an 451 | organization, or merging organizations. If propagation of a covered 452 | work results from an entity transaction, each party to that 453 | transaction who receives a copy of the work also receives whatever 454 | licenses to the work the party's predecessor in interest had or could 455 | give under the previous paragraph, plus a right to possession of the 456 | Corresponding Source of the work from the predecessor in interest, if 457 | the predecessor has it or can get it with reasonable efforts. 458 | 459 | You may not impose any further restrictions on the exercise of the 460 | rights granted or affirmed under this License. For example, you may 461 | not impose a license fee, royalty, or other charge for exercise of 462 | rights granted under this License, and you may not initiate litigation 463 | (including a cross-claim or counterclaim in a lawsuit) alleging that 464 | any patent claim is infringed by making, using, selling, offering for 465 | sale, or importing the Program or any portion of it. 466 | 467 | #### 11. Patents. 468 | 469 | A "contributor" is a copyright holder who authorizes use under this 470 | License of the Program or a work on which the Program is based. The 471 | work thus licensed is called the contributor's "contributor version". 472 | 473 | A contributor's "essential patent claims" are all patent claims owned 474 | or controlled by the contributor, whether already acquired or 475 | hereafter acquired, that would be infringed by some manner, permitted 476 | by this License, of making, using, or selling its contributor version, 477 | but do not include claims that would be infringed only as a 478 | consequence of further modification of the contributor version. For 479 | purposes of this definition, "control" includes the right to grant 480 | patent sublicenses in a manner consistent with the requirements of 481 | this License. 482 | 483 | Each contributor grants you a non-exclusive, worldwide, royalty-free 484 | patent license under the contributor's essential patent claims, to 485 | make, use, sell, offer for sale, import and otherwise run, modify and 486 | propagate the contents of its contributor version. 487 | 488 | In the following three paragraphs, a "patent license" is any express 489 | agreement or commitment, however denominated, not to enforce a patent 490 | (such as an express permission to practice a patent or covenant not to 491 | sue for patent infringement). To "grant" such a patent license to a 492 | party means to make such an agreement or commitment not to enforce a 493 | patent against the party. 494 | 495 | If you convey a covered work, knowingly relying on a patent license, 496 | and the Corresponding Source of the work is not available for anyone 497 | to copy, free of charge and under the terms of this License, through a 498 | publicly available network server or other readily accessible means, 499 | then you must either (1) cause the Corresponding Source to be so 500 | available, or (2) arrange to deprive yourself of the benefit of the 501 | patent license for this particular work, or (3) arrange, in a manner 502 | consistent with the requirements of this License, to extend the patent 503 | license to downstream recipients. "Knowingly relying" means you have 504 | actual knowledge that, but for the patent license, your conveying the 505 | covered work in a country, or your recipient's use of the covered work 506 | in a country, would infringe one or more identifiable patents in that 507 | country that you have reason to believe are valid. 508 | 509 | If, pursuant to or in connection with a single transaction or 510 | arrangement, you convey, or propagate by procuring conveyance of, a 511 | covered work, and grant a patent license to some of the parties 512 | receiving the covered work authorizing them to use, propagate, modify 513 | or convey a specific copy of the covered work, then the patent license 514 | you grant is automatically extended to all recipients of the covered 515 | work and works based on it. 516 | 517 | A patent license is "discriminatory" if it does not include within the 518 | scope of its coverage, prohibits the exercise of, or is conditioned on 519 | the non-exercise of one or more of the rights that are specifically 520 | granted under this License. You may not convey a covered work if you 521 | are a party to an arrangement with a third party that is in the 522 | business of distributing software, under which you make payment to the 523 | third party based on the extent of your activity of conveying the 524 | work, and under which the third party grants, to any of the parties 525 | who would receive the covered work from you, a discriminatory patent 526 | license (a) in connection with copies of the covered work conveyed by 527 | you (or copies made from those copies), or (b) primarily for and in 528 | connection with specific products or compilations that contain the 529 | covered work, unless you entered into that arrangement, or that patent 530 | license was granted, prior to 28 March 2007. 531 | 532 | Nothing in this License shall be construed as excluding or limiting 533 | any implied license or other defenses to infringement that may 534 | otherwise be available to you under applicable patent law. 535 | 536 | #### 12. No Surrender of Others' Freedom. 537 | 538 | If conditions are imposed on you (whether by court order, agreement or 539 | otherwise) that contradict the conditions of this License, they do not 540 | excuse you from the conditions of this License. If you cannot convey a 541 | covered work so as to satisfy simultaneously your obligations under 542 | this License and any other pertinent obligations, then as a 543 | consequence you may not convey it at all. For example, if you agree to 544 | terms that obligate you to collect a royalty for further conveying 545 | from those to whom you convey the Program, the only way you could 546 | satisfy both those terms and this License would be to refrain entirely 547 | from conveying the Program. 548 | 549 | #### 13. Use with the GNU Affero General Public License. 550 | 551 | Notwithstanding any other provision of this License, you have 552 | permission to link or combine any covered work with a work licensed 553 | under version 3 of the GNU Affero General Public License into a single 554 | combined work, and to convey the resulting work. The terms of this 555 | License will continue to apply to the part which is the covered work, 556 | but the special requirements of the GNU Affero General Public License, 557 | section 13, concerning interaction through a network will apply to the 558 | combination as such. 559 | 560 | #### 14. Revised Versions of this License. 561 | 562 | The Free Software Foundation may publish revised and/or new versions 563 | of the GNU General Public License from time to time. Such new versions 564 | will be similar in spirit to the present version, but may differ in 565 | detail to address new problems or concerns. 566 | 567 | Each version is given a distinguishing version number. If the Program 568 | specifies that a certain numbered version of the GNU General Public 569 | License "or any later version" applies to it, you have the option of 570 | following the terms and conditions either of that numbered version or 571 | of any later version published by the Free Software Foundation. If the 572 | Program does not specify a version number of the GNU General Public 573 | License, you may choose any version ever published by the Free 574 | Software Foundation. 575 | 576 | If the Program specifies that a proxy can decide which future versions 577 | of the GNU General Public License can be used, that proxy's public 578 | statement of acceptance of a version permanently authorizes you to 579 | choose that version for the Program. 580 | 581 | Later license versions may give you additional or different 582 | permissions. However, no additional obligations are imposed on any 583 | author or copyright holder as a result of your choosing to follow a 584 | later version. 585 | 586 | #### 15. Disclaimer of Warranty. 587 | 588 | THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY 589 | APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT 590 | HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT 591 | WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT 592 | LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 593 | A PARTICULAR PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND 594 | PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE PROGRAM PROVE 595 | DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, REPAIR OR 596 | CORRECTION. 597 | 598 | #### 16. Limitation of Liability. 599 | 600 | IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING 601 | WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR 602 | CONVEYS THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, 603 | INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES 604 | ARISING OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT 605 | NOT LIMITED TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR 606 | LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM 607 | TO OPERATE WITH ANY OTHER PROGRAMS), EVEN IF SUCH HOLDER OR OTHER 608 | PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. 609 | 610 | #### 17. Interpretation of Sections 15 and 16. 611 | 612 | If the disclaimer of warranty and limitation of liability provided 613 | above cannot be given local legal effect according to their terms, 614 | reviewing courts shall apply local law that most closely approximates 615 | an absolute waiver of all civil liability in connection with the 616 | Program, unless a warranty or assumption of liability accompanies a 617 | copy of the Program in return for a fee. 618 | 619 | END OF TERMS AND CONDITIONS 620 | 621 | ### How to Apply These Terms to Your New Programs 622 | 623 | If you develop a new program, and you want it to be of the greatest 624 | possible use to the public, the best way to achieve this is to make it 625 | free software which everyone can redistribute and change under these 626 | terms. 627 | 628 | To do so, attach the following notices to the program. It is safest to 629 | attach them to the start of each source file to most effectively state 630 | the exclusion of warranty; and each file should have at least the 631 | "copyright" line and a pointer to where the full notice is found. 632 | 633 | 634 | Copyright (C) 635 | 636 | This program is free software: you can redistribute it and/or modify 637 | it under the terms of the GNU General Public License as published by 638 | the Free Software Foundation, either version 3 of the License, or 639 | (at your option) any later version. 640 | 641 | This program is distributed in the hope that it will be useful, 642 | but WITHOUT ANY WARRANTY; without even the implied warranty of 643 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 644 | GNU General Public License for more details. 645 | 646 | You should have received a copy of the GNU General Public License 647 | along with this program. If not, see . 648 | 649 | Also add information on how to contact you by electronic and paper 650 | mail. 651 | 652 | If the program does terminal interaction, make it output a short 653 | notice like this when it starts in an interactive mode: 654 | 655 | Copyright (C) 656 | This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'. 657 | This is free software, and you are welcome to redistribute it 658 | under certain conditions; type `show c' for details. 659 | 660 | The hypothetical commands \`show w' and \`show c' should show the 661 | appropriate parts of the General Public License. Of course, your 662 | program's commands might be different; for a GUI interface, you would 663 | use an "about box". 664 | 665 | You should also get your employer (if you work as a programmer) or 666 | school, if any, to sign a "copyright disclaimer" for the program, if 667 | necessary. For more information on this, and how to apply and follow 668 | the GNU GPL, see . 669 | 670 | The GNU General Public License does not permit incorporating your 671 | program into proprietary programs. If your program is a subroutine 672 | library, you may consider it more useful to permit linking proprietary 673 | applications with the library. If this is what you want to do, use the 674 | GNU Lesser General Public License instead of this License. But first, 675 | please read . -------------------------------------------------------------------------------- /MainUnit.dfm: -------------------------------------------------------------------------------- 1 | object MainForm: TMainForm 2 | Left = 0 3 | Top = 0 4 | Caption = 'KeePass4D' 5 | ClientHeight = 234 6 | ClientWidth = 506 7 | Color = clBtnFace 8 | Font.Charset = DEFAULT_CHARSET 9 | Font.Color = clWindowText 10 | Font.Height = -10 11 | Font.Name = 'Tahoma' 12 | Font.Style = [] 13 | OldCreateOrder = False 14 | ShowHint = True 15 | OnCreate = FormCreate 16 | OnDestroy = FormDestroy 17 | PixelsPerInch = 96 18 | TextHeight = 12 19 | object ActionMainMenuBar: TActionMainMenuBar 20 | Left = 0 21 | Top = 0 22 | Width = 506 23 | Height = 27 24 | UseSystemFont = False 25 | ActionManager = ActionManager 26 | Caption = 'ActionMainMenuBar' 27 | Color = clMenuBar 28 | ColorMap.DisabledFontColor = 7171437 29 | ColorMap.HighlightColor = clWhite 30 | ColorMap.BtnSelectedFont = clBlack 31 | ColorMap.UnusedColor = clWhite 32 | Font.Charset = DEFAULT_CHARSET 33 | Font.Color = clBlack 34 | Font.Height = -13 35 | Font.Name = 'Segoe UI' 36 | Font.Style = [] 37 | Spacing = 0 38 | end 39 | object StatusBar: TStatusBar 40 | Left = 0 41 | Top = 215 42 | Width = 506 43 | Height = 19 44 | Panels = < 45 | item 46 | Width = 150 47 | end 48 | item 49 | Width = -1 50 | end> 51 | end 52 | object MainActionToolBar: TActionToolBar 53 | Left = 0 54 | Top = 27 55 | Width = 506 56 | Height = 26 57 | ActionManager = ActionManager 58 | Caption = 'MainActionToolBar' 59 | Color = clMenuBar 60 | ColorMap.DisabledFontColor = 7171437 61 | ColorMap.HighlightColor = clWhite 62 | ColorMap.BtnSelectedFont = clBlack 63 | ColorMap.UnusedColor = clWhite 64 | Font.Charset = DEFAULT_CHARSET 65 | Font.Color = clBlack 66 | Font.Height = -11 67 | Font.Name = 'Tahoma' 68 | Font.Style = [] 69 | ParentFont = False 70 | Spacing = 0 71 | end 72 | object ActionManager: TActionManager 73 | ActionBars = < 74 | item 75 | Items = < 76 | item 77 | Items = < 78 | item 79 | Action = FileOpen 80 | ImageIndex = 0 81 | ShortCut = 16463 82 | end 83 | item 84 | Caption = '-' 85 | end 86 | item 87 | Action = FileExit1 88 | ImageIndex = 1 89 | end> 90 | Caption = '&File' 91 | end> 92 | ActionBar = ActionMainMenuBar 93 | end 94 | item 95 | Items.CaptionOptions = coNone 96 | Items = < 97 | item 98 | Action = FileOpen 99 | ImageIndex = 0 100 | ShortCut = 16463 101 | end> 102 | ActionBar = MainActionToolBar 103 | end> 104 | Images = MainImageList 105 | Left = 96 106 | Top = 64 107 | StyleName = 'Platform Default' 108 | object FileOpen: TFileOpen 109 | Category = 'File' 110 | Caption = '&Open...' 111 | Dialog.Filter = 'KeePass 2 files (*.kdbx)|*.kdbx|All files (*.*)|*.*' 112 | Hint = 'Open|Opens an existing file' 113 | ImageIndex = 0 114 | ShortCut = 16463 115 | OnAccept = FileOpenAccept 116 | end 117 | object FileExit1: TFileExit 118 | Category = 'File' 119 | Caption = 'E&xit' 120 | Hint = 'Exit|Quits the application' 121 | ImageIndex = 1 122 | end 123 | end 124 | object MainImageList: TImageList 125 | Left = 168 126 | Top = 64 127 | Bitmap = { 128 | 494C0101020008000C0010001000FFFFFFFFFF10FFFFFFFFFFFFFFFF424D3600 129 | 0000000000003600000028000000400000001000000001002000000000000010 130 | 0000000000000000000000000000000000000000000000000000000000000000 131 | 0000000000000000000000000000000000000000000000000000000000000000 132 | 0000000000000000000000000000000000008686860086868600868686008686 133 | 8600868686008686860086868600868686008686860086868600FFFFFF00C0C0 134 | C00086868600C0C0C000FFFFFF00C0C0C0000000000000000000000000000000 135 | 0000000000000000000000000000000000000000000000000000000000000000 136 | 0000000000000000000000000000000000000000000000000000000000000000 137 | 0000000000000000000000000000000000000000000000000000000000000000 138 | 0000000000000000000000000000000000000000000000000000000000000000 139 | 0000000000000000000000000000000000000000000000000000000000000000 140 | 0000000000000000000000000000000000008686860086868600868686008686 141 | 860086868600868686008686860086868600868686008686860086868600FFFF 142 | FF0086868600FFFFFF0086868600868686000000000000000000000000000000 143 | 0000000000000000000000000000000000000000000000000000000000000000 144 | 0000000000000000000000000000000000000000000000000000000000000000 145 | 0000000000000000000000000000000000000000000000000000000000000000 146 | 0000000000000000000000000000000000000000000000000000000000000000 147 | 0000000000000000000000000000000000000000000000000000000000000000 148 | 0000000000000000000000000000000000008000000080000000800000008000 149 | 00000000000000000000868686008686860086868600FFFFFF00FFFFFF00FFFF 150 | FF00800000008000000080000000800000000000000000000000000000000000 151 | 0000000000000000000000000000000000000000000000000000000000000000 152 | 0000000000000000000000000000000000000000000000000000000000000000 153 | 0000000000000000000000000000000000000000000000000000000000000000 154 | 0000000000000000000000000000000000000000000000000000008080000080 155 | 8000008080000080800000808000008080000080800000808000008080000000 156 | 0000000000000000000000000000000000000000000000000000000000008000 157 | 0000FF00000080000000000000000000000086868600FFFFFF00FFFFFF00FFFF 158 | FF00800000000000000000000000000000000000000000000000000000000000 159 | 0000000000000000000000000000000000000000000000000000000000000000 160 | 0000000000000000000000000000000000000000000000000000000000000000 161 | 0000000000000000000000000000000000000000000000000000000000000000 162 | 0000000000000000000000000000000000000000000000FFFF00000000000080 163 | 8000008080000080800000808000008080000080800000808000008080000080 164 | 8000000000000000000000000000000000000000000000000000000000008000 165 | 000080000000FF0000008000000000000000FFFFFF00FFFFFF00FFFFFF00FFFF 166 | FF00800000000000000000000000000000000000000000000000000000000000 167 | 0000000000000000000000000000000000000000000000000000000000000000 168 | 0000000000000000000000000000000000000000000000000000000000000000 169 | 0000000000000000000000000000000000000000000000000000000000000000 170 | 00000000000000000000000000000000000000000000FFFFFF0000FFFF000000 171 | 0000008080000080800000808000008080000080800000808000008080000080 172 | 8000008080000000000000000000000000000000000000000000000000008000 173 | 0000FF00000080000000FF00000000000000FFFFFF00FFFFFF00FFFFFF00FFFF 174 | FF00800000000000000000000000000000000000000000000000000000000000 175 | 0000000000000000000000000000000000000000000000000000000000000000 176 | 0000000000000000000000000000000000000000000000000000000000000000 177 | 0000000000000000000000000000000000000000000000000000000000000000 178 | 0000000000000000000000000000000000000000000000FFFF00FFFFFF0000FF 179 | FF00000000000080800000808000008080000080800000808000008080000080 180 | 8000008080000080800000000000000000000000000000000000000000008000 181 | 000080000000FF0000008000000000000000FFFFFF00FFFF0000FFFFFF00FFFF 182 | 0000800000000000000000000000000000000000000000000000000000000000 183 | 0000000000000000000000000000000000000000000000000000000000000000 184 | 0000000000000000000000000000000000000000000000000000000000000000 185 | 0000000000000000000000000000000000000000000000000000000000000000 186 | 00000000000000000000000000000000000000000000FFFFFF0000FFFF00FFFF 187 | FF0000FFFF000000000000000000000000000000000000000000000000000000 188 | 0000000000000000000000000000000000000000000000000000000000008000 189 | 0000FF00000080000000FF00000000000000FFFF0000FFFFFF00FFFF0000FFFF 190 | FF00800000000000000000000000000000000000000000000000000000000000 191 | 0000000000000000000000000000000000000000000000000000000000000000 192 | 0000000000000000000000000000000000000000000000000000000000000000 193 | 0000000000000000000000000000000000000000000000000000000000000000 194 | 0000000000000000000000000000000000000000000000FFFF00FFFFFF0000FF 195 | FF00FFFFFF0000FFFF00FFFFFF0000FFFF00FFFFFF0000FFFF00000000000000 196 | 0000000000000000000000000000000000000000000000000000000000008000 197 | 000080000000FF0000008000000000000000FFFFFF00FFFF0000FFFFFF00FFFF 198 | 0000800000000000000000000000000000000000000000000000000000000000 199 | 0000000000000000000000000000000000000000000000000000000000000000 200 | 0000000000000000000000000000000000000000000000000000000000000000 201 | 0000000000000000000000000000000000000000000000000000000000000000 202 | 00000000000000000000000000000000000000000000FFFFFF0000FFFF00FFFF 203 | FF0000FFFF00FFFFFF0000FFFF00FFFFFF0000FFFF00FFFFFF00000000000000 204 | 0000000000000000000000000000000000000000000000000000000000008000 205 | 0000FF00000080000000FF00000000000000FFFF0000FFFFFF00FFFF0000FFFF 206 | FF00800000000000000000000000000000000000000000000000000000000000 207 | 0000000000000000000000000000000000000000000000000000000000000000 208 | 0000000000000000000000000000000000000000000000000000000000000000 209 | 0000000000000000000000000000000000000000000000000000000000000000 210 | 0000000000000000000000000000000000000000000000FFFF00FFFFFF0000FF 211 | FF00000000000000000000000000000000000000000000000000000000000000 212 | 0000000000000000000000000000000000000000000000000000000000008000 213 | 0000800000008000000080000000800000008000000080000000800000008000 214 | 0000800000000000000000000000000000000000000000000000000000000000 215 | 0000000000000000000000000000000000000000000000000000000000000000 216 | 0000000000000000000000000000000000000000000000000000000000000000 217 | 0000000000000000000000000000000000000000000000000000000000000000 218 | 0000000000000000000000000000000000000000000000000000000000000000 219 | 0000000000000000000000000000000000000000000000000000000000000000 220 | 0000000000000000000000000000000000000000000000000000000000000000 221 | 0000000000000000000000000000000000000000000000000000000000000000 222 | 0000000000000000000000000000000000000000000000000000000000000000 223 | 0000000000000000000000000000000000000000000000000000000000000000 224 | 0000000000000000000000000000000000000000000000000000000000000000 225 | 0000000000000000000000000000000000000000000000000000000000000000 226 | 0000000000000000000000000000000000000000000000000000000000000000 227 | 0000000000000000000000000000000000000000000000000000000000000000 228 | 0000000000000000000000000000000000000000000000000000000000000000 229 | 0000000000000000000000000000000000000000000000000000000000000000 230 | 0000000000000000000000000000000000000000000000000000000000000000 231 | 0000000000000000000000000000000000000000000000000000000000000000 232 | 0000000000000000000000000000000000000000000000000000000000000000 233 | 0000000000000000000000000000000000000000000000000000000000000000 234 | 0000000000000000000000000000000000000000000000000000000000000000 235 | 0000000000000000000000000000000000000000000000000000000000000000 236 | 0000000000000000000000000000000000000000000000000000000000000000 237 | 0000000000000000000000800000008000000080000000800000000000000000 238 | 0000000000000000000000000000000000000000000000000000000000000000 239 | 0000000000000000000000000000000000000000000000000000000000000000 240 | 0000000000000000000000000000000000000000000000000000000000000000 241 | 0000000000000000000000000000000000000000000000000000000000000000 242 | 0000000000000000000000000000000000000000000000000000000000000000 243 | 0000000000000000000000000000000000000000000000000000000000000000 244 | 0000000000000000000000000000000000000000000000000000000000000000 245 | 0000000000000000000000000000000000000000000000000000000000000000 246 | 0000000000000000000000000000000000000000000000000000000000000000 247 | 0000000000000000000000000000000000000000000000000000000000000000 248 | 0000000000000000000000000000000000000000000000000000000000000000 249 | 0000000000000000000000000000000000000000000000000000000000000000 250 | 0000000000000000000000000000000000000000000000000000000000000000 251 | 0000000000000000000000000000000000000000000000000000000000000000 252 | 0000000000000000000000000000000000000000000000000000000000000000 253 | 0000000000000000000000000000000000000000000000000000000000000000 254 | 0000000000000000000000000000000000000000000000000000000000000000 255 | 0000000000000000000000000000000000000000000000000000000000000000 256 | 0000000000000000000000000000000000000000000000000000000000000000 257 | 0000000000000000000000000000000000000000000000000000000000000000 258 | 000000000000000000000000000000000000424D3E000000000000003E000000 259 | 2800000040000000100000000100010000000000800000000000000000000000 260 | 000000000000000000000000FFFFFF00FFFF000000000000FFFF000000000000 261 | 001F000000000000000FE007000000000007E007000000000003E00700000000 262 | 0001E007000000000000E00700000000001FE00700000000001FE00700000000 263 | 001FE007000000008FF1FFFF00000000FFF9F81F00000000FF75F81F00000000 264 | FF8FF81F00000000FFFFFFFF0000000000000000000000000000000000000000 265 | 000000000000} 266 | end 267 | object ApplicationEvents: TApplicationEvents 268 | OnHint = ApplicationEventsHint 269 | Left = 96 270 | Top = 120 271 | end 272 | end 273 | -------------------------------------------------------------------------------- /MainUnit.pas: -------------------------------------------------------------------------------- 1 | { This file is part of KeePass4D. 2 | 3 | KeePass4D is free software: you can redistribute it and/or modify 4 | it under the terms of the GNU General Public License as published by 5 | the Free Software Foundation, either version 3 of the License, or 6 | (at your option) any later version. 7 | 8 | KeePass4D is distributed in the hope that it will be useful, 9 | but WITHOUT ANY WARRANTY; without even the implied warranty of 10 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 11 | GNU General Public License for more details. 12 | 13 | You should have received a copy of the GNU General Public License 14 | along with KeePass4D. If not, see . } 15 | 16 | unit MainUnit; 17 | 18 | interface 19 | 20 | uses 21 | Winapi.Windows, Winapi.Messages, System.SysUtils, System.Variants, System.Classes, Vcl.Graphics, 22 | Vcl.Controls, Vcl.Forms, Vcl.Dialogs, Vcl.StdCtrls, System.Generics.Collections, System.Types, KeePassLib, 23 | PasswordUnit, System.Actions, Vcl.ActnList, Vcl.ToolWin, Vcl.ActnMan, 24 | Vcl.ActnCtrls, Vcl.ActnMenus, Vcl.PlatformDefaultStyleActnCtrls, Vcl.StdActns, 25 | System.ImageList, Vcl.ImgList, Vcl.ComCtrls, Vcl.AppEvnts, System.IOUtils, 26 | System.UITypes; 27 | 28 | const 29 | DefaultApplicationTitle = 'KeePass4D'; 30 | 31 | type 32 | TMainForm = class(TForm) 33 | ActionManager: TActionManager; 34 | ActionMainMenuBar: TActionMainMenuBar; 35 | MainImageList: TImageList; 36 | FileOpen: TFileOpen; 37 | StatusBar: TStatusBar; 38 | MainActionToolBar: TActionToolBar; 39 | ApplicationEvents: TApplicationEvents; 40 | FileExit1: TFileExit; 41 | procedure FileOpenAccept(Sender: TObject); 42 | procedure ApplicationEventsHint(Sender: TObject); 43 | procedure FormCreate(Sender: TObject); 44 | procedure FormDestroy(Sender: TObject); 45 | private 46 | { Private declarations } 47 | FKdbx: TKdbxFile; 48 | FFileName: string; 49 | public 50 | { Public declarations } 51 | end; 52 | 53 | var 54 | MainForm: TMainForm; 55 | 56 | implementation 57 | 58 | {$R *.dfm} 59 | 60 | uses 61 | KeePassLib.Wincrypt, KeePassLib.Bcrypt, System.Hash, 62 | System.Security.Cryptography; 63 | 64 | procedure TMainForm.ApplicationEventsHint(Sender: TObject); 65 | begin 66 | StatusBar.Panels[1].Text := Application.Hint; 67 | end; 68 | 69 | procedure TMainForm.FileOpenAccept(Sender: TObject); 70 | var 71 | PasswordIsCorrect: Boolean; 72 | mr: Integer; 73 | begin 74 | PasswordIsCorrect := False; 75 | 76 | PasswordForm := TPasswordForm.Create(Self); 77 | try 78 | 79 | repeat 80 | mr := PasswordForm.ShowModal; 81 | if mr = mrCancel then 82 | Break; 83 | 84 | try 85 | FKdbx.LoadFromFile(PasswordForm.Password, FileOpen.Dialog.FileName); 86 | PasswordIsCorrect := True; 87 | FFileName := FileOpen.Dialog.FileName; 88 | Caption := Format('%s - %s', [DefaultApplicationTitle, TPath.GetFileNameWithoutExtension(FFileName)]); 89 | except 90 | on E: EKdbxPasswordError do 91 | begin 92 | PasswordIsCorrect := False; 93 | MessageDlg('Password is incorrect!', mtError, [mbOk], 0); 94 | end 95 | end; 96 | until PasswordIsCorrect = True; 97 | 98 | finally 99 | PasswordForm.Free; 100 | end; 101 | end; 102 | 103 | procedure TMainForm.FormCreate(Sender: TObject); 104 | begin 105 | FKdbx := TKdbxFile.Create; 106 | end; 107 | 108 | procedure TMainForm.FormDestroy(Sender: TObject); 109 | begin 110 | FKdbx.Free; 111 | end; 112 | 113 | end. 114 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # KeePass4D 2 | 3 | KeePass4D is password manager written in Delphi with Kdbx format support. 4 | -------------------------------------------------------------------------------- /TODO.md: -------------------------------------------------------------------------------- 1 | # Todo list 2 | 3 | ## v1.0 4 | 5 | * Reading and KeePass Kdbx & Kdb files. 6 | --------------------------------------------------------------------------------