├── .gitattributes ├── .gitignore ├── CSPRNG.Delphi.groupproj ├── README.md ├── sample ├── CSPRNG_FMX.dpr ├── CSPRNG_FMX.dproj ├── CSPRNG_FMX.res ├── CSPRNG_FMX_Main.fmx ├── CSPRNG_FMX_Main.pas ├── CSPRNG_sample.dpr ├── CSPRNG_sample.dproj └── CSPRNG_sample.res ├── src ├── CSPRNG.Interfaces.pas ├── CSPRNG.Provider.Base.pas ├── CSPRNG.Provider.MacOS64.pas ├── CSPRNG.Provider.Posix.pas ├── CSPRNG.Provider.Windows.pas ├── CSPRNG.Provider.iOS.pas ├── CSPRNG.pas ├── CSPRNG_sample.dpr ├── CSPRNG_sample.dproj └── CSPRNG_sample.res └── tests ├── CSPRNG.Tests.Providers.pas ├── CSPRNG.Tests.dpr ├── CSPRNG.Tests.dproj ├── CSPRNG.Tests.res ├── Win32 └── Debug │ ├── TestInsightSettings.ini │ └── dunitx-results.xml └── Win64 └── Debug └── dunitx-results.xml /.gitattributes: -------------------------------------------------------------------------------- 1 | # Set the default behavior, in case people don't have core.autocrlf set. 2 | #* binary 3 | 4 | # Core files that needs lf ending 5 | *.gitattributes text eol=lf diff 6 | *.gitignore text eol=lf diff 7 | 8 | # Declare text files that will always have CRLF line endings on checkout 9 | *.txt text eol=crlf diff 10 | *.md text eol=crlf diff 11 | *.xml text eol=crlf diff 12 | *.json text eol=crlf diff 13 | *.manifest text eol=crlf diff 14 | *.rc text eol=crlf diff 15 | *.bat text eol=crlf diff 16 | 17 | # Delphi specific text files that will always have CRLF line endings on checkout 18 | *.pas text eol=crlf diff 19 | *.inc text eol=crlf diff 20 | *.dfm text eol=crlf diff 21 | *.fmx text eol=crlf diff 22 | *.dpr text eol=crlf diff 23 | *.dpk text eol=crlf diff 24 | *.dproj text eol=crlf diff 25 | *.groupproj text eol=crlf diff 26 | *.deployproj text eol=crlf diff 27 | *.plist text eol=lf diff 28 | 29 | # Misc text files that will always have CRLF line endings on checkout 30 | *.cpp text eol=crlf diff 31 | *.h text eol=crlf diff 32 | *.hpp text eol=crlf diff 33 | *.asm text eol=crlf diff 34 | *.ps1 text eol=crlf diff 35 | *.prjmgc text eol=crlf diff 36 | *.sql text eol=crlf diff 37 | -------------------------------------------------------------------------------- /.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 | *.res 53 | 54 | # Delphi local files (user-specific info) 55 | *.local 56 | *.identcache 57 | *.projdata 58 | *.tvsconfig 59 | *.dsk 60 | 61 | # Delphi history and backups 62 | __history/ 63 | __recovery/ 64 | *.~* 65 | 66 | # Castalia statistics file (since XE7 Castalia is distributed with Delphi) 67 | *.stat 68 | 69 | # Boss dependency manager vendor folder https://github.com/HashLoad/boss 70 | modules/ 71 | 72 | # Build folders 73 | **/Debug/ 74 | **/Relase/ 75 | 76 | AndroidManifest.template.xml 77 | *.deployproj 78 | *.res 79 | -------------------------------------------------------------------------------- /CSPRNG.Delphi.groupproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | {979A6A91-DCB4-482C-AC19-E7D9A41B18D6} 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | Default.Personality.12 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # [DelphiCSPRNG](https://github.com/jimmckeeth/DelphiCSPRNG) 2 | _A cross-platform Cryptographically-Secure Pseudo-Random Number Generator for Delphi_ 3 | 4 | I wanted an easy to use cross-platform random number generator that was more reliable than the built in Random. It is modular so you can just include the parts you want. Makes use of the platform secure random provider for each platform, with a common provider interface. I've only tested it on Win32, Win64, Android64, and Linux64. 5 | 6 | There are some basic tests and a sample app. Open to feedback, [issues](https://github.com/jimmckeeth/DelphiCSPRNG/issue) reports, and [pull requests](https://github.com/jimmckeeth/DelphiCSPRNG/fork). Especially if you want to test it on Apple hardware. 7 | 8 | **Disclaimer**: _Make sure you understand any code before using it for anything important._ Just because I am calling this "Cryptographically-Secure" doesn't necessarily mean it is secure or suitable for cryptography. 9 | 10 | ## Basic usage 11 | 12 | ```Delphi 13 | uses CSPRNG, CSPRNG.Interfaces; 14 | 15 | /// 16 | var rng: ICSPRNGProvider := GetCSPRNGProvider; 17 | Writeln(rng.GetFloat); 18 | Writeln(rng.GetUInt64); 19 | Writeln(rng.GetBase64); 20 | ``` 21 | 22 | ## The provider interface 23 | 24 | ```Delphi 25 | type 26 | ICSPRNGProvider = interface 27 | // Generates a specified number of cryptographically secure random bytes. 28 | function GetBytes(const Count: Integer): TBytes; 29 | 30 | // Generates a cryptographically secure random unsigned 32-bit integer. 31 | function GetUInt32(const max: UInt32 = High(UInt32)): UInt32; 32 | 33 | // Generates a cryptographically secure random signed 32-bit integer. 34 | function GetInt32(const max: Int32 = High(Int32)): Int32; 35 | 36 | // Generates a cryptographically secure random signed 64-bit integer. 37 | function GetInt64(const max: Int64 = High(Int64)): Int64; 38 | 39 | // Generates a cryptographically secure random unsigned 64-bit integer. 40 | function GetUInt64(const max: UInt64 = High(UInt64)): UInt64; 41 | 42 | // Generates a cryptographically secure random float between 0 and 1 43 | function GetFloat: Double; 44 | 45 | // Generates a BASE64 encoded random string 46 | function GetBase64(const len: Integer = 1024): String; 47 | end; 48 | ``` 49 | 50 | Most of the functionality comes from the base implementation, with the platform specific implementation providing the **`GetBytes`** function. 51 | -------------------------------------------------------------------------------- /sample/CSPRNG_FMX.dpr: -------------------------------------------------------------------------------- 1 | program CSPRNG_FMX; 2 | 3 | uses 4 | System.StartUpCopy, 5 | FMX.Forms, 6 | CSPRNG_FMX_Main in 'CSPRNG_FMX_Main.pas' {Form28}; 7 | 8 | {$R *.res} 9 | 10 | begin 11 | Application.Initialize; 12 | Application.CreateForm(TForm28, Form28); 13 | Application.Run; 14 | end. 15 | -------------------------------------------------------------------------------- /sample/CSPRNG_FMX.dproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | True 4 | Application 5 | Debug 6 | FMX 7 | CSPRNG_FMX.dpr 8 | Win32 9 | {152D4698-4EAC-4079-9777-B9318D4E12A3} 10 | CSPRNG_FMX 11 | 20.2 12 | 693267 13 | 14 | 15 | true 16 | 17 | 18 | true 19 | Base 20 | true 21 | 22 | 23 | true 24 | Base 25 | true 26 | 27 | 28 | true 29 | Base 30 | true 31 | 32 | 33 | true 34 | Base 35 | true 36 | 37 | 38 | true 39 | Base 40 | true 41 | 42 | 43 | true 44 | Base 45 | true 46 | 47 | 48 | true 49 | Base 50 | true 51 | 52 | 53 | true 54 | Base 55 | true 56 | 57 | 58 | true 59 | Base 60 | true 61 | 62 | 63 | true 64 | Cfg_1 65 | true 66 | true 67 | 68 | 69 | true 70 | Cfg_1 71 | true 72 | true 73 | 74 | 75 | true 76 | Base 77 | true 78 | 79 | 80 | true 81 | Cfg_2 82 | true 83 | true 84 | 85 | 86 | true 87 | Cfg_2 88 | true 89 | true 90 | 91 | 92 | CSPRNG_FMX 93 | true 94 | true 95 | true 96 | true 97 | true 98 | true 99 | true 100 | true 101 | .\$(Platform)\$(Config) 102 | .\$(Platform)\$(Config) 103 | System;Xml;Data;Datasnap;Web;Soap;$(DCC_Namespace) 104 | ..\src;$(DCC_UnitSearchPath) 105 | $(BDS)\bin\delphi_PROJECTICNS.icns 106 | $(BDS)\bin\delphi_PROJECTICON.ico 107 | 108 | 109 | $(BDS)\bin\Artwork\Android\FM_AdaptiveIcon_Background.xml 110 | $(BDS)\bin\Artwork\Android\FM_AdaptiveIcon_Foreground.xml 111 | $(BDS)\bin\Artwork\Android\FM_AdaptiveIcon_Monochrome.xml 112 | $(BDS)\bin\Artwork\Android\FM_LauncherIcon_144x144.png 113 | $(BDS)\bin\Artwork\Android\FM_LauncherIcon_192x192.png 114 | $(BDS)\bin\Artwork\Android\FM_LauncherIcon_36x36.png 115 | $(BDS)\bin\Artwork\Android\FM_LauncherIcon_48x48.png 116 | $(BDS)\bin\Artwork\Android\FM_LauncherIcon_72x72.png 117 | $(BDS)\bin\Artwork\Android\FM_LauncherIcon_96x96.png 118 | $(BDS)\bin\Artwork\Android\FM_NotificationIcon_24x24.png 119 | $(BDS)\bin\Artwork\Android\FM_NotificationIcon_36x36.png 120 | $(BDS)\bin\Artwork\Android\FM_NotificationIcon_48x48.png 121 | $(BDS)\bin\Artwork\Android\FM_NotificationIcon_72x72.png 122 | $(BDS)\bin\Artwork\Android\FM_NotificationIcon_96x96.png 123 | $(BDS)\bin\Artwork\Android\FM_SplashImage_426x320.png 124 | $(BDS)\bin\Artwork\Android\FM_SplashImage_470x320.png 125 | $(BDS)\bin\Artwork\Android\FM_SplashImage_640x480.png 126 | $(BDS)\bin\Artwork\Android\FM_SplashImage_960x720.png 127 | $(BDS)\bin\Artwork\Android\FM_VectorizedNotificationIcon.xml 128 | $(BDS)\bin\Artwork\Android\FM_VectorizedSplash.xml 129 | $(BDS)\bin\Artwork\Android\FM_VectorizedSplashDark.xml 130 | $(BDS)\bin\Artwork\Android\FM_VectorizedSplashV31.xml 131 | $(BDS)\bin\Artwork\Android\FM_VectorizedSplashV31Dark.xml 132 | Debug 133 | fmx;DbxCommonDriver;bindengine;IndyIPCommon;emsclient;IndyProtocols;dbxcds;FmxTeeUI;FireDACSqliteDriver;DbxClientDriver;soapmidas;dbexpress;inet;FireDACDBXDriver;CustomIPTransport;IndySystem;FireDACCommon;emsserverresource;bindcompdbx;rtl;DBXSqliteDriver;DataSnapFireDAC;FireDAC;xmlrtl;dsnap;DataSnapNativeClient;emshosting;FireDACCommonDriver;IndyIPClient;emsedge;bindcompfmx;fmxFireDAC;DataSnapCommon;fmxase;dbrtl;DBXInterBaseDriver;bindcomp;inetstn;IndyCore;RESTBackendComponents;AWSSDKFMX;RESTComponents;IndyIPServer;dsnapxml;DataSnapClient;DataSnapProviderClient;emsclientfiredac;FireDACDSDriver;tethering;CloudService;FMXTee;soaprtl;soapserver;FireDACIBDriver;$(DCC_UsePackage) 134 | activity-1.7.2.dex.jar;annotation-experimental-1.3.0.dex.jar;annotation-jvm-1.6.0.dex.jar;annotations-13.0.dex.jar;appcompat-1.2.0.dex.jar;appcompat-resources-1.2.0.dex.jar;billing-6.0.1.dex.jar;biometric-1.1.0.dex.jar;browser-1.4.0.dex.jar;cloud-messaging.dex.jar;collection-1.1.0.dex.jar;concurrent-futures-1.1.0.dex.jar;core-1.10.1.dex.jar;core-common-2.2.0.dex.jar;core-ktx-1.10.1.dex.jar;core-runtime-2.2.0.dex.jar;cursoradapter-1.0.0.dex.jar;customview-1.0.0.dex.jar;documentfile-1.0.0.dex.jar;drawerlayout-1.0.0.dex.jar;error_prone_annotations-2.9.0.dex.jar;exifinterface-1.3.6.dex.jar;firebase-annotations-16.2.0.dex.jar;firebase-common-20.3.1.dex.jar;firebase-components-17.1.0.dex.jar;firebase-datatransport-18.1.7.dex.jar;firebase-encoders-17.0.0.dex.jar;firebase-encoders-json-18.0.0.dex.jar;firebase-encoders-proto-16.0.0.dex.jar;firebase-iid-interop-17.1.0.dex.jar;firebase-installations-17.1.3.dex.jar;firebase-installations-interop-17.1.0.dex.jar;firebase-measurement-connector-19.0.0.dex.jar;firebase-messaging-23.1.2.dex.jar;fmx.dex.jar;fragment-1.2.5.dex.jar;google-play-licensing.dex.jar;interpolator-1.0.0.dex.jar;javax.inject-1.dex.jar;kotlin-stdlib-1.8.22.dex.jar;kotlin-stdlib-common-1.8.22.dex.jar;kotlin-stdlib-jdk7-1.8.22.dex.jar;kotlin-stdlib-jdk8-1.8.22.dex.jar;kotlinx-coroutines-android-1.6.4.dex.jar;kotlinx-coroutines-core-jvm-1.6.4.dex.jar;legacy-support-core-utils-1.0.0.dex.jar;lifecycle-common-2.6.1.dex.jar;lifecycle-livedata-2.6.1.dex.jar;lifecycle-livedata-core-2.6.1.dex.jar;lifecycle-runtime-2.6.1.dex.jar;lifecycle-service-2.6.1.dex.jar;lifecycle-viewmodel-2.6.1.dex.jar;lifecycle-viewmodel-savedstate-2.6.1.dex.jar;listenablefuture-1.0.dex.jar;loader-1.0.0.dex.jar;localbroadcastmanager-1.0.0.dex.jar;okio-jvm-3.4.0.dex.jar;play-services-ads-22.2.0.dex.jar;play-services-ads-base-22.2.0.dex.jar;play-services-ads-identifier-18.0.0.dex.jar;play-services-ads-lite-22.2.0.dex.jar;play-services-appset-16.0.1.dex.jar;play-services-base-18.1.0.dex.jar;play-services-basement-18.1.0.dex.jar;play-services-cloud-messaging-17.0.1.dex.jar;play-services-location-21.0.1.dex.jar;play-services-maps-18.1.0.dex.jar;play-services-measurement-base-20.1.2.dex.jar;play-services-measurement-sdk-api-20.1.2.dex.jar;play-services-stats-17.0.2.dex.jar;play-services-tasks-18.0.2.dex.jar;print-1.0.0.dex.jar;profileinstaller-1.3.0.dex.jar;room-common-2.2.5.dex.jar;room-runtime-2.2.5.dex.jar;savedstate-1.2.1.dex.jar;sqlite-2.1.0.dex.jar;sqlite-framework-2.1.0.dex.jar;startup-runtime-1.1.1.dex.jar;tracing-1.0.0.dex.jar;transport-api-3.0.0.dex.jar;transport-backend-cct-3.1.8.dex.jar;transport-runtime-3.1.8.dex.jar;user-messaging-platform-2.0.0.dex.jar;vectordrawable-1.1.0.dex.jar;vectordrawable-animated-1.1.0.dex.jar;versionedparcelable-1.1.1.dex.jar;viewpager-1.0.0.dex.jar;work-runtime-2.7.0.dex.jar 135 | true 136 | false 137 | true 138 | true 139 | true 140 | package=com.embarcadero.$(MSBuildProjectName);label=$(MSBuildProjectName);versionCode=1;versionName=1.0.0;persistent=False;restoreAnyVersion=False;installLocation=auto;largeHeap=False;theme=TitleBar;hardwareAccelerated=true;apiKey=;minSdkVersion=23;targetSdkVersion=34 141 | 142 | 143 | $(BDS)\bin\Artwork\Android\FM_AdaptiveIcon_Background.xml 144 | $(BDS)\bin\Artwork\Android\FM_AdaptiveIcon_Foreground.xml 145 | $(BDS)\bin\Artwork\Android\FM_AdaptiveIcon_Monochrome.xml 146 | $(BDS)\bin\Artwork\Android\FM_LauncherIcon_144x144.png 147 | $(BDS)\bin\Artwork\Android\FM_LauncherIcon_192x192.png 148 | $(BDS)\bin\Artwork\Android\FM_LauncherIcon_36x36.png 149 | $(BDS)\bin\Artwork\Android\FM_LauncherIcon_48x48.png 150 | $(BDS)\bin\Artwork\Android\FM_LauncherIcon_72x72.png 151 | $(BDS)\bin\Artwork\Android\FM_LauncherIcon_96x96.png 152 | $(BDS)\bin\Artwork\Android\FM_NotificationIcon_24x24.png 153 | $(BDS)\bin\Artwork\Android\FM_NotificationIcon_36x36.png 154 | $(BDS)\bin\Artwork\Android\FM_NotificationIcon_48x48.png 155 | $(BDS)\bin\Artwork\Android\FM_NotificationIcon_72x72.png 156 | $(BDS)\bin\Artwork\Android\FM_NotificationIcon_96x96.png 157 | $(BDS)\bin\Artwork\Android\FM_SplashImage_426x320.png 158 | $(BDS)\bin\Artwork\Android\FM_SplashImage_470x320.png 159 | $(BDS)\bin\Artwork\Android\FM_SplashImage_640x480.png 160 | $(BDS)\bin\Artwork\Android\FM_SplashImage_960x720.png 161 | $(BDS)\bin\Artwork\Android\FM_VectorizedNotificationIcon.xml 162 | $(BDS)\bin\Artwork\Android\FM_VectorizedSplash.xml 163 | $(BDS)\bin\Artwork\Android\FM_VectorizedSplashDark.xml 164 | $(BDS)\bin\Artwork\Android\FM_VectorizedSplashV31.xml 165 | $(BDS)\bin\Artwork\Android\FM_VectorizedSplashV31Dark.xml 166 | Debug 167 | fmx;DbxCommonDriver;bindengine;IndyIPCommon;emsclient;IndyProtocols;dbxcds;FmxTeeUI;FireDACSqliteDriver;DbxClientDriver;soapmidas;dbexpress;inet;FireDACDBXDriver;CustomIPTransport;IndySystem;FireDACCommon;emsserverresource;bindcompdbx;rtl;DBXSqliteDriver;DataSnapFireDAC;FireDAC;xmlrtl;dsnap;DataSnapNativeClient;emshosting;FireDACCommonDriver;IndyIPClient;emsedge;bindcompfmx;fmxFireDAC;DataSnapCommon;dbrtl;DBXInterBaseDriver;bindcomp;inetstn;IndyCore;RESTBackendComponents;AWSSDKFMX;RESTComponents;IndyIPServer;dsnapxml;DataSnapClient;DataSnapProviderClient;emsclientfiredac;FireDACDSDriver;tethering;CloudService;FMXTee;soaprtl;soapserver;FireDACIBDriver;$(DCC_UsePackage) 168 | activity-1.7.2.dex.jar;annotation-experimental-1.3.0.dex.jar;annotation-jvm-1.6.0.dex.jar;annotations-13.0.dex.jar;appcompat-1.2.0.dex.jar;appcompat-resources-1.2.0.dex.jar;billing-6.0.1.dex.jar;biometric-1.1.0.dex.jar;browser-1.4.0.dex.jar;cloud-messaging.dex.jar;collection-1.1.0.dex.jar;concurrent-futures-1.1.0.dex.jar;core-1.10.1.dex.jar;core-common-2.2.0.dex.jar;core-ktx-1.10.1.dex.jar;core-runtime-2.2.0.dex.jar;cursoradapter-1.0.0.dex.jar;customview-1.0.0.dex.jar;documentfile-1.0.0.dex.jar;drawerlayout-1.0.0.dex.jar;error_prone_annotations-2.9.0.dex.jar;exifinterface-1.3.6.dex.jar;firebase-annotations-16.2.0.dex.jar;firebase-common-20.3.1.dex.jar;firebase-components-17.1.0.dex.jar;firebase-datatransport-18.1.7.dex.jar;firebase-encoders-17.0.0.dex.jar;firebase-encoders-json-18.0.0.dex.jar;firebase-encoders-proto-16.0.0.dex.jar;firebase-iid-interop-17.1.0.dex.jar;firebase-installations-17.1.3.dex.jar;firebase-installations-interop-17.1.0.dex.jar;firebase-measurement-connector-19.0.0.dex.jar;firebase-messaging-23.1.2.dex.jar;fmx.dex.jar;fragment-1.2.5.dex.jar;google-play-licensing.dex.jar;interpolator-1.0.0.dex.jar;javax.inject-1.dex.jar;kotlin-stdlib-1.8.22.dex.jar;kotlin-stdlib-common-1.8.22.dex.jar;kotlin-stdlib-jdk7-1.8.22.dex.jar;kotlin-stdlib-jdk8-1.8.22.dex.jar;kotlinx-coroutines-android-1.6.4.dex.jar;kotlinx-coroutines-core-jvm-1.6.4.dex.jar;legacy-support-core-utils-1.0.0.dex.jar;lifecycle-common-2.6.1.dex.jar;lifecycle-livedata-2.6.1.dex.jar;lifecycle-livedata-core-2.6.1.dex.jar;lifecycle-runtime-2.6.1.dex.jar;lifecycle-service-2.6.1.dex.jar;lifecycle-viewmodel-2.6.1.dex.jar;lifecycle-viewmodel-savedstate-2.6.1.dex.jar;listenablefuture-1.0.dex.jar;loader-1.0.0.dex.jar;localbroadcastmanager-1.0.0.dex.jar;okio-jvm-3.4.0.dex.jar;play-services-ads-22.2.0.dex.jar;play-services-ads-base-22.2.0.dex.jar;play-services-ads-identifier-18.0.0.dex.jar;play-services-ads-lite-22.2.0.dex.jar;play-services-appset-16.0.1.dex.jar;play-services-base-18.1.0.dex.jar;play-services-basement-18.1.0.dex.jar;play-services-cloud-messaging-17.0.1.dex.jar;play-services-location-21.0.1.dex.jar;play-services-maps-18.1.0.dex.jar;play-services-measurement-base-20.1.2.dex.jar;play-services-measurement-sdk-api-20.1.2.dex.jar;play-services-stats-17.0.2.dex.jar;play-services-tasks-18.0.2.dex.jar;print-1.0.0.dex.jar;profileinstaller-1.3.0.dex.jar;room-common-2.2.5.dex.jar;room-runtime-2.2.5.dex.jar;savedstate-1.2.1.dex.jar;sqlite-2.1.0.dex.jar;sqlite-framework-2.1.0.dex.jar;startup-runtime-1.1.1.dex.jar;tracing-1.0.0.dex.jar;transport-api-3.0.0.dex.jar;transport-backend-cct-3.1.8.dex.jar;transport-runtime-3.1.8.dex.jar;user-messaging-platform-2.0.0.dex.jar;vectordrawable-1.1.0.dex.jar;vectordrawable-animated-1.1.0.dex.jar;versionedparcelable-1.1.1.dex.jar;viewpager-1.0.0.dex.jar;work-runtime-2.7.0.dex.jar 169 | true 170 | false 171 | true 172 | true 173 | true 174 | package=com.embarcadero.$(MSBuildProjectName);label=$(MSBuildProjectName);versionCode=1;versionName=1.0.0;persistent=False;restoreAnyVersion=False;installLocation=auto;largeHeap=False;theme=TitleBar;hardwareAccelerated=true;apiKey=;minSdkVersion=23;targetSdkVersion=34 175 | 176 | 177 | Debug 178 | DataSnapServer;fmx;DbxCommonDriver;bindengine;IndyIPCommon;FireDACCommonODBC;emsclient;IndyProtocols;dbxcds;FmxTeeUI;DBXFirebirdDriver;FireDACSqliteDriver;DbxClientDriver;soapmidas;dbexpress;inet;FireDACDBXDriver;fmxdae;CustomIPTransport;FireDACMSSQLDriver;IndySystem;FireDACCommon;DataSnapServerMidas;FireDACODBCDriver;emsserverresource;bindcompdbx;rtl;FireDACMySQLDriver;DBXSqliteDriver;DataSnapFireDAC;inetdbxpress;FireDAC;xmlrtl;dsnap;DBXOracleDriver;DBXInformixDriver;fmxobj;DataSnapNativeClient;emshosting;FireDACCommonDriver;IndyIPClient;emsedge;bindcompfmx;inetdb;FireDACASADriver;fmxFireDAC;DBXMySQLDriver;DataSnapCommon;fmxase;dbrtl;FireDACOracleDriver;DataSnapIndy10ServerTransport;DBXInterBaseDriver;FireDACMongoDBDriver;FireDACTDataDriver;bindcomp;inetstn;IndyCore;RESTBackendComponents;AWSSDKFMX;RESTComponents;IndyIPServer;dsnapxml;DataSnapClient;DataSnapProviderClient;emsclientfiredac;FireDACPgDriver;FireDACDSDriver;tethering;CloudService;DBXSybaseASADriver;FMXTee;soaprtl;soapserver;FireDACIBDriver;$(DCC_UsePackage) 179 | true 180 | CFBundleName=$(MSBuildProjectName);CFBundleDisplayName=$(MSBuildProjectName);CFBundleIdentifier=$(MSBuildProjectName);CFBundleVersion=1.0.0;CFBundleShortVersionString=1.0.0;CFBundlePackageType=APPL;CFBundleSignature=????;CFBundleAllowMixedLocalizations=YES;CFBundleExecutable=$(MSBuildProjectName);NSHighResolutionCapable=true;LSApplicationCategoryType=public.app-category.utilities;NSLocationUsageDescription=The reason for accessing the location information of the user;NSContactsUsageDescription=The reason for accessing the contacts;NSCalendarsUsageDescription=The reason for accessing the calendar data;NSRemindersUsageDescription=The reason for accessing the reminders;NSCameraUsageDescription=The reason for accessing the camera;NSMicrophoneUsageDescription=The reason for accessing the microphone;NSMotionUsageDescription=The reason for accessing the accelerometer;NSDesktopFolderUsageDescription=The reason for accessing the Desktop folder;NSDocumentsFolderUsageDescription=The reason for accessing the Documents folder;NSDownloadsFolderUsageDescription=The reason for accessing the Downloads folder;NSNetworkVolumesUsageDescription=The reason for accessing files on a network volume;NSRemovableVolumesUsageDescription=The reason for accessing files on a removable volume;NSSpeechRecognitionUsageDescription=The reason for requesting to send user data to Apple's speech recognition servers;ITSAppUsesNonExemptEncryption=false;NSBluetoothAlwaysUsageDescription=The reason for accessing the Bluetooth interface 181 | 182 | 183 | Debug 184 | DataSnapServer;fmx;DbxCommonDriver;bindengine;IndyIPCommon;FireDACCommonODBC;emsclient;IndyProtocols;dbxcds;FmxTeeUI;DBXFirebirdDriver;FireDACSqliteDriver;DbxClientDriver;soapmidas;dbexpress;inet;FireDACDBXDriver;fmxdae;CustomIPTransport;FireDACMSSQLDriver;IndySystem;FireDACCommon;DataSnapServerMidas;FireDACODBCDriver;emsserverresource;bindcompdbx;rtl;FireDACMySQLDriver;DBXSqliteDriver;DataSnapFireDAC;inetdbxpress;FireDAC;xmlrtl;dsnap;DBXOracleDriver;DBXInformixDriver;fmxobj;DataSnapNativeClient;emshosting;FireDACCommonDriver;IndyIPClient;emsedge;bindcompfmx;inetdb;FireDACASADriver;fmxFireDAC;DBXMySQLDriver;DataSnapCommon;fmxase;dbrtl;FireDACOracleDriver;DataSnapIndy10ServerTransport;DBXInterBaseDriver;FireDACMongoDBDriver;FireDACTDataDriver;bindcomp;inetstn;IndyCore;RESTBackendComponents;AWSSDKFMX;RESTComponents;IndyIPServer;dsnapxml;DataSnapClient;DataSnapProviderClient;emsclientfiredac;FireDACPgDriver;FireDACDSDriver;tethering;CloudService;DBXSybaseASADriver;FMXTee;soaprtl;soapserver;FireDACIBDriver;$(DCC_UsePackage) 185 | true 186 | CFBundleName=$(MSBuildProjectName);CFBundleDisplayName=$(MSBuildProjectName);CFBundleIdentifier=$(MSBuildProjectName);CFBundleVersion=1.0.0;CFBundleShortVersionString=1.0.0;CFBundlePackageType=APPL;CFBundleSignature=????;CFBundleAllowMixedLocalizations=YES;CFBundleExecutable=$(MSBuildProjectName);NSHighResolutionCapable=true;LSApplicationCategoryType=public.app-category.utilities;NSLocationUsageDescription=The reason for accessing the location information of the user;NSContactsUsageDescription=The reason for accessing the contacts;NSCalendarsUsageDescription=The reason for accessing the calendar data;NSRemindersUsageDescription=The reason for accessing the reminders;NSCameraUsageDescription=The reason for accessing the camera;NSMicrophoneUsageDescription=The reason for accessing the microphone;NSMotionUsageDescription=The reason for accessing the accelerometer;NSDesktopFolderUsageDescription=The reason for accessing the Desktop folder;NSDocumentsFolderUsageDescription=The reason for accessing the Documents folder;NSDownloadsFolderUsageDescription=The reason for accessing the Downloads folder;NSNetworkVolumesUsageDescription=The reason for accessing files on a network volume;NSRemovableVolumesUsageDescription=The reason for accessing files on a removable volume;NSSpeechRecognitionUsageDescription=The reason for requesting to send user data to Apple's speech recognition servers;ITSAppUsesNonExemptEncryption=false;NSBluetoothAlwaysUsageDescription=The reason for accessing the Bluetooth interface 187 | 188 | 189 | Debug 190 | Winapi;System.Win;Data.Win;Datasnap.Win;Web.Win;Soap.Win;Xml.Win;Bde;$(DCC_Namespace) 191 | RaizeComponentsVcl;vclwinx;DataSnapServer;P4DPandas;fmx;vclie;DbxCommonDriver;bindengine;IndyIPCommon;VCLRESTComponents;DBXMSSQLDriver;FireDACCommonODBC;emsclient;appanalytics;IndyProtocols;vclx;Skia.Package.RTL;dbxcds;vcledge;FmxTeeUI;P4DONNXRuntime;DBXFirebirdDriver;FireDACSqliteDriver;DbxClientDriver;GdkToolsApiHelper;FMXColorEditors;soapmidas;JclVcl;TeeUI;Jcl;dbexpress;Python;FormGuardPkg;inet;PythonVcl;vcltouch;P4DOpenCV;FireDACDBXDriver;fmxdae;CustomIPTransport;FireDACMSSQLDriver;P4DSciPy;IndySystem;CodolexUtils;BossExperts;CodolexEditors;VirtualTreesR;JclContainers;vclFireDAC;FireDACCommon;DataSnapServerMidas;FireDACODBCDriver;emsserverresource;DOSCommandDR;P4DScikitLearn;P4DPyTorch;bindcompdbx;rtl;FireDACMySQLDriver;DBXSqliteDriver;DBXSybaseASEDriver;vclimg;DataSnapFireDAC;inetdbxpress;FireDAC;xmlrtl;P4DEnvironment;dsnap;FireDACDb2Driver;DBXOracleDriver;DBXInformixDriver;fmxobj;bindcompvclsmp;DataSnapNativeClient;DatasnapConnectorsFreePascal;P4DMatplotLib;emshosting;FireDACCommonDriver;IndyIPClient;bindcompvclwinx;emsedge;bindcompfmx;inetdb;FireDACASADriver;CodolexComponents;Tee;vclactnband;fmxFireDAC;FireDACInfxDriver;P4DPyPackage;DBXMySQLDriver;VclSmp;DataSnapCommon;CodolexFramework;fmxase;DBXOdbcDriver;dbrtl;FireDACOracleDriver;Skia.Package.FMX;CodeSiteExpressPkg;TeeDB;FireDACMSAccDriver;DataSnapIndy10ServerTransport;JclDeveloperTools;P4DTensorFlow;DataSnapConnectors;P4DKeras;vcldsnap;DBXInterBaseDriver;CodolexSynEditDR;FireDACMongoDBDriver;CodolexCodeGenInterfaces;FireDACTDataDriver;Skia.Package.VCL;vcldb;CodolexRenderingVCL;SynEditDR;bindcomp;inetstn;IndyCore;RESTBackendComponents;AWSSDKFMX;FireDACADSDriver;RaizeComponentsVclDb;AWSSDKVCL;RESTComponents;IndyIPServer;vcl;dsnapxml;adortl;dsnapcon;DataSnapClient;DataSnapProviderClient;P4DNLTK;FixInsight_12;DBXDb2Driver;emsclientfiredac;FireDACPgDriver;FireDACDSDriver;tethering;bindcompvcl;CodolexCore;CloudService;DBXSybaseASADriver;P4DNumPy;FMXTee;PythonFmx;soaprtl;soapserver;FireDACIBDriver;$(DCC_UsePackage) 192 | $(BDS)\bin\default_app.manifest 193 | $(BDS)\bin\Artwork\Windows\UWP\delphi_UwpDefault_150.png 194 | $(BDS)\bin\Artwork\Windows\UWP\delphi_UwpDefault_44.png 195 | true 196 | CompanyName=;FileDescription=$(MSBuildProjectName);FileVersion=1.0.0.0;InternalName=;LegalCopyright=;LegalTrademarks=;OriginalFilename=;ProgramID=com.embarcadero.$(MSBuildProjectName);ProductName=$(MSBuildProjectName);ProductVersion=1.0.0.0;Comments= 197 | 1033 198 | 199 | 200 | Debug 201 | Winapi;System.Win;Data.Win;Datasnap.Win;Web.Win;Soap.Win;Xml.Win;$(DCC_Namespace) 202 | RaizeComponentsVcl;vclwinx;DataSnapServer;fmx;vclie;DbxCommonDriver;bindengine;IndyIPCommon;VCLRESTComponents;DBXMSSQLDriver;FireDACCommonODBC;emsclient;appanalytics;IndyProtocols;vclx;dbxcds;vcledge;FmxTeeUI;DBXFirebirdDriver;FireDACSqliteDriver;DbxClientDriver;soapmidas;TeeUI;dbexpress;inet;PythonVcl;vcltouch;FireDACDBXDriver;fmxdae;CustomIPTransport;FireDACMSSQLDriver;IndySystem;VirtualTreesR;vclFireDAC;FireDACCommon;DataSnapServerMidas;FireDACODBCDriver;emsserverresource;DOSCommandDR;bindcompdbx;rtl;FireDACMySQLDriver;DBXSqliteDriver;DBXSybaseASEDriver;vclimg;DataSnapFireDAC;inetdbxpress;FireDAC;xmlrtl;dsnap;FireDACDb2Driver;DBXOracleDriver;DBXInformixDriver;fmxobj;bindcompvclsmp;DataSnapNativeClient;DatasnapConnectorsFreePascal;emshosting;FireDACCommonDriver;IndyIPClient;bindcompvclwinx;emsedge;bindcompfmx;inetdb;FireDACASADriver;Tee;vclactnband;fmxFireDAC;FireDACInfxDriver;DBXMySQLDriver;VclSmp;DataSnapCommon;fmxase;DBXOdbcDriver;dbrtl;FireDACOracleDriver;TeeDB;FireDACMSAccDriver;DataSnapIndy10ServerTransport;DataSnapConnectors;vcldsnap;DBXInterBaseDriver;FireDACMongoDBDriver;FireDACTDataDriver;Skia.Package.VCL;vcldb;SynEditDR;bindcomp;inetstn;IndyCore;RESTBackendComponents;AWSSDKFMX;FireDACADSDriver;RaizeComponentsVclDb;AWSSDKVCL;RESTComponents;IndyIPServer;vcl;dsnapxml;adortl;dsnapcon;DataSnapClient;DataSnapProviderClient;DBXDb2Driver;emsclientfiredac;FireDACPgDriver;FireDACDSDriver;tethering;bindcompvcl;CloudService;DBXSybaseASADriver;FMXTee;soaprtl;soapserver;FireDACIBDriver;$(DCC_UsePackage) 203 | $(BDS)\bin\default_app.manifest 204 | $(BDS)\bin\Artwork\Windows\UWP\delphi_UwpDefault_150.png 205 | $(BDS)\bin\Artwork\Windows\UWP\delphi_UwpDefault_44.png 206 | true 207 | CompanyName=;FileDescription=$(MSBuildProjectName);FileVersion=1.0.0.0;InternalName=;LegalCopyright=;LegalTrademarks=;OriginalFilename=;ProgramID=com.embarcadero.$(MSBuildProjectName);ProductName=$(MSBuildProjectName);ProductVersion=1.0.0.0;Comments= 208 | 1033 209 | 210 | 211 | Debug 212 | fmx;DbxCommonDriver;bindengine;IndyIPCommon;emsclient;IndyProtocols;dbxcds;FmxTeeUI;FireDACSqliteDriver;DbxClientDriver;soapmidas;dbexpress;inet;FireDACDBXDriver;CustomIPTransport;IndySystem;FireDACCommon;emsserverresource;bindcompdbx;rtl;DBXSqliteDriver;DataSnapFireDAC;FireDAC;xmlrtl;dsnap;DataSnapNativeClient;emshosting;FireDACCommonDriver;IndyIPClient;emsedge;bindcompfmx;fmxFireDAC;DataSnapCommon;fmxase;dbrtl;DBXInterBaseDriver;bindcomp;inetstn;IndyCore;RESTBackendComponents;AWSSDKFMX;RESTComponents;IndyIPServer;dsnapxml;DataSnapClient;DataSnapProviderClient;emsclientfiredac;FireDACDSDriver;tethering;CloudService;FMXTee;soaprtl;soapserver;FireDACIBDriver;$(DCC_UsePackage) 213 | $(MSBuildProjectName) 214 | true 215 | CFBundleName=$(MSBuildProjectName);CFBundleDevelopmentRegion=en;CFBundleDisplayName=$(MSBuildProjectName);CFBundleIdentifier=$(MSBuildProjectName);CFBundleInfoDictionaryVersion=7.1;CFBundleVersion=1.0.0;CFBundleShortVersionString=1.0.0;CFBundlePackageType=APPL;CFBundleSignature=????;LSRequiresIPhoneOS=true;CFBundleAllowMixedLocalizations=YES;CFBundleExecutable=$(MSBuildProjectName);UIDeviceFamily=iPhone & iPad;NSLocationAlwaysUsageDescription=The reason for accessing the location information of the user;NSLocationWhenInUseUsageDescription=The reason for accessing the location information of the user;NSLocationAlwaysAndWhenInUseUsageDescription=The reason for accessing the location information of the user;UIBackgroundModes=;NSContactsUsageDescription=The reason for accessing the contacts;NSPhotoLibraryUsageDescription=The reason for accessing the photo library;NSPhotoLibraryAddUsageDescription=The reason for adding to the photo library;NSCameraUsageDescription=The reason for accessing the camera;NSFaceIDUsageDescription=The reason for accessing the face id;NSMicrophoneUsageDescription=The reason for accessing the microphone;NSSiriUsageDescription=The reason for accessing Siri;ITSAppUsesNonExemptEncryption=false;NSBluetoothAlwaysUsageDescription=The reason for accessing bluetooth;NSBluetoothPeripheralUsageDescription=The reason for accessing bluetooth peripherals;NSCalendarsUsageDescription=The reason for accessing the calendar data;NSRemindersUsageDescription=The reason for accessing the reminders;NSMotionUsageDescription=The reason for accessing the accelerometer;NSSpeechRecognitionUsageDescription=The reason for requesting to send user data to Apple's speech recognition servers 216 | iPhoneAndiPad 217 | $(BDS)\bin\Artwork\iOS\iPhone\FM_ApplicationIcon_1024x1024.png 218 | $(BDS)\bin\Artwork\iOS\iPad\FM_ApplicationIcon_152x152.png 219 | $(BDS)\bin\Artwork\iOS\iPad\FM_ApplicationIcon_167x167.png 220 | $(BDS)\bin\Artwork\iOS\iPad\FM_LaunchImage_2x.png 221 | $(BDS)\bin\Artwork\iOS\iPad\FM_LaunchImageDark_2x.png 222 | $(BDS)\bin\Artwork\iOS\iPad\FM_NotificationIcon_40x40.png 223 | $(BDS)\bin\Artwork\iOS\iPad\FM_SettingIcon_58x58.png 224 | $(BDS)\bin\Artwork\iOS\iPad\FM_SpotlightSearchIcon_80x80.png 225 | $(BDS)\bin\Artwork\iOS\iPhone\FM_ApplicationIcon_120x120.png 226 | $(BDS)\bin\Artwork\iOS\iPhone\FM_ApplicationIcon_180x180.png 227 | $(BDS)\bin\Artwork\iOS\iPhone\FM_LaunchImage_2x.png 228 | $(BDS)\bin\Artwork\iOS\iPhone\FM_LaunchImage_3x.png 229 | $(BDS)\bin\Artwork\iOS\iPhone\FM_LaunchImageDark_2x.png 230 | $(BDS)\bin\Artwork\iOS\iPhone\FM_LaunchImageDark_3x.png 231 | $(BDS)\bin\Artwork\iOS\iPhone\FM_NotificationIcon_40x40.png 232 | $(BDS)\bin\Artwork\iOS\iPhone\FM_NotificationIcon_60x60.png 233 | $(BDS)\bin\Artwork\iOS\iPhone\FM_SettingIcon_58x58.png 234 | $(BDS)\bin\Artwork\iOS\iPhone\FM_SettingIcon_87x87.png 235 | $(BDS)\bin\Artwork\iOS\iPhone\FM_SpotlightSearchIcon_120x120.png 236 | $(BDS)\bin\Artwork\iOS\iPhone\FM_SpotlightSearchIcon_80x80.png 237 | 238 | 239 | fmx;DbxCommonDriver;bindengine;IndyIPCommon;emsclient;IndyProtocols;dbxcds;FmxTeeUI;FireDACSqliteDriver;DbxClientDriver;soapmidas;dbexpress;inet;FireDACDBXDriver;CustomIPTransport;IndySystem;FireDACCommon;emsserverresource;bindcompdbx;rtl;DBXSqliteDriver;DataSnapFireDAC;FireDAC;xmlrtl;dsnap;DataSnapNativeClient;emshosting;FireDACCommonDriver;IndyIPClient;emsedge;bindcompfmx;fmxFireDAC;DataSnapCommon;fmxase;dbrtl;DBXInterBaseDriver;bindcomp;inetstn;IndyCore;RESTBackendComponents;AWSSDKFMX;RESTComponents;IndyIPServer;dsnapxml;DataSnapClient;DataSnapProviderClient;emsclientfiredac;FireDACDSDriver;tethering;CloudService;FMXTee;soaprtl;soapserver;FireDACIBDriver;$(DCC_UsePackage) 240 | true 241 | CFBundleName=$(MSBuildProjectName);CFBundleDevelopmentRegion=en;CFBundleDisplayName=$(MSBuildProjectName);CFBundleIdentifier=$(MSBuildProjectName);CFBundleInfoDictionaryVersion=7.1;CFBundleVersion=1.0.0;CFBundleShortVersionString=1.0.0;CFBundlePackageType=APPL;CFBundleSignature=????;LSRequiresIPhoneOS=true;CFBundleAllowMixedLocalizations=YES;CFBundleExecutable=$(MSBuildProjectName);UIDeviceFamily=iPhone & iPad;NSLocationAlwaysUsageDescription=The reason for accessing the location information of the user;NSLocationWhenInUseUsageDescription=The reason for accessing the location information of the user;NSLocationAlwaysAndWhenInUseUsageDescription=The reason for accessing the location information of the user;UIBackgroundModes=;NSContactsUsageDescription=The reason for accessing the contacts;NSPhotoLibraryUsageDescription=The reason for accessing the photo library;NSPhotoLibraryAddUsageDescription=The reason for adding to the photo library;NSCameraUsageDescription=The reason for accessing the camera;NSFaceIDUsageDescription=The reason for accessing the face id;NSMicrophoneUsageDescription=The reason for accessing the microphone;NSSiriUsageDescription=The reason for accessing Siri;ITSAppUsesNonExemptEncryption=false;NSBluetoothAlwaysUsageDescription=The reason for accessing bluetooth;NSBluetoothPeripheralUsageDescription=The reason for accessing bluetooth peripherals;NSCalendarsUsageDescription=The reason for accessing the calendar data;NSRemindersUsageDescription=The reason for accessing the reminders;NSMotionUsageDescription=The reason for accessing the accelerometer;NSSpeechRecognitionUsageDescription=The reason for requesting to send user data to Apple's speech recognition servers 242 | iPhoneAndiPad 243 | $(BDS)\bin\Artwork\iOS\iPhone\FM_ApplicationIcon_1024x1024.png 244 | $(BDS)\bin\Artwork\iOS\iPad\FM_ApplicationIcon_152x152.png 245 | $(BDS)\bin\Artwork\iOS\iPad\FM_ApplicationIcon_167x167.png 246 | $(BDS)\bin\Artwork\iOS\iPad\FM_LaunchImage_2x.png 247 | $(BDS)\bin\Artwork\iOS\iPad\FM_LaunchImageDark_2x.png 248 | $(BDS)\bin\Artwork\iOS\iPad\FM_NotificationIcon_40x40.png 249 | $(BDS)\bin\Artwork\iOS\iPad\FM_SettingIcon_58x58.png 250 | $(BDS)\bin\Artwork\iOS\iPad\FM_SpotlightSearchIcon_80x80.png 251 | $(BDS)\bin\Artwork\iOS\iPhone\FM_ApplicationIcon_120x120.png 252 | $(BDS)\bin\Artwork\iOS\iPhone\FM_ApplicationIcon_180x180.png 253 | $(BDS)\bin\Artwork\iOS\iPhone\FM_LaunchImage_2x.png 254 | $(BDS)\bin\Artwork\iOS\iPhone\FM_LaunchImage_3x.png 255 | $(BDS)\bin\Artwork\iOS\iPhone\FM_LaunchImageDark_2x.png 256 | $(BDS)\bin\Artwork\iOS\iPhone\FM_LaunchImageDark_3x.png 257 | $(BDS)\bin\Artwork\iOS\iPhone\FM_NotificationIcon_40x40.png 258 | $(BDS)\bin\Artwork\iOS\iPhone\FM_NotificationIcon_60x60.png 259 | $(BDS)\bin\Artwork\iOS\iPhone\FM_SettingIcon_58x58.png 260 | $(BDS)\bin\Artwork\iOS\iPhone\FM_SettingIcon_87x87.png 261 | $(BDS)\bin\Artwork\iOS\iPhone\FM_SpotlightSearchIcon_120x120.png 262 | $(BDS)\bin\Artwork\iOS\iPhone\FM_SpotlightSearchIcon_80x80.png 263 | 264 | 265 | true 266 | true 267 | DEBUG;$(DCC_Define) 268 | true 269 | true 270 | false 271 | true 272 | true 273 | 274 | 275 | PerMonitorV2 276 | false 277 | true 278 | 1033 279 | 280 | 281 | PerMonitorV2 282 | 283 | 284 | 0 285 | RELEASE;$(DCC_Define) 286 | false 287 | 0 288 | 289 | 290 | PerMonitorV2 291 | 292 | 293 | PerMonitorV2 294 | 295 | 296 | 297 | MainSource 298 | 299 | 300 |
Form28
301 | fmx 302 |
303 | 304 | Base 305 | 306 | 307 | Cfg_1 308 | Base 309 | 310 | 311 | Cfg_2 312 | Base 313 | 314 |
315 | 316 | Delphi.Personality.12 317 | Application 318 | 319 | 320 | 321 | CSPRNG_FMX.dpr 322 | 323 | 324 | 325 | 326 | True 327 | True 328 | False 329 | True 330 | True 331 | True 332 | True 333 | False 334 | True 335 | True 336 | 337 | 338 | 12 339 | 340 | 341 | 342 | 343 |
344 | -------------------------------------------------------------------------------- /sample/CSPRNG_FMX.res: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jimmckeeth/DelphiCSPRNG/f49d935b20d06f61fc18461c71b22da56da48dca/sample/CSPRNG_FMX.res -------------------------------------------------------------------------------- /sample/CSPRNG_FMX_Main.fmx: -------------------------------------------------------------------------------- 1 | object Form28: TForm28 2 | Left = 0 3 | Top = 0 4 | Caption = 'Form28' 5 | ClientHeight = 480 6 | ClientWidth = 640 7 | FormFactor.Width = 320 8 | FormFactor.Height = 480 9 | FormFactor.Devices = [Desktop] 10 | OnCreate = FormCreate 11 | DesignerMasterStyle = 0 12 | object Button1: TButton 13 | Position.X = 8.000000000000000000 14 | Position.Y = 8.000000000000000000 15 | Size.Width = 80.000000000000000000 16 | Size.Height = 40.000000000000000000 17 | Size.PlatformDefault = False 18 | TabOrder = 0 19 | Text = 'Button1' 20 | TextSettings.Trimming = None 21 | OnClick = Button1Click 22 | end 23 | object Memo1: TMemo 24 | Touch.InteractiveGestures = [Pan, LongTap, DoubleTap] 25 | DataDetectorTypes = [] 26 | ShowScrollBars = False 27 | TextSettings.WordWrap = True 28 | Anchors = [akLeft, akTop, akRight, akBottom] 29 | Position.X = 8.000000000000000000 30 | Position.Y = 56.000000000000000000 31 | Size.Width = 624.000000000000000000 32 | Size.Height = 416.000000000000000000 33 | Size.PlatformDefault = False 34 | TabOrder = 1 35 | Viewport.Width = 620.000000000000000000 36 | Viewport.Height = 412.000000000000000000 37 | end 38 | end 39 | -------------------------------------------------------------------------------- /sample/CSPRNG_FMX_Main.pas: -------------------------------------------------------------------------------- 1 | unit CSPRNG_FMX_Main; 2 | 3 | interface 4 | 5 | uses 6 | System.SysUtils, System.Types, System.UITypes, System.Classes, System.Variants, 7 | FMX.Types, FMX.Controls, FMX.Forms, FMX.Graphics, FMX.Dialogs, 8 | 9 | CSPRNG, CSPRNG.Interfaces, FMX.Memo.Types, FMX.ScrollBox, FMX.Memo, 10 | FMX.Controls.Presentation, FMX.StdCtrls; 11 | 12 | type 13 | TForm28 = class(TForm) 14 | Button1: TButton; 15 | Memo1: TMemo; 16 | procedure FormCreate(Sender: TObject); 17 | procedure Button1Click(Sender: TObject); 18 | private 19 | { Private declarations } 20 | rng: ICSPRNGProvider; 21 | public 22 | { Public declarations } 23 | end; 24 | 25 | var 26 | Form28: TForm28; 27 | 28 | implementation 29 | 30 | {$R *.fmx} 31 | 32 | procedure TForm28.Button1Click(Sender: TObject); 33 | begin 34 | memo1.Lines.Text := rng.GetBase64() 35 | end; 36 | 37 | procedure TForm28.FormCreate(Sender: TObject); 38 | begin 39 | rng := GetCSPRNGProvider; 40 | end; 41 | 42 | end. 43 | -------------------------------------------------------------------------------- /sample/CSPRNG_sample.dpr: -------------------------------------------------------------------------------- 1 | program CSPRNG_sample; 2 | 3 | {$APPTYPE CONSOLE} 4 | 5 | {$R *.res} 6 | 7 | uses 8 | System.SysUtils, 9 | CSPRNG in '..\src\CSPRNG.pas', 10 | CSPRNG.Interfaces in '..\src\CSPRNG.Interfaces.pas', 11 | CSPRNG.ProviderInfo in '..\src\CSPRNG.ProviderInfo.pas'; 12 | 13 | begin 14 | try 15 | { TODO -oUser -cConsole Main : Insert code here } 16 | except 17 | on E: Exception do 18 | Writeln(E.ClassName, ': ', E.Message); 19 | end; 20 | end. 21 | -------------------------------------------------------------------------------- /sample/CSPRNG_sample.dproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | True 4 | Console 5 | Debug 6 | None 7 | CSPRNG_sample.dpr 8 | Win32 9 | {7F7C03D2-1B62-4C4B-8FA9-C2EEB044296C} 10 | CSPRNG_sample 11 | 20.1 12 | 1 13 | 14 | 15 | true 16 | 17 | 18 | true 19 | Base 20 | true 21 | 22 | 23 | true 24 | Base 25 | true 26 | 27 | 28 | true 29 | Cfg_1 30 | true 31 | true 32 | 33 | 34 | true 35 | Base 36 | true 37 | 38 | 39 | CSPRNG_sample 40 | .\$(Platform)\$(Config) 41 | .\$(Platform)\$(Config) 42 | System;Xml;Data;Datasnap;Web;Soap;$(DCC_Namespace) 43 | 44 | 45 | Debug 46 | true 47 | Winapi;System.Win;Data.Win;Datasnap.Win;Web.Win;Soap.Win;Xml.Win;Bde;$(DCC_Namespace) 48 | vclwinx;DataSnapServer;P4DMatplotLib;P4DPandas;fmx;emshosting;vclie;DbxCommonDriver;bindengine;IndyIPCommon;VCLRESTComponents;DBXMSSQLDriver;FireDACCommonODBC;emsclient;FireDACCommonDriver;appanalytics;IndyProtocols;vclx;Skia.Package.RTL;IndyIPClient;dbxcds;vcledge;bindcompvclwinx;FmxTeeUI;P4DONNXRuntime;emsedge;bindcompfmx;DBXFirebirdDriver;inetdb;FireDACSqliteDriver;DbxClientDriver;FireDACASADriver;Tee;soapmidas;vclactnband;TeeUI;fmxFireDAC;dbexpress;Python;FireDACInfxDriver;P4DTools;DBXMySQLDriver;P4DPyPackage;VclSmp;inet;DataSnapCommon;PythonVcl;vcltouch;fmxase;P4DOpenCV;DBXOdbcDriver;dbrtl;FireDACDBXDriver;Skia.Package.FMX;FireDACOracleDriver;fmxdae;TeeDB;FireDACMSAccDriver;CustomIPTransport;FireDACMSSQLDriver;P4DSciPy;DataSnapIndy10ServerTransport;P4DTensorFlow;DataSnapConnectors;P4DKeras;vcldsnap;DBXInterBaseDriver;FireDACMongoDBDriver;IndySystem;FireDACTDataDriver;Skia.Package.VCL;vcldb;vclFireDAC;bindcomp;FireDACCommon;DataSnapServerMidas;FireDACODBCDriver;emsserverresource;IndyCore;RESTBackendComponents;P4DScikitLearn;P4DPyTorch;bindcompdbx;rtl;FireDACMySQLDriver;FireDACADSDriver;RESTComponents;DBXSqliteDriver;vcl;IndyIPServer;dsnapxml;dsnapcon;DataSnapClient;DataSnapProviderClient;adortl;P4DNLTK;DBXSybaseASEDriver;FixInsight_12;DBXDb2Driver;vclimg;DataSnapFireDAC;emsclientfiredac;FireDACPgDriver;FireDAC;FireDACDSDriver;inetdbxpress;xmlrtl;tethering;P4DEnvironment;bindcompvcl;dsnap;CloudService;DBXSybaseASADriver;DBXOracleDriver;FireDACDb2Driver;DBXInformixDriver;P4DNumPy;fmxobj;bindcompvclsmp;FMXTee;DataSnapNativeClient;PythonFmx;AIAPI;DatasnapConnectorsFreePascal;soaprtl;soapserver;FireDACIBDriver;$(DCC_UsePackage) 49 | $(BDS)\bin\Artwork\Windows\UWP\delphi_UwpDefault_150.png 50 | $(BDS)\bin\Artwork\Windows\UWP\delphi_UwpDefault_44.png 51 | CompanyName=;FileDescription=$(MSBuildProjectName);FileVersion=1.0.0.0;InternalName=;LegalCopyright=;LegalTrademarks=;OriginalFilename=;ProgramID=com.embarcadero.$(MSBuildProjectName);ProductName=$(MSBuildProjectName);ProductVersion=1.0.0.0;Comments= 52 | 1033 53 | 54 | 55 | true 56 | true 57 | DEBUG;$(DCC_Define) 58 | true 59 | true 60 | false 61 | true 62 | true 63 | 64 | 65 | false 66 | 67 | 68 | 0 69 | RELEASE;$(DCC_Define) 70 | false 71 | 0 72 | 73 | 74 | 75 | MainSource 76 | 77 | 78 | 79 | 80 | 81 | Base 82 | 83 | 84 | Cfg_1 85 | Base 86 | 87 | 88 | Cfg_2 89 | Base 90 | 91 | 92 | 93 | Delphi.Personality.12 94 | Application 95 | 96 | 97 | 98 | CSPRNG_sample.dpr 99 | 100 | 101 | 102 | False 103 | False 104 | False 105 | False 106 | False 107 | True 108 | False 109 | False 110 | False 111 | 112 | 113 | 12 114 | 115 | 116 | 117 | 118 | 119 | -------------------------------------------------------------------------------- /sample/CSPRNG_sample.res: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jimmckeeth/DelphiCSPRNG/f49d935b20d06f61fc18461c71b22da56da48dca/sample/CSPRNG_sample.res -------------------------------------------------------------------------------- /src/CSPRNG.Interfaces.pas: -------------------------------------------------------------------------------- 1 | unit CSPRNG.Interfaces; 2 | 3 | interface 4 | 5 | uses SysUtils; 6 | 7 | type 8 | ICSPRNGProvider = interface 9 | /// 10 | /// Generates a specified number of cryptographically secure random bytes. 11 | /// 12 | function GetBytes(const Count: Integer): TBytes; 13 | 14 | /// 15 | /// Generates a cryptographically secure random unsigned 32-bit integer. 16 | /// 17 | function GetUInt32(const max: UInt32 = High(UInt32)): UInt32; 18 | 19 | /// 20 | /// Generates a cryptographically secure random signed 32-bit integer. 21 | /// 22 | function GetInt32(const max: Int32 = High(Int32)): Int32; 23 | 24 | /// 25 | /// Generates a cryptographically secure random signed 64-bit integer. 26 | /// 27 | function GetInt64(const max: Int64 = High(Int64)): Int64; 28 | 29 | /// 30 | /// Generates a cryptographically secure random unsigned 64-bit integer. 31 | /// 32 | function GetUInt64(const max: UInt64 = High(UInt64)): UInt64; 33 | 34 | /// 35 | /// Generates a cryptographically secure random float between 0 and 1 36 | /// 37 | function GetFloat: Double; 38 | 39 | /// 40 | /// Generates a BASE64 encoded random string 41 | /// 42 | function GetBase64(const len: Integer = 1024): String; 43 | end; 44 | 45 | 46 | implementation 47 | 48 | end. 49 | -------------------------------------------------------------------------------- /src/CSPRNG.Provider.Base.pas: -------------------------------------------------------------------------------- 1 | unit CSPRNG.Provider.Base; 2 | 3 | interface 4 | 5 | uses 6 | System.SysUtils, CSPRNG.Interfaces, 7 | System.NetEncoding; 8 | 9 | type 10 | /// 11 | /// Abstract base class for CSPRNG providers. 12 | /// 13 | TCSPRNGProviderBase = class abstract(TInterfacedObject, ICSPRNGProvider) 14 | 15 | protected 16 | function GetBytes(const Count: Integer): TBytes; virtual; abstract; 17 | public 18 | 19 | function GetFloat: Double; 20 | function GetUInt32(const max: UInt32 = High(UInt32)): UInt32; 21 | function GetInt32(const max: Int32 = High(Int32)): Int32; 22 | function GetInt64(const max: Int64 = High(Int64)): Int64; 23 | function GetUInt64(const max: UInt64 = High(UInt64)): UInt64; 24 | function GetBase64(const len: Integer = 1024): String; 25 | 26 | // Helpers 27 | class function ToUInt32(const Bytes: TBytes): UInt32; 28 | class function ToInt32(const Bytes: TBytes): Int32; 29 | class function ToInt64(const Bytes: TBytes): Int64; 30 | class function ToUInt64(const Bytes: TBytes): UInt64; 31 | class function PadBytes(const Bytes: TBytes; PadLength: Integer): TBytes; static; 32 | 33 | end; 34 | 35 | implementation 36 | 37 | { TCSPRNGProviderBase } 38 | 39 | function TCSPRNGProviderBase.GetUInt32(const max: UInt32 = High(UInt32)): UInt32; 40 | var 41 | RandomBytes: TBytes; 42 | Value: UInt64; 43 | begin 44 | if max = 0 then 45 | Exit(0); // Handle the case where max is 0 46 | 47 | RandomBytes := GetBytes(SizeOf(UInt32)); // Get 4 random bytes 48 | Value := ToUInt64(RandomBytes); 49 | 50 | Result := UInt32(Value mod (UInt64(max) + 1)); // Modulo and cast to UInt32 51 | end; 52 | 53 | function TCSPRNGProviderBase.GetInt32(const max: Int32 = High(Int32)): Int32; 54 | var 55 | RandomBytes: TBytes; 56 | Value: UInt64; 57 | begin 58 | if max < 0 then 59 | raise Exception.Create('Max value must be greater than or equal to 0'); 60 | 61 | RandomBytes := GetBytes(SizeOf(Int32)); // Get 4 random bytes 62 | Value := ToUInt64(RandomBytes); // Convert to UInt64 63 | 64 | // Calculate the range size and adjust the modulo operation for signed values 65 | var rangeSize := UInt64(max) + 1; // Range from 0 to max (inclusive) 66 | var adjustedValue := Value mod rangeSize; 67 | 68 | // If the adjusted value is too large to fit in Int32 after conversion, subtract the range size 69 | if adjustedValue > High(Int32) then 70 | adjustedValue := adjustedValue - rangeSize; 71 | 72 | Result := Int32(adjustedValue); // Safely cast to Int32 73 | end; 74 | 75 | function TCSPRNGProviderBase.GetInt64(const max: Int64 = High(Int64)): Int64; 76 | var 77 | RandomBytes: TBytes; 78 | Value: UInt64; 79 | begin 80 | if max < 0 then 81 | raise Exception.Create('Max value must be greater than or equal to 0'); 82 | 83 | RandomBytes := GetBytes(SizeOf(Int64)); 84 | Value := ToUInt64(RandomBytes); 85 | 86 | var rangeSize := UInt64(max) + 1; 87 | var adjustedValue := Value mod rangeSize; 88 | 89 | if adjustedValue > High(Int64) then 90 | adjustedValue := adjustedValue - rangeSize; 91 | 92 | Result := Int64(adjustedValue); 93 | end; 94 | 95 | function TCSPRNGProviderBase.GetUInt64(const max: UInt64 = High(UInt64)): UInt64; 96 | var 97 | RandomBytes: TBytes; 98 | Value: UInt64; 99 | begin 100 | if max = 0 then 101 | Exit(0); // Handle the case where max is 0 102 | 103 | // Special handling when max is High(UInt64) to avoid overflow 104 | if max = High(UInt64) then 105 | begin 106 | RandomBytes := GetBytes(SizeOf(UInt64)); // Get 8 random bytes 107 | Exit(ToUInt64(RandomBytes)); 108 | end; 109 | 110 | RandomBytes := GetBytes(SizeOf(UInt64)); // Get 8 random bytes 111 | Value := ToUInt64(RandomBytes); 112 | 113 | // Optimized range reduction without a loop 114 | var divisor := High(UInt64) div (max + 1); 115 | Result := Value div divisor; // Integer division ensures the result is in the range 116 | end; 117 | 118 | 119 | class function TCSPRNGProviderBase.PadBytes(const Bytes: TBytes; PadLength: Integer): TBytes; 120 | begin 121 | if Length(Bytes) < PadLength then 122 | begin 123 | SetLength(Result, PadLength); 124 | FillChar(Result[0], PadLength, 0); // Fill with zeros 125 | if Length(Bytes) > 0 then // Only move bytes if the input array is not empty 126 | Move(Bytes[0], Result[PadLength - Length(Bytes)], Length(Bytes)); 127 | end 128 | else 129 | Result := Copy(Bytes, 0, PadLength); // Copy only the required bytes 130 | end; 131 | 132 | class function TCSPRNGProviderBase.ToUInt32(const Bytes: TBytes): UInt32; 133 | begin 134 | var localBytes := PadBytes(Bytes, SizeOf(UInt32)); 135 | 136 | // Combine bytes using bit shifting to avoid potential endianness issues 137 | Result := UInt32(localBytes[0]) + 138 | (UInt32(localBytes[1]) shl 8) + 139 | (UInt32(localBytes[2]) shl 16) + 140 | (UInt32(localBytes[3]) shl 24); 141 | end; 142 | 143 | class function TCSPRNGProviderBase.ToInt32(const Bytes: TBytes): Int32; 144 | var 145 | localBytes: TBytes; 146 | begin 147 | localBytes := PadBytes(Bytes, SizeOf(Int32)); 148 | 149 | // Combine bytes using bit shifting to avoid potential endianness issues 150 | Result := Int32(localBytes[0]) + 151 | (Int32(localBytes[1]) shl 8) + 152 | (Int32(localBytes[2]) shl 16) + 153 | (Int32(localBytes[3]) shl 24); 154 | end; 155 | 156 | class function TCSPRNGProviderBase.ToInt64(const Bytes: TBytes): Int64; 157 | var 158 | localBytes: TBytes; 159 | begin 160 | localBytes := PadBytes(Bytes, SizeOf(Int64)); 161 | 162 | // Combine bytes using bit shifting 163 | Result := Int64(localBytes[0]) + 164 | (Int64(localBytes[1]) shl 8) + 165 | (Int64(localBytes[2]) shl 16) + 166 | (Int64(localBytes[3]) shl 24) + 167 | (Int64(localBytes[4]) shl 32) + 168 | (Int64(localBytes[5]) shl 40) + 169 | (Int64(localBytes[6]) shl 48) + 170 | (Int64(localBytes[7]) shl 56); 171 | end; 172 | 173 | class function TCSPRNGProviderBase.ToUInt64(const Bytes: TBytes): UInt64; 174 | var 175 | localBytes: TBytes; 176 | begin 177 | localBytes := PadBytes(Bytes, SizeOf(UInt64)); 178 | 179 | // Combine bytes using bit shifting 180 | Result := UInt64(localBytes[0]) + 181 | (UInt64(localBytes[1]) shl 8) + 182 | (UInt64(localBytes[2]) shl 16) + 183 | (UInt64(localBytes[3]) shl 24) + 184 | (UInt64(localBytes[4]) shl 32) + 185 | (UInt64(localBytes[5]) shl 40) + 186 | (UInt64(localBytes[6]) shl 48) + 187 | (UInt64(localBytes[7]) shl 56); 188 | end; 189 | 190 | function TCSPRNGProviderBase.GetFloat: Double; 191 | var 192 | Bytes: TBytes; 193 | RandomInt: UInt64; 194 | begin 195 | Bytes := GetBytes(SizeOf(UInt64)); 196 | RandomInt := PUInt64(@Bytes[0])^; // Assuming little-endian 197 | Result := RandomInt / UInt64(High(UInt64)); // Scale to [0, 1) 198 | end; 199 | 200 | function TCSPRNGProviderBase.GetBase64(const len: Integer = 1024): String; 201 | var 202 | Bytes: TBytes; 203 | begin 204 | Bytes := GetBytes(len); 205 | var Encoding := TBase64Encoding.Create(0); 206 | try 207 | Result := Encoding.EncodeBytesToString(Bytes); // Convert to Base64 208 | finally 209 | Encoding.Free; 210 | end; 211 | end; 212 | 213 | end. 214 | -------------------------------------------------------------------------------- /src/CSPRNG.Provider.MacOS64.pas: -------------------------------------------------------------------------------- 1 | unit CSPRNG.Provider.MacOS64; 2 | 3 | interface 4 | 5 | {$IFDEF OSX} 6 | 7 | uses 8 | CSPRNG.Provider.Base, SysUtils, Classes, Posix.Base, Posix.Unistd, Posix.Fcntl, Posix.Errno; 9 | 10 | type 11 | /// 12 | /// macOS (64-bit) implementation of the CSPRNG provider using platform entropy sources. 13 | /// 14 | TCSPRNGProviderMacOS64 = class(TCSPRNGProviderBase) 15 | protected 16 | /// 17 | /// Seeds the CSPRNG using the provided byte array. 18 | /// 19 | procedure SeedFromBytes(const SeedData: TBytes); override; 20 | 21 | /// 22 | /// Seeds the CSPRNG using the platform's entropy source (/dev/urandom). 23 | /// 24 | procedure SeedFromEntropySource; override; 25 | 26 | /// 27 | /// Generates a specified number of cryptographically secure random bytes using /dev/urandom. 28 | /// 29 | function GetBytes(const Count: Integer): TBytes; override; 30 | end; 31 | 32 | implementation 33 | 34 | { TCSPRNGProviderMacOS64 } 35 | 36 | procedure TCSPRNGProviderMacOS64.SeedFromBytes(const SeedData: TBytes); 37 | begin 38 | // Like on Linux, custom seeding is generally not necessary or supported. 39 | raise Exception.Create('Custom seeding is not supported for the macOS provider'); 40 | end; 41 | 42 | procedure TCSPRNGProviderMacOS64.SeedFromEntropySource; 43 | begin 44 | // On macOS, no extra action is needed since /dev/urandom provides entropy. 45 | end; 46 | 47 | function TCSPRNGProviderMacOS64.GetBytes(const Count: Integer): TBytes; 48 | var 49 | FileStream: TFileStream; 50 | BytesRead: Integer; 51 | begin 52 | SetLength(Result, Count); 53 | 54 | // Open /dev/urandom as a file stream on macOS to get random bytes 55 | FileStream := TFileStream.Create('/dev/urandom', fmOpenRead); 56 | try 57 | BytesRead := FileStream.Read(Result[0], Count); 58 | if BytesRead <> Count then 59 | raise Exception.Create('Unable to read sufficient random bytes from /dev/urandom on macOS'); 60 | finally 61 | FileStream.Free; 62 | end; 63 | end; 64 | 65 | {$ELSE} 66 | implementation 67 | {$ENDIF} 68 | 69 | end. 70 | 71 | -------------------------------------------------------------------------------- /src/CSPRNG.Provider.Posix.pas: -------------------------------------------------------------------------------- 1 | unit CSPRNG.Provider.Posix; 2 | 3 | interface 4 | 5 | {$IFDEF POSIX} 6 | 7 | uses 8 | CSPRNG.Provider.Base, SysUtils, Classes, Posix.Base, Posix.Unistd, Posix.Fcntl, Posix.Errno; 9 | 10 | type 11 | /// 12 | /// Linux (64-bit) implementation of the CSPRNG provider using platform entropy sources. 13 | /// 14 | TCSPRNGProviderPosix = class(TCSPRNGProviderBase) 15 | protected 16 | /// 17 | /// Generates a specified number of cryptographically secure random bytes using /dev/urandom. 18 | /// 19 | function GetBytes(const Count: Integer): TBytes; override; 20 | end; 21 | 22 | implementation 23 | 24 | { TCSPRNGProviderLinux64 } 25 | 26 | function TCSPRNGProviderPosix.GetBytes(const Count: Integer): TBytes; 27 | var 28 | FileStream: TFileStream; 29 | BytesRead: Integer; 30 | begin 31 | SetLength(Result, Count); 32 | 33 | // Open /dev/urandom as a file stream 34 | FileStream := TFileStream.Create('/dev/urandom', fmOpenRead); 35 | try 36 | BytesRead := FileStream.Read(Result[0], Count); 37 | if BytesRead <> Count then 38 | raise Exception.Create('Unable to read sufficient random bytes from /dev/urandom'); 39 | finally 40 | FileStream.Free; 41 | end; 42 | end; 43 | 44 | {$ELSE} 45 | implementation 46 | {$ENDIF} 47 | 48 | end. 49 | 50 | 51 | -------------------------------------------------------------------------------- /src/CSPRNG.Provider.Windows.pas: -------------------------------------------------------------------------------- 1 | unit CSPRNG.Provider.Windows; 2 | 3 | interface 4 | 5 | {$IFDEF MSWINDOWS} 6 | 7 | uses 8 | System.SysUtils, 9 | Winapi.Windows, 10 | CSPRNG.Interfaces, 11 | CSPRNG.Provider.Base; 12 | 13 | type 14 | BCRYPT_ALG_HANDLE = PVOID; 15 | TWindowsCSPRNGProvider = class(TCSPRNGProviderBase, ICSPRNGProvider) 16 | private 17 | FHandle: BCRYPT_ALG_HANDLE; 18 | procedure SeedFromEntropySource; // Add a field to store the seed 19 | 20 | public 21 | constructor Create; 22 | destructor Destroy; override; 23 | 24 | // ICSPRNGProvider implementation 25 | function GetBytes(const Count: Integer): TBytes; override; 26 | end; 27 | 28 | implementation 29 | 30 | uses 31 | System.Math; 32 | 33 | const 34 | BCRYPT_RNG_ALGORITHM = 'RNG'; 35 | BCRYPT_RNG_USE_ENTROPY_IN_BUFFER = $00000001; 36 | 37 | type 38 | PBCRYPT_ALG_HANDLE = ^BCRYPT_ALG_HANDLE; 39 | 40 | function BCryptOpenAlgorithmProvider(phAlgorithm: PBCRYPT_ALG_HANDLE; 41 | pszAlgId: LPCWSTR; pszImplementation: LPCWSTR; dwFlags: ULONG): NTSTATUS; stdcall; external 'bcrypt.dll'; 42 | 43 | function BCryptCloseAlgorithmProvider(hAlgorithm: BCRYPT_ALG_HANDLE; 44 | dwFlags: ULONG): NTSTATUS; stdcall; external 'bcrypt.dll'; 45 | 46 | function BCryptGenRandom(hAlgorithm: BCRYPT_ALG_HANDLE; pbBuffer: PBYTE; 47 | cbBuffer: ULONG; dwFlags: ULONG): NTSTATUS; stdcall; external 'bcrypt.dll'; 48 | 49 | const 50 | STATUS_SUCCESS = 0; // NTSTATUS Success value 51 | 52 | 53 | { TWindowsCSPRNGProvider } 54 | 55 | constructor TWindowsCSPRNGProvider.Create; 56 | begin 57 | inherited Create; 58 | if BCryptOpenAlgorithmProvider(@FHandle, BCRYPT_RNG_ALGORITHM, nil, 0) <> STATUS_SUCCESS then 59 | raise Exception.Create('Failed to open BCrypt RNG provider'); 60 | 61 | SeedFromEntropySource(); 62 | end; 63 | 64 | destructor TWindowsCSPRNGProvider.Destroy; 65 | begin 66 | BCryptCloseAlgorithmProvider(FHandle, 0); 67 | inherited; 68 | end; 69 | 70 | procedure TWindowsCSPRNGProvider.SeedFromEntropySource; 71 | begin 72 | // Use the default system-provided entropy 73 | BCryptGenRandom(FHandle, nil, 0, 0); 74 | end; 75 | 76 | function TWindowsCSPRNGProvider.GetBytes(const Count: Integer): TBytes; 77 | var 78 | pBytes: PByte; 79 | begin 80 | SetLength(Result, Count); 81 | pBytes := PByte(Result); 82 | if BCryptGenRandom(FHandle, pBytes, Count, 0) <> STATUS_SUCCESS then 83 | raise Exception.Create('Failed to generate random bytes'); 84 | end; 85 | {$ELSE} 86 | implementation 87 | {$ENDIF} 88 | 89 | end. 90 | 91 | -------------------------------------------------------------------------------- /src/CSPRNG.Provider.iOS.pas: -------------------------------------------------------------------------------- 1 | unit CSPRNG.Provider.iOS; 2 | 3 | interface 4 | 5 | {$ifdef IOS} 6 | uses 7 | CSPRNG.Provider.Base, Macapi.CoreFoundation, Macapi.Security, SysUtils; 8 | 9 | type 10 | /// 11 | /// iOS implementation of the CSPRNG provider using SecRandomCopyBytes. 12 | /// 13 | TCSPRNGProvideriOS = class(TCSPRNGProviderBase) 14 | protected 15 | procedure SeedFromBytes(const SeedData: TBytes); override; 16 | procedure SeedFromEntropySource; override; 17 | function GetBytes(const Count: Integer): TBytes; override; 18 | end; 19 | 20 | implementation 21 | 22 | { TCSPRNGProvideriOS } 23 | 24 | procedure TCSPRNGProvideriOS.SeedFromBytes(const SeedData: TBytes); 25 | begin 26 | // Seeding is not necessary on iOS. 27 | raise Exception.Create('Custom seeding is not supported on iOS.'); 28 | end; 29 | 30 | procedure TCSPRNGProvideriOS.SeedFromEntropySource; 31 | begin 32 | // Seeding is not necessary for iOS. 33 | end; 34 | 35 | function TCSPRNGProvideriOS.GetBytes(const Count: Integer): TBytes; 36 | var 37 | Status: Integer; 38 | begin 39 | SetLength(Result, Count); 40 | Status := SecRandomCopyBytes(kSecRandomDefault, Count, @Result[0]); 41 | 42 | if Status <> errSecSuccess then 43 | raise Exception.Create('Unable to generate random bytes using SecRandomCopyBytes'); 44 | end; 45 | 46 | {$ELSE} 47 | implementation 48 | {$endif} 49 | 50 | end. 51 | 52 | -------------------------------------------------------------------------------- /src/CSPRNG.pas: -------------------------------------------------------------------------------- 1 | unit CSPRNG; 2 | 3 | interface 4 | 5 | uses 6 | System.SysUtils, CSPRNG.Interfaces; 7 | 8 | function GetCSPRNGProvider: ICSPRNGProvider; 9 | 10 | implementation 11 | 12 | {$IF Defined(MSWINDOWS)} 13 | uses CSPRNG.Provider.Windows; 14 | function GetCSPRNGProvider: ICSPRNGProvider; 15 | begin 16 | Result := TWindowsCSPRNGProvider.Create; // Create Windows provider 17 | end; 18 | {$ENDIF} 19 | 20 | {$IFDEF POSIX} 21 | uses CSPRNG.Provider.Posix; 22 | 23 | function GetCSPRNGProvider: ICSPRNGProvider; 24 | begin 25 | Result := TCSPRNGProviderPosix.Create; 26 | end; 27 | {$ENDIF} 28 | 29 | {$IFDEF MACOS} 30 | uses CSPRNG.Provider.MacOS64; 31 | 32 | function GetCSPRNGProvider: ICSPRNGProvider; 33 | begin 34 | Result := TCSPRNGProviderMacOS64.Create; 35 | end; 36 | {$ENDIF} 37 | 38 | initialization 39 | 40 | finalization 41 | 42 | end. 43 | 44 | -------------------------------------------------------------------------------- /src/CSPRNG_sample.dpr: -------------------------------------------------------------------------------- 1 | program CSPRNG_sample; 2 | 3 | {$APPTYPE CONSOLE} 4 | 5 | {$R *.res} 6 | 7 | uses 8 | System.SysUtils, 9 | CSPRNG in 'CSPRNG.pas', 10 | CSPRNG.Provider.Windows in 'CSPRNG.Provider.Windows.pas', 11 | CSPRNG.Interfaces in 'CSPRNG.Interfaces.pas', 12 | CSPRNG.Provider.Base in 'CSPRNG.Provider.Base.pas', 13 | CSPRNG.Provider.Posix in 'CSPRNG.Provider.Posix.pas', 14 | CSPRNG.Provider.iOS in 'CSPRNG.Provider.iOS.pas', 15 | CSPRNG.Provider.MacOS64 in 'CSPRNG.Provider.MacOS64.pas'; 16 | 17 | begin 18 | try 19 | var rnd := GetCSPRNGProvider; 20 | for var b in rnd.GetBytes(1000) do 21 | begin 22 | write(IntToHex(b, 2).ToLower); 23 | end; 24 | Writeln; 25 | const limit = 5; 26 | writeln(' - Float -'); 27 | for var i := 0 to limit do Writeln(rnd.GetFloat); 28 | writeln(' - UInt32(max) -'); 29 | for var i := 0 to limit do Writeln(rnd.GetUInt32); 30 | writeln(' - UInt32(quarter) -'); 31 | for var i := 0 to limit do Writeln(rnd.GetUInt32(High(UInt32) div 4)); 32 | writeln(' - UInt32(small) -'); 33 | for var i := 0 to limit do Writeln(rnd.GetUInt32($F0)); 34 | 35 | 36 | writeln(' - Int32(max) -'); 37 | for var i := 0 to limit do Writeln(rnd.GetInt32()); 38 | writeln(' - Int32(quarter) -'); 39 | for var i := 0 to limit do Writeln(rnd.GetInt32(High(Int32) div 2)); 40 | writeln(' - Int32(small) -'); 41 | for var i := 0 to limit do Writeln(rnd.GetInt32($F0)); 42 | 43 | writeln(' - UInt64(max) -'); 44 | for var i := 0 to limit do Writeln(rnd.GetUInt64); 45 | writeln(' - UInt64(quarter) -'); 46 | for var i := 0 to limit do Writeln(rnd.GetUInt64(High(UInt64) div 4)); 47 | writeln(' - UInt64(small) -'); 48 | for var i := 0 to limit do Writeln(rnd.GetUInt64($F0)); 49 | 50 | writeln(' - Int64(max) -'); 51 | for var i := 0 to limit do Writeln(rnd.GetInt64); 52 | writeln(' - Int64(quarter) -'); 53 | for var i := 0 to limit do Writeln(rnd.GetInt64(High(UInt64) div 4)); 54 | writeln(' - Int64(small) -'); 55 | for var i := 0 to limit do Writeln(rnd.GetInt64($F0)); 56 | except 57 | on E: Exception do 58 | Writeln(E.ClassName, ': ', E.Message); 59 | end; 60 | Writeln; 61 | Writeln('Done!'); 62 | Readln; 63 | end. 64 | -------------------------------------------------------------------------------- /src/CSPRNG_sample.dproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | True 4 | Console 5 | Debug 6 | None 7 | CSPRNG_sample.dpr 8 | Win32 9 | {7F7C03D2-1B62-4C4B-8FA9-C2EEB044296C} 10 | CSPRNG_sample 11 | 20.2 12 | 33923 13 | 14 | 15 | true 16 | 17 | 18 | true 19 | Base 20 | true 21 | 22 | 23 | true 24 | Base 25 | true 26 | 27 | 28 | true 29 | Base 30 | true 31 | 32 | 33 | true 34 | Base 35 | true 36 | 37 | 38 | true 39 | Base 40 | true 41 | 42 | 43 | true 44 | Cfg_1 45 | true 46 | true 47 | 48 | 49 | true 50 | Base 51 | true 52 | 53 | 54 | CSPRNG_sample 55 | .\$(Platform)\$(Config) 56 | .\$(Platform)\$(Config) 57 | System;Xml;Data;Datasnap;Web;Soap;$(DCC_Namespace) 58 | 59 | 60 | Debug 61 | package=com.embarcadero.$(MSBuildProjectName);label=$(MSBuildProjectName);versionCode=1;versionName=1.0.0;persistent=False;restoreAnyVersion=False;installLocation=auto;largeHeap=False;theme=TitleBar;hardwareAccelerated=true;apiKey=;minSdkVersion=23;targetSdkVersion=34 62 | 63 | 64 | Debug 65 | true 66 | Winapi;System.Win;Data.Win;Datasnap.Win;Web.Win;Soap.Win;Xml.Win;Bde;$(DCC_Namespace) 67 | vclwinx;DataSnapServer;P4DMatplotLib;P4DPandas;fmx;emshosting;vclie;DbxCommonDriver;bindengine;IndyIPCommon;VCLRESTComponents;DBXMSSQLDriver;FireDACCommonODBC;emsclient;FireDACCommonDriver;appanalytics;IndyProtocols;vclx;Skia.Package.RTL;IndyIPClient;dbxcds;vcledge;bindcompvclwinx;FmxTeeUI;P4DONNXRuntime;emsedge;bindcompfmx;DBXFirebirdDriver;inetdb;FireDACSqliteDriver;DbxClientDriver;FireDACASADriver;Tee;soapmidas;vclactnband;TeeUI;fmxFireDAC;dbexpress;Python;FireDACInfxDriver;P4DTools;DBXMySQLDriver;P4DPyPackage;VclSmp;inet;DataSnapCommon;PythonVcl;vcltouch;fmxase;P4DOpenCV;DBXOdbcDriver;dbrtl;FireDACDBXDriver;Skia.Package.FMX;FireDACOracleDriver;fmxdae;TeeDB;FireDACMSAccDriver;CustomIPTransport;FireDACMSSQLDriver;P4DSciPy;DataSnapIndy10ServerTransport;P4DTensorFlow;DataSnapConnectors;P4DKeras;vcldsnap;DBXInterBaseDriver;FireDACMongoDBDriver;IndySystem;FireDACTDataDriver;Skia.Package.VCL;vcldb;vclFireDAC;bindcomp;FireDACCommon;DataSnapServerMidas;FireDACODBCDriver;emsserverresource;IndyCore;RESTBackendComponents;P4DScikitLearn;P4DPyTorch;bindcompdbx;rtl;FireDACMySQLDriver;FireDACADSDriver;RESTComponents;DBXSqliteDriver;vcl;IndyIPServer;dsnapxml;dsnapcon;DataSnapClient;DataSnapProviderClient;adortl;P4DNLTK;DBXSybaseASEDriver;FixInsight_12;DBXDb2Driver;vclimg;DataSnapFireDAC;emsclientfiredac;FireDACPgDriver;FireDAC;FireDACDSDriver;inetdbxpress;xmlrtl;tethering;P4DEnvironment;bindcompvcl;dsnap;CloudService;DBXSybaseASADriver;DBXOracleDriver;FireDACDb2Driver;DBXInformixDriver;P4DNumPy;fmxobj;bindcompvclsmp;FMXTee;DataSnapNativeClient;PythonFmx;AIAPI;DatasnapConnectorsFreePascal;soaprtl;soapserver;FireDACIBDriver;$(DCC_UsePackage) 68 | $(BDS)\bin\Artwork\Windows\UWP\delphi_UwpDefault_150.png 69 | $(BDS)\bin\Artwork\Windows\UWP\delphi_UwpDefault_44.png 70 | CompanyName=;FileDescription=$(MSBuildProjectName);FileVersion=1.0.0.0;InternalName=;LegalCopyright=;LegalTrademarks=;OriginalFilename=;ProgramID=com.embarcadero.$(MSBuildProjectName);ProductName=$(MSBuildProjectName);ProductVersion=1.0.0.0;Comments= 71 | 1033 72 | 73 | 74 | Debug 75 | Winapi;System.Win;Data.Win;Datasnap.Win;Web.Win;Soap.Win;Xml.Win;$(DCC_Namespace) 76 | CompanyName=;FileDescription=$(MSBuildProjectName);FileVersion=1.0.0.0;InternalName=;LegalCopyright=;LegalTrademarks=;OriginalFilename=;ProgramID=com.embarcadero.$(MSBuildProjectName);ProductName=$(MSBuildProjectName);ProductVersion=1.0.0.0;Comments= 77 | 1033 78 | 79 | 80 | Debug 81 | $(MSBuildProjectName) 82 | true 83 | CFBundleName=$(MSBuildProjectName);CFBundleDevelopmentRegion=en;CFBundleDisplayName=$(MSBuildProjectName);CFBundleIdentifier=$(MSBuildProjectName);CFBundleInfoDictionaryVersion=7.1;CFBundleVersion=1.0.0;CFBundleShortVersionString=1.0.0;CFBundlePackageType=APPL;CFBundleSignature=????;LSRequiresIPhoneOS=true;CFBundleAllowMixedLocalizations=YES;CFBundleExecutable=$(MSBuildProjectName);UIDeviceFamily=iPhone & iPad;NSLocationAlwaysUsageDescription=The reason for accessing the location information of the user;NSLocationWhenInUseUsageDescription=The reason for accessing the location information of the user;NSLocationAlwaysAndWhenInUseUsageDescription=The reason for accessing the location information of the user;UIBackgroundModes=;NSContactsUsageDescription=The reason for accessing the contacts;NSPhotoLibraryUsageDescription=The reason for accessing the photo library;NSPhotoLibraryAddUsageDescription=The reason for adding to the photo library;NSCameraUsageDescription=The reason for accessing the camera;NSFaceIDUsageDescription=The reason for accessing the face id;NSMicrophoneUsageDescription=The reason for accessing the microphone;NSSiriUsageDescription=The reason for accessing Siri;ITSAppUsesNonExemptEncryption=false;NSBluetoothAlwaysUsageDescription=The reason for accessing bluetooth;NSBluetoothPeripheralUsageDescription=The reason for accessing bluetooth peripherals;NSCalendarsUsageDescription=The reason for accessing the calendar data;NSRemindersUsageDescription=The reason for accessing the reminders;NSMotionUsageDescription=The reason for accessing the accelerometer;NSSpeechRecognitionUsageDescription=The reason for requesting to send user data to Apple's speech recognition servers 84 | iPhoneAndiPad 85 | 86 | 87 | true 88 | true 89 | DEBUG;$(DCC_Define) 90 | true 91 | true 92 | false 93 | true 94 | true 95 | 96 | 97 | false 98 | 99 | 100 | 0 101 | RELEASE;$(DCC_Define) 102 | false 103 | 0 104 | 105 | 106 | 107 | MainSource 108 | 109 | 110 | 111 | 112 | 113 | 114 | 115 | 116 | 117 | Base 118 | 119 | 120 | Cfg_1 121 | Base 122 | 123 | 124 | Cfg_2 125 | Base 126 | 127 | 128 | 129 | Delphi.Personality.12 130 | Application 131 | 132 | 133 | 134 | CSPRNG_sample.dpr 135 | 136 | 137 | 138 | False 139 | True 140 | True 141 | False 142 | False 143 | True 144 | True 145 | False 146 | True 147 | False 148 | 149 | 150 | 12 151 | 152 | 153 | 154 | 155 | 156 | -------------------------------------------------------------------------------- /src/CSPRNG_sample.res: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jimmckeeth/DelphiCSPRNG/f49d935b20d06f61fc18461c71b22da56da48dca/src/CSPRNG_sample.res -------------------------------------------------------------------------------- /tests/CSPRNG.Tests.Providers.pas: -------------------------------------------------------------------------------- 1 | unit CSPRNG.Tests.Providers; 2 | 3 | interface 4 | 5 | uses 6 | SysUtils, 7 | DUnitX.TestFramework, 8 | CSPRNG, 9 | CSPRNG.Interfaces; 10 | 11 | type 12 | 13 | [TestFixture] 14 | TCSPRNGProviderTests = class 15 | private 16 | FCSPRNGProvider: ICSPRNGProvider; 17 | public 18 | [Setup] 19 | procedure Setup; 20 | [TearDown] 21 | procedure TearDown; 22 | 23 | [Test] 24 | procedure TestGetBytes_Length; 25 | [Test] 26 | procedure TestGetBytes_Randomness; 27 | 28 | [Test] 29 | procedure TestPadBytes_EmptyArrayTo4; 30 | [Test] 31 | procedure TestPadBytes_ExactLengthTo4; 32 | [Test] 33 | procedure TestPadBytes_LongArrayTo4; 34 | [Test] 35 | procedure TestPadBytes_ShortArrayTo4; 36 | [Test] 37 | procedure TestPadBytes_ShortArrayTo8; 38 | [Test] 39 | procedure TestPadBytes_ExactLengthTo8; 40 | [Test] 41 | procedure TestPadBytes_LongArrayTo8; 42 | [Test] 43 | procedure TestPadBytes_EmptyArrayTo8; 44 | 45 | [Test] 46 | [TestCase('UInt32_DefaultRange', '123456')] 47 | [TestCase('UInt32_SmallRange', '20')] 48 | procedure TestGetUInt32(const ExpectedMax: string); 49 | 50 | [Test] 51 | [TestCase('Int64_DefaultRange', '9223372036854775807')] 52 | [TestCase('Int64_SmallRange', '1000000')] 53 | [TestCase('Int64_SingleValue', '5')] 54 | procedure TestGetInt64(const ExpectedMax: string); 55 | 56 | [Test] 57 | [TestCase('Int32_DefaultRange', '2147483647')] 58 | [TestCase('Int32_SmallRange', '100')] 59 | [TestCase('Int32_SingleValue', '5')] 60 | procedure TestGetInt32(const ExpectedMax: string); 61 | 62 | [Test] 63 | [TestCase('UInt64_DefaultRange', '$FFFFFFFFFFFFFFFF')] 64 | [TestCase('UInt64_SmallRange', '1000000')] 65 | [TestCase('UInt64_SingleValue', '5')] 66 | procedure TestGetUInt64(const ExpectedMax: string); 67 | 68 | [Test] 69 | [TestCase('Len64','64')] 70 | [TestCase('Len512','512')] 71 | [TestCase('Len2048','2048')] 72 | procedure TestGetBase64_CustomLength(const Len: String); 73 | [Test] 74 | procedure TestGetBase64_Length; 75 | [Test] 76 | procedure TestGetBase64_Randomness; 77 | [Test] 78 | procedure TestGetBase64_ValidEncoding; 79 | 80 | [Test] 81 | procedure TestGetFloat_Range; 82 | [Test] 83 | procedure TestSeedFromBytes; 84 | [Test] 85 | procedure TestSeedFromEntropySource; 86 | end; 87 | 88 | implementation 89 | 90 | uses 91 | System.Math, 92 | System.NetEncoding, 93 | System.Generics.Collections, 94 | System.Classes, 95 | CSPRNG.Provider.Base; 96 | 97 | { TCSPRNGProviderTests } 98 | 99 | procedure TCSPRNGProviderTests.Setup; 100 | begin 101 | FCSPRNGProvider := GetCSPRNGProvider; 102 | end; 103 | 104 | procedure TCSPRNGProviderTests.TearDown; 105 | begin 106 | FCSPRNGProvider := nil; 107 | end; 108 | 109 | procedure TCSPRNGProviderTests.TestGetBytes_Length; 110 | const 111 | ByteCount = 1024; 112 | var 113 | Bytes: TBytes; 114 | begin 115 | Bytes := FCSPRNGProvider.GetBytes(ByteCount); 116 | Assert.AreEqual(UInt64(ByteCount), UInt64(Length(Bytes)), 117 | 'Incorrect number of bytes generated'); 118 | end; 119 | 120 | procedure TCSPRNGProviderTests.TestGetBytes_Randomness; 121 | const 122 | ByteCount = 1024 * 1024; // 1MB of data 123 | begin 124 | var Bytes := FCSPRNGProvider.GetBytes(ByteCount); 125 | 126 | var Frequencies := TDictionary.Create; 127 | for var Byte in Bytes do 128 | begin 129 | var Frequency: Integer; 130 | if Frequencies.TryGetValue(Byte, Frequency) then 131 | Frequencies[Byte] := Frequency + 1 132 | else 133 | Frequencies.Add(Byte, 1); 134 | end; 135 | 136 | // Roughly check for uniform distribution (this is not a perfect statistical test) 137 | for var Frequency in Frequencies.Values do 138 | Assert.IsTrue(Frequency > ByteCount * 0.9 / 256, 'Insufficient randomness detected'); // 10% tolerance 139 | end; 140 | 141 | 142 | procedure TCSPRNGProviderTests.TestGetUInt32(const ExpectedMax: string); 143 | begin 144 | var MaxVal: Cardinal := StrToInt(ExpectedMax); 145 | 146 | for var i := 1 to 1000 do 147 | begin 148 | var Value := FCSPRNGProvider.GetUInt32(MaxVal); 149 | Assert.IsTrue(Value <= MaxVal, 'UInt32 above maximum'); 150 | end; 151 | end; 152 | 153 | procedure TCSPRNGProviderTests.TestGetUInt64(const ExpectedMax: string); 154 | var 155 | MaxVal, Value: UInt64; 156 | i: Integer; 157 | begin 158 | MaxVal := StrToUInt64(ExpectedMax); 159 | 160 | for i := 1 to 1000 do 161 | begin 162 | Value := FCSPRNGProvider.GetUInt64(MaxVal); 163 | Assert.IsTrue(Value >= 0, 'UInt64 below minimum (0)'); 164 | Assert.IsTrue(Value <= MaxVal, 'UInt64 above maximum'); 165 | end; 166 | end; 167 | 168 | procedure TCSPRNGProviderTests.TestGetInt32(const ExpectedMax: string); 169 | var 170 | MaxVal, Value: Int32; 171 | i: Integer; 172 | begin 173 | MaxVal := StrToInt(ExpectedMax); 174 | 175 | for i := 1 to 1000 do 176 | begin 177 | Value := FCSPRNGProvider.GetInt32(MaxVal); 178 | Assert.IsTrue(Value >= 0, 'Int32 below minimum (0)'); 179 | Assert.IsTrue(Value <= MaxVal, 'Int32 above maximum'); 180 | end; 181 | end; 182 | 183 | procedure TCSPRNGProviderTests.TestGetInt64(const ExpectedMax: string); 184 | var 185 | MaxVal, Value: Int64; 186 | i: Integer; 187 | begin 188 | MaxVal := StrToInt64(ExpectedMax); 189 | 190 | for i := 1 to 1000 do 191 | begin 192 | Value := FCSPRNGProvider.GetInt64(MaxVal); 193 | Assert.IsTrue(Value >= 0, 'Int64 below minimum (0)'); 194 | Assert.IsTrue(Value <= MaxVal, 'Int64 above maximum'); 195 | end; 196 | end; 197 | 198 | procedure TCSPRNGProviderTests.TestGetFloat_Range; 199 | begin 200 | for var i := 1 to 1000 do 201 | begin 202 | var Value := FCSPRNGProvider.GetFloat; 203 | Assert.IsTrue(Value >= 0, 'Float below 0'); 204 | Assert.IsTrue(Value < 1, 'Float not strictly less than 1'); 205 | end; 206 | end; 207 | 208 | procedure TCSPRNGProviderTests.TestSeedFromBytes; 209 | begin 210 | // ... (Implement a test for SeedFromBytes. 211 | // This could involve checking for changes in the random output after seeding 212 | // or verifying that the same seed produces the same output sequence.) 213 | end; 214 | 215 | procedure TCSPRNGProviderTests.TestSeedFromEntropySource; 216 | begin 217 | // ... (Implement a test for SeedFromEntropySource. 218 | // This is more challenging, as it relies on system entropy. 219 | // You could potentially check if the output changes after reseeding, but it's not guaranteed.) 220 | end; 221 | 222 | procedure TCSPRNGProviderTests.TestPadBytes_ShortArrayTo4; 223 | begin 224 | var InputBytes: TBytes := [ $1, $2 ]; 225 | var ExpectedBytes: TBytes := [ $0, $0, $1, $2 ]; 226 | var ResultBytes := TCSPRNGProviderBase.PadBytes(InputBytes, SizeOf(UInt32)); 227 | Assert.AreEqual(ExpectedBytes, ResultBytes); 228 | end; 229 | 230 | procedure TCSPRNGProviderTests.TestPadBytes_ExactLengthTo4; 231 | begin 232 | var InputBytes: TBytes := [ $1, $2, $3, $4 ]; 233 | var ExpectedBytes: TBytes := [ $1, $2, $3, $4 ]; 234 | var ResultBytes := TCSPRNGProviderBase.PadBytes(InputBytes, SizeOf(UInt32)); 235 | Assert.AreEqual(ExpectedBytes, ResultBytes); 236 | end; 237 | 238 | procedure TCSPRNGProviderTests.TestPadBytes_LongArrayTo4; 239 | begin 240 | var InputBytes: TBytes := [ $1, $2, $3, $4, $5, $6 ]; 241 | var ExpectedBytes: TBytes := [ $1, $2, $3, $4 ]; 242 | var ResultBytes := TCSPRNGProviderBase.PadBytes(InputBytes, SizeOf(UInt32)); 243 | Assert.AreEqual(ExpectedBytes, ResultBytes); 244 | end; 245 | 246 | procedure TCSPRNGProviderTests.TestPadBytes_EmptyArrayTo4; 247 | begin 248 | var InputBytes: TBytes := []; 249 | var ExpectedBytes: TBytes := [ $0, $0, $0, $0 ]; 250 | var ResultBytes := TCSPRNGProviderBase.PadBytes(InputBytes, SizeOf(UInt32)); 251 | Assert.AreEqual(ExpectedBytes, ResultBytes); 252 | end; 253 | 254 | procedure TCSPRNGProviderTests.TestPadBytes_ShortArrayTo8; 255 | begin 256 | var InputBytes: TBytes := [$1, $2, $3, $4]; 257 | var ExpectedBytes: TBytes := [$0, $0, $0, $0, $1, $2, $3, $4]; 258 | var ResultBytes := TCSPRNGProviderBase.PadBytes(InputBytes, SizeOf(UInt64)); 259 | Assert.AreEqual(ExpectedBytes, ResultBytes, 'Incorrect padding: ShortArrayTo8'); 260 | end; 261 | 262 | procedure TCSPRNGProviderTests.TestPadBytes_ExactLengthTo8; 263 | begin 264 | var InputBytes: TBytes := [$1, $2, $3, $4, $5, $6, $7, $8]; 265 | var ExpectedBytes: TBytes := [$1, $2, $3, $4, $5, $6, $7, $8]; 266 | var ResultBytes := TCSPRNGProviderBase.PadBytes(InputBytes, SizeOf(UInt64)); 267 | Assert.AreEqual(ExpectedBytes, ResultBytes, 'Incorrect padding: ExactLengthTo8'); 268 | end; 269 | 270 | procedure TCSPRNGProviderTests.TestPadBytes_LongArrayTo8; 271 | begin 272 | var InputBytes: TBytes := [$1, $2, $3, $4, $5, $6, $7, $8, $9, $A]; 273 | var ExpectedBytes: TBytes := [$1, $2, $3, $4, $5, $6, $7, $8]; 274 | var ResultBytes := TCSPRNGProviderBase.PadBytes(InputBytes, SizeOf(UInt64)); 275 | Assert.AreEqual(ExpectedBytes, ResultBytes, 'Incorrect padding: LongArrayTo8'); 276 | end; 277 | 278 | procedure TCSPRNGProviderTests.TestPadBytes_EmptyArrayTo8; 279 | begin 280 | var InputBytes: TBytes := []; 281 | var ExpectedBytes: TBytes := [$0, $0, $0, $0, $0, $0, $0, $0]; 282 | var ResultBytes := TCSPRNGProviderBase.PadBytes(InputBytes, SizeOf(UInt64)); 283 | Assert.AreEqual(ExpectedBytes, ResultBytes, 'Incorrect padding: EmptyArrayTo8'); 284 | end; 285 | 286 | procedure TCSPRNGProviderTests.TestGetBase64_Length; 287 | begin 288 | var Bytes := TNetEncoding.Base64.DecodeStringToBytes(FCSPRNGProvider.GetBase64(1024)); 289 | Assert.AreEqual(UInt64(1024), UInt64(Length(Bytes)), 'Incorrect Base64 string length'); 290 | end; 291 | 292 | function GetBase64EncodedLength(ByteLength: Integer): Integer; 293 | begin 294 | Result := ((ByteLength + 2) div 3) * 4; 295 | end; 296 | 297 | procedure TCSPRNGProviderTests.TestGetBase64_CustomLength(const Len: String); 298 | var 299 | Base64String: string; 300 | iLen: Integer; 301 | ExpectedLength: Integer; 302 | begin 303 | iLen := StrToInt(Len); 304 | Base64String := FCSPRNGProvider.GetBase64(iLen); 305 | 306 | // Calculate expected length with padding 307 | ExpectedLength := GetBase64EncodedLength(iLen); 308 | 309 | Assert.AreEqual(ExpectedLength, Length(Base64String), 310 | 'Incorrect Base64 string length for custom length: ' + Len); 311 | end; 312 | 313 | procedure TCSPRNGProviderTests.TestGetBase64_Randomness; 314 | var 315 | Strings: TStringList; 316 | Base64String: string; 317 | i: Integer; 318 | begin 319 | Strings := TStringList.Create; 320 | try 321 | for i := 1 to 100 do 322 | begin 323 | Base64String := FCSPRNGProvider.GetBase64(64); 324 | Assert.IsFalse(Strings.Contains(Base64String), 'Duplicate Base64 string generated'); 325 | Strings.Add(Base64String); 326 | end; 327 | finally 328 | Strings.Free; 329 | end; 330 | end; 331 | 332 | procedure TCSPRNGProviderTests.TestGetBase64_ValidEncoding; 333 | var 334 | Bytes: TBytes; 335 | begin 336 | var Base64String := FCSPRNGProvider.GetBase64; 337 | var Encoding := TBase64Encoding.Create(0); 338 | try 339 | Assert.WillNotRaiseAny( 340 | procedure 341 | begin 342 | Bytes := Encoding.DecodeStringToBytes(Base64String); 343 | end, 344 | 'Invalid Base64 encoding'); 345 | Assert.AreEqual(Base64String, Encoding.EncodeBytesToString(Bytes), 346 | 'Failed round trip back to Base64.'); 347 | finally 348 | Encoding.Free; 349 | end; 350 | end; 351 | 352 | initialization 353 | TDUnitX.Options.ExitBehavior := TDUnitXExitBehavior.Pause 354 | end. 355 | 356 | -------------------------------------------------------------------------------- /tests/CSPRNG.Tests.dpr: -------------------------------------------------------------------------------- 1 | program CSPRNG.Tests; 2 | 3 | {$IFNDEF TESTINSIGHT} 4 | {$APPTYPE CONSOLE} 5 | {$ENDIF} 6 | {$STRONGLINKTYPES ON} 7 | uses 8 | System.SysUtils, 9 | {$IFDEF TESTINSIGHT} 10 | TestInsight.DUnitX, 11 | {$ELSE} 12 | DUnitX.Loggers.Console, 13 | DUnitX.Loggers.Xml.NUnit, 14 | {$ENDIF } 15 | DUnitX.TestFramework, 16 | CSPRNG.Tests.Providers in 'CSPRNG.Tests.Providers.pas', 17 | CSPRNG.Interfaces in '..\src\CSPRNG.Interfaces.pas', 18 | CSPRNG in '..\src\CSPRNG.pas', 19 | CSPRNG.Provider.Base in '..\src\CSPRNG.Provider.Base.pas', 20 | CSPRNG.Provider.Windows in '..\src\CSPRNG.Provider.Windows.pas', 21 | CSPRNG.Provider.Posix in '..\src\CSPRNG.Provider.Posix.pas', 22 | CSPRNG.Provider.MacOS64 in '..\src\CSPRNG.Provider.MacOS64.pas'; 23 | 24 | { keep comment here to protect the following conditional from being removed by the IDE when adding a unit } 25 | {$IFNDEF TESTINSIGHT} 26 | var 27 | runner: ITestRunner; 28 | results: IRunResults; 29 | logger: ITestLogger; 30 | nunitLogger : ITestLogger; 31 | {$ENDIF} 32 | begin 33 | {$IFDEF TESTINSIGHT} 34 | TestInsight.DUnitX.RunRegisteredTests; 35 | {$ELSE} 36 | try 37 | //Check command line options, will exit if invalid 38 | TDUnitX.CheckCommandLine; 39 | //Create the test runner 40 | runner := TDUnitX.CreateRunner; 41 | //Tell the runner to use RTTI to find Fixtures 42 | runner.UseRTTI := True; 43 | //When true, Assertions must be made during tests; 44 | runner.FailsOnNoAsserts := False; 45 | 46 | //tell the runner how we will log things 47 | //Log to the console window if desired 48 | if TDUnitX.Options.ConsoleMode <> TDunitXConsoleMode.Off then 49 | begin 50 | logger := TDUnitXConsoleLogger.Create(TDUnitX.Options.ConsoleMode = TDunitXConsoleMode.Quiet); 51 | runner.AddLogger(logger); 52 | end; 53 | //Generate an NUnit compatible XML File 54 | nunitLogger := TDUnitXXMLNUnitFileLogger.Create(TDUnitX.Options.XMLOutputFile); 55 | runner.AddLogger(nunitLogger); 56 | 57 | //Run tests 58 | results := runner.Execute; 59 | if not results.AllPassed then 60 | System.ExitCode := EXIT_ERRORS; 61 | 62 | {$IFNDEF CI} 63 | //We don't want this happening when running under CI. 64 | if TDUnitX.Options.ExitBehavior = TDUnitXExitBehavior.Pause then 65 | begin 66 | System.Write('Done.. press key to quit.'); 67 | System.Readln; 68 | end; 69 | {$ENDIF} 70 | except 71 | on E: Exception do 72 | System.Writeln(E.ClassName, ': ', E.Message); 73 | end; 74 | {$ENDIF} 75 | end. 76 | -------------------------------------------------------------------------------- /tests/CSPRNG.Tests.dproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | True 4 | Console 5 | Debug 6 | None 7 | CSPRNG.Tests.dpr 8 | Win32 9 | {7D0CB541-0803-4C81-969D-19AF88443577} 10 | CSPRNG.Tests 11 | 20.2 12 | 4227 13 | 14 | 15 | true 16 | 17 | 18 | true 19 | Base 20 | true 21 | 22 | 23 | true 24 | Base 25 | true 26 | 27 | 28 | true 29 | Base 30 | true 31 | 32 | 33 | true 34 | Base 35 | true 36 | 37 | 38 | true 39 | Cfg_1 40 | true 41 | true 42 | 43 | 44 | true 45 | Base 46 | true 47 | 48 | 49 | CSPRNG_Tests 50 | .\$(Platform)\$(Config) 51 | .\$(Platform)\$(Config) 52 | System;Xml;Data;Datasnap;Web;Soap;$(DCC_Namespace) 53 | $(DUnitX);$(DCC_UnitSearchPath) 54 | $(BDS)\bin\delphi_PROJECTICNS.icns 55 | $(BDS)\bin\delphi_PROJECTICON.ico 56 | 57 | 58 | Debug 59 | CFBundleName=$(MSBuildProjectName);CFBundleDisplayName=$(MSBuildProjectName);CFBundleIdentifier=$(MSBuildProjectName);CFBundleVersion=1.0.0;CFBundleShortVersionString=1.0.0;CFBundlePackageType=APPL;CFBundleSignature=????;CFBundleAllowMixedLocalizations=YES;CFBundleExecutable=$(MSBuildProjectName);NSHighResolutionCapable=true;LSApplicationCategoryType=public.app-category.utilities;NSLocationUsageDescription=The reason for accessing the location information of the user;NSContactsUsageDescription=The reason for accessing the contacts;NSCalendarsUsageDescription=The reason for accessing the calendar data;NSRemindersUsageDescription=The reason for accessing the reminders;NSCameraUsageDescription=The reason for accessing the camera;NSMicrophoneUsageDescription=The reason for accessing the microphone;NSMotionUsageDescription=The reason for accessing the accelerometer;NSDesktopFolderUsageDescription=The reason for accessing the Desktop folder;NSDocumentsFolderUsageDescription=The reason for accessing the Documents folder;NSDownloadsFolderUsageDescription=The reason for accessing the Downloads folder;NSNetworkVolumesUsageDescription=The reason for accessing files on a network volume;NSRemovableVolumesUsageDescription=The reason for accessing files on a removable volume;NSSpeechRecognitionUsageDescription=The reason for requesting to send user data to Apple's speech recognition servers;ITSAppUsesNonExemptEncryption=false;NSBluetoothAlwaysUsageDescription=The reason for accessing the Bluetooth interface 60 | 61 | 62 | Debug 63 | Winapi;System.Win;Data.Win;Datasnap.Win;Web.Win;Soap.Win;Xml.Win;Bde;$(DCC_Namespace) 64 | RaizeComponentsVcl;vclwinx;DataSnapServer;P4DPandas;fmx;vclie;DbxCommonDriver;bindengine;IndyIPCommon;VCLRESTComponents;DBXMSSQLDriver;FireDACCommonODBC;emsclient;ApperceptAPIClient;appanalytics;IndyProtocols;vclx;Skia.Package.RTL;dbxcds;vcledge;FmxTeeUI;P4DONNXRuntime;DBXFirebirdDriver;FireDACSqliteDriver;DbxClientDriver;soapmidas;TeeUI;dbexpress;Python;inet;PythonVcl;vcltouch;P4DOpenCV;FireDACDBXDriver;fmxdae;CustomIPTransport;FireDACMSSQLDriver;P4DSciPy;IndySystem;vclFireDAC;FireDACCommon;DataSnapServerMidas;FireDACODBCDriver;emsserverresource;P4DScikitLearn;P4DPyTorch;bindcompdbx;rtl;FireDACMySQLDriver;DBXSqliteDriver;DBXSybaseASEDriver;vclimg;DataSnapFireDAC;inetdbxpress;FireDAC;xmlrtl;P4DEnvironment;dsnap;FireDACDb2Driver;DBXOracleDriver;DBXInformixDriver;fmxobj;bindcompvclsmp;DataSnapNativeClient;AIAPI;DatasnapConnectorsFreePascal;P4DMatplotLib;emshosting;FireDACCommonDriver;RadiantShapesFmx_Design;IndyIPClient;bindcompvclwinx;emsedge;bindcompfmx;inetdb;FireDACASADriver;Tee;vclactnband;fmxFireDAC;FireDACInfxDriver;P4DTools;DBXMySQLDriver;P4DPyPackage;VclSmp;DataSnapCommon;fmxase;DBXOdbcDriver;dbrtl;FireDACOracleDriver;Skia.Package.FMX;TeeDB;FireDACMSAccDriver;DataSnapIndy10ServerTransport;P4DTensorFlow;DataSnapConnectors;P4DKeras;vcldsnap;DBXInterBaseDriver;FireDACMongoDBDriver;RadiantShapesFmx;FireDACTDataDriver;Skia.Package.VCL;vcldb;bindcomp;IndyCore;RESTBackendComponents;AWSSDKFMX;FireDACADSDriver;RaizeComponentsVclDb;AWSSDKVCL;RESTComponents;IndyIPServer;vcl;dsnapxml;adortl;dsnapcon;DataSnapClient;DataSnapProviderClient;P4DNLTK;FixInsight_12;DBXDb2Driver;emsclientfiredac;FireDACPgDriver;FireDACDSDriver;tethering;bindcompvcl;CloudService;DBXSybaseASADriver;P4DNumPy;FMXTee;PythonFmx;soaprtl;soapserver;FireDACIBDriver;$(DCC_UsePackage) 65 | CompanyName=;FileDescription=$(MSBuildProjectName);FileVersion=1.0.0.0;InternalName=;LegalCopyright=;LegalTrademarks=;OriginalFilename=;ProgramID=com.embarcadero.$(MSBuildProjectName);ProductName=$(MSBuildProjectName);ProductVersion=1.0.0.0;Comments= 66 | 1033 67 | 68 | 69 | Debug 70 | Winapi;System.Win;Data.Win;Datasnap.Win;Web.Win;Soap.Win;Xml.Win;$(DCC_Namespace) 71 | CompanyName=;FileDescription=$(MSBuildProjectName);FileVersion=1.0.0.0;InternalName=;LegalCopyright=;LegalTrademarks=;OriginalFilename=;ProgramID=com.embarcadero.$(MSBuildProjectName);ProductName=$(MSBuildProjectName);ProductVersion=1.0.0.0;Comments= 72 | 1033 73 | 74 | 75 | true 76 | true 77 | DEBUG;$(DCC_Define) 78 | true 79 | true 80 | false 81 | true 82 | true 83 | 84 | 85 | none 86 | false 87 | (None) 88 | 1033 89 | 90 | 91 | 0 92 | RELEASE;$(DCC_Define) 93 | false 94 | 0 95 | 96 | 97 | 98 | MainSource 99 | 100 | 101 | 102 | 103 | 104 | 105 | 106 | 107 | 108 | Base 109 | 110 | 111 | Cfg_1 112 | Base 113 | 114 | 115 | Cfg_2 116 | Base 117 | 118 | 119 | 120 | Delphi.Personality.12 121 | Console 122 | 123 | 124 | 125 | CSPRNG.Tests.dpr 126 | 127 | 128 | 129 | 130 | False 131 | False 132 | True 133 | True 134 | False 135 | True 136 | True 137 | False 138 | False 139 | False 140 | 141 | 142 | 12 143 | 144 | 145 | 146 | 147 | 148 | -------------------------------------------------------------------------------- /tests/CSPRNG.Tests.res: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jimmckeeth/DelphiCSPRNG/f49d935b20d06f61fc18461c71b22da56da48dca/tests/CSPRNG.Tests.res -------------------------------------------------------------------------------- /tests/Win32/Debug/TestInsightSettings.ini: -------------------------------------------------------------------------------- 1 | [Config] 2 | BaseUrl=http://MSI:8103 3 | -------------------------------------------------------------------------------- /tests/Win32/Debug/dunitx-results.xml: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | -------------------------------------------------------------------------------- /tests/Win64/Debug/dunitx-results.xml: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | --------------------------------------------------------------------------------