├── .gitattributes ├── .gitignore ├── README.md ├── WebSecure.Models ├── RegisterVerification.cs ├── ResetPasswordVerification.cs ├── User.cs ├── UserTokens.cs └── WebSecure.Models.csproj ├── WebSecure.Repository ├── DatabaseContext.cs ├── IUserRepository.cs ├── IVerificationRepository.cs ├── UserRepository.cs ├── VerificationRepository.cs └── WebSecure.Repository.csproj ├── WebSecure.ViewModel ├── AppSettings.cs ├── ChangePasswordViewModel.cs ├── ConnectionStrings.cs ├── ForgotPasswordViewModel.cs ├── LoginViewModel.cs ├── RegisterViewModel.cs ├── ResetPasswordViewModel.cs └── WebSecure.ViewModel.csproj ├── WebSecure.sln └── WebSecure ├── Controllers ├── ChangePasswordController.cs ├── DashboardController.cs ├── ErrorController.cs ├── ForgotPasswordController.cs ├── HomeController.cs ├── PortalController.cs ├── RegistrationController.cs ├── ResetPasswordController.cs ├── VerifyRegistrationController.cs └── VerifyResetPasswordController.cs ├── Filters ├── AuthorizeResetPasswordAttribute.cs └── AuthorizeUserAttribute.cs ├── Helpers ├── AesAlgorithm.cs ├── GenerateHashSha256.cs ├── GenerateHashSha512.cs ├── GenerateRandomNumbers.cs └── SecurityManager.cs ├── Images ├── 1.png ├── 10.png ├── 11.png ├── 12.png ├── 13.png ├── 2.png ├── 3.png ├── 4.png ├── 5.png ├── 6.png ├── 7.png ├── 8.png └── 9.png ├── Models └── ErrorViewModel.cs ├── Program.cs ├── Properties └── launchSettings.json ├── Startup.cs ├── Views ├── ChangePassword │ └── Process.cshtml ├── Dashboard │ └── Dashboard.cshtml ├── ForgotPassword │ └── Process.cshtml ├── Home │ ├── Index.cshtml │ └── Privacy.cshtml ├── Portal │ └── Login.cshtml ├── Registration │ └── Register.cshtml ├── ResetPassword │ └── Reset.cshtml ├── Shared │ ├── Error.cshtml │ ├── _Layout.cshtml │ ├── _UserLayout.cshtml │ └── _ValidationScriptsPartial.cshtml ├── VerifyRegistration │ └── Completed.cshtml ├── _ViewImports.cshtml └── _ViewStart.cshtml ├── WebSecure.csproj ├── appsettings.Development.json ├── appsettings.json └── wwwroot ├── crypto ├── sha256.min.js └── sha512.min.js ├── css └── site.css ├── favicon.ico ├── js └── site.js └── lib ├── bootstrap ├── LICENSE └── dist │ ├── css │ ├── bootstrap-grid.css │ ├── bootstrap-grid.css.map │ ├── bootstrap-grid.min.css │ ├── bootstrap-grid.min.css.map │ ├── bootstrap-reboot.css │ ├── bootstrap-reboot.css.map │ ├── bootstrap-reboot.min.css │ ├── bootstrap-reboot.min.css.map │ ├── bootstrap.css │ ├── bootstrap.css.map │ ├── bootstrap.min.css │ └── bootstrap.min.css.map │ └── js │ ├── bootstrap.bundle.js │ ├── bootstrap.bundle.js.map │ ├── bootstrap.bundle.min.js │ ├── bootstrap.bundle.min.js.map │ ├── bootstrap.js │ ├── bootstrap.js.map │ ├── bootstrap.min.js │ └── bootstrap.min.js.map ├── jquery-validation-unobtrusive ├── LICENSE.txt ├── jquery.validate.unobtrusive.js └── jquery.validate.unobtrusive.min.js ├── jquery-validation ├── LICENSE.md └── dist │ ├── additional-methods.js │ ├── additional-methods.min.js │ ├── jquery.validate.js │ └── jquery.validate.min.js └── jquery ├── LICENSE.txt └── dist ├── jquery.js ├── jquery.min.js └── jquery.min.map /.gitattributes: -------------------------------------------------------------------------------- 1 | ############################################################################### 2 | # Set default behavior to automatically normalize line endings. 3 | ############################################################################### 4 | * text=auto 5 | 6 | ############################################################################### 7 | # Set default behavior for command prompt diff. 8 | # 9 | # This is need for earlier builds of msysgit that does not have it on by 10 | # default for csharp files. 11 | # Note: This is only used by command line 12 | ############################################################################### 13 | #*.cs diff=csharp 14 | 15 | ############################################################################### 16 | # Set the merge driver for project and solution files 17 | # 18 | # Merging from the command prompt will add diff markers to the files if there 19 | # are conflicts (Merging from VS is not affected by the settings below, in VS 20 | # the diff markers are never inserted). Diff markers may cause the following 21 | # file extensions to fail to load in VS. An alternative would be to treat 22 | # these files as binary and thus will always conflict and require user 23 | # intervention with every merge. To do so, just uncomment the entries below 24 | ############################################################################### 25 | #*.sln merge=binary 26 | #*.csproj merge=binary 27 | #*.vbproj merge=binary 28 | #*.vcxproj merge=binary 29 | #*.vcproj merge=binary 30 | #*.dbproj merge=binary 31 | #*.fsproj merge=binary 32 | #*.lsproj merge=binary 33 | #*.wixproj merge=binary 34 | #*.modelproj merge=binary 35 | #*.sqlproj merge=binary 36 | #*.wwaproj merge=binary 37 | 38 | ############################################################################### 39 | # behavior for image files 40 | # 41 | # image files are treated as binary by default. 42 | ############################################################################### 43 | #*.jpg binary 44 | #*.png binary 45 | #*.gif binary 46 | 47 | ############################################################################### 48 | # diff behavior for common document formats 49 | # 50 | # Convert binary document formats to text before diffing them. This feature 51 | # is only available from the command line. Turn it on by uncommenting the 52 | # entries below. 53 | ############################################################################### 54 | #*.doc diff=astextplain 55 | #*.DOC diff=astextplain 56 | #*.docx diff=astextplain 57 | #*.DOCX diff=astextplain 58 | #*.dot diff=astextplain 59 | #*.DOT diff=astextplain 60 | #*.pdf diff=astextplain 61 | #*.PDF diff=astextplain 62 | #*.rtf diff=astextplain 63 | #*.RTF diff=astextplain 64 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | ## Ignore Visual Studio temporary files, build results, and 2 | ## files generated by popular Visual Studio add-ons. 3 | ## 4 | ## Get latest from https://github.com/github/gitignore/blob/master/VisualStudio.gitignore 5 | 6 | # User-specific files 7 | *.rsuser 8 | *.suo 9 | *.user 10 | *.userosscache 11 | *.sln.docstates 12 | 13 | # User-specific files (MonoDevelop/Xamarin Studio) 14 | *.userprefs 15 | 16 | # Build results 17 | [Dd]ebug/ 18 | [Dd]ebugPublic/ 19 | [Rr]elease/ 20 | [Rr]eleases/ 21 | x64/ 22 | x86/ 23 | [Aa][Rr][Mm]/ 24 | [Aa][Rr][Mm]64/ 25 | bld/ 26 | [Bb]in/ 27 | [Oo]bj/ 28 | [Ll]og/ 29 | 30 | # Visual Studio 2015/2017 cache/options directory 31 | .vs/ 32 | # Uncomment if you have tasks that create the project's static files in wwwroot 33 | #wwwroot/ 34 | 35 | # Visual Studio 2017 auto generated files 36 | Generated\ Files/ 37 | 38 | # MSTest test Results 39 | [Tt]est[Rr]esult*/ 40 | [Bb]uild[Ll]og.* 41 | 42 | # NUNIT 43 | *.VisualState.xml 44 | TestResult.xml 45 | 46 | # Build Results of an ATL Project 47 | [Dd]ebugPS/ 48 | [Rr]eleasePS/ 49 | dlldata.c 50 | 51 | # Benchmark Results 52 | BenchmarkDotNet.Artifacts/ 53 | 54 | # .NET Core 55 | project.lock.json 56 | project.fragment.lock.json 57 | artifacts/ 58 | 59 | # StyleCop 60 | StyleCopReport.xml 61 | 62 | # Files built by Visual Studio 63 | *_i.c 64 | *_p.c 65 | *_h.h 66 | *.ilk 67 | *.meta 68 | *.obj 69 | *.iobj 70 | *.pch 71 | *.pdb 72 | *.ipdb 73 | *.pgc 74 | *.pgd 75 | *.rsp 76 | *.sbr 77 | *.tlb 78 | *.tli 79 | *.tlh 80 | *.tmp 81 | *.tmp_proj 82 | *_wpftmp.csproj 83 | *.log 84 | *.vspscc 85 | *.vssscc 86 | .builds 87 | *.pidb 88 | *.svclog 89 | *.scc 90 | 91 | # Chutzpah Test files 92 | _Chutzpah* 93 | 94 | # Visual C++ cache files 95 | ipch/ 96 | *.aps 97 | *.ncb 98 | *.opendb 99 | *.opensdf 100 | *.sdf 101 | *.cachefile 102 | *.VC.db 103 | *.VC.VC.opendb 104 | 105 | # Visual Studio profiler 106 | *.psess 107 | *.vsp 108 | *.vspx 109 | *.sap 110 | 111 | # Visual Studio Trace Files 112 | *.e2e 113 | 114 | # TFS 2012 Local Workspace 115 | $tf/ 116 | 117 | # Guidance Automation Toolkit 118 | *.gpState 119 | 120 | # ReSharper is a .NET coding add-in 121 | _ReSharper*/ 122 | *.[Rr]e[Ss]harper 123 | *.DotSettings.user 124 | 125 | # JustCode is a .NET coding add-in 126 | .JustCode 127 | 128 | # TeamCity is a build add-in 129 | _TeamCity* 130 | 131 | # DotCover is a Code Coverage Tool 132 | *.dotCover 133 | 134 | # AxoCover is a Code Coverage Tool 135 | .axoCover/* 136 | !.axoCover/settings.json 137 | 138 | # Visual Studio code coverage results 139 | *.coverage 140 | *.coveragexml 141 | 142 | # NCrunch 143 | _NCrunch_* 144 | .*crunch*.local.xml 145 | nCrunchTemp_* 146 | 147 | # MightyMoose 148 | *.mm.* 149 | AutoTest.Net/ 150 | 151 | # Web workbench (sass) 152 | .sass-cache/ 153 | 154 | # Installshield output folder 155 | [Ee]xpress/ 156 | 157 | # DocProject is a documentation generator add-in 158 | DocProject/buildhelp/ 159 | DocProject/Help/*.HxT 160 | DocProject/Help/*.HxC 161 | DocProject/Help/*.hhc 162 | DocProject/Help/*.hhk 163 | DocProject/Help/*.hhp 164 | DocProject/Help/Html2 165 | DocProject/Help/html 166 | 167 | # Click-Once directory 168 | publish/ 169 | 170 | # Publish Web Output 171 | *.[Pp]ublish.xml 172 | *.azurePubxml 173 | # Note: Comment the next line if you want to checkin your web deploy settings, 174 | # but database connection strings (with potential passwords) will be unencrypted 175 | *.pubxml 176 | *.publishproj 177 | 178 | # Microsoft Azure Web App publish settings. Comment the next line if you want to 179 | # checkin your Azure Web App publish settings, but sensitive information contained 180 | # in these scripts will be unencrypted 181 | PublishScripts/ 182 | 183 | # NuGet Packages 184 | *.nupkg 185 | # The packages folder can be ignored because of Package Restore 186 | **/[Pp]ackages/* 187 | # except build/, which is used as an MSBuild target. 188 | !**/[Pp]ackages/build/ 189 | # Uncomment if necessary however generally it will be regenerated when needed 190 | #!**/[Pp]ackages/repositories.config 191 | # NuGet v3's project.json files produces more ignorable files 192 | *.nuget.props 193 | *.nuget.targets 194 | 195 | # Microsoft Azure Build Output 196 | csx/ 197 | *.build.csdef 198 | 199 | # Microsoft Azure Emulator 200 | ecf/ 201 | rcf/ 202 | 203 | # Windows Store app package directories and files 204 | AppPackages/ 205 | BundleArtifacts/ 206 | Package.StoreAssociation.xml 207 | _pkginfo.txt 208 | *.appx 209 | 210 | # Visual Studio cache files 211 | # files ending in .cache can be ignored 212 | *.[Cc]ache 213 | # but keep track of directories ending in .cache 214 | !?*.[Cc]ache/ 215 | 216 | # Others 217 | ClientBin/ 218 | ~$* 219 | *~ 220 | *.dbmdl 221 | *.dbproj.schemaview 222 | *.jfm 223 | *.pfx 224 | *.publishsettings 225 | orleans.codegen.cs 226 | 227 | # Including strong name files can present a security risk 228 | # (https://github.com/github/gitignore/pull/2483#issue-259490424) 229 | #*.snk 230 | 231 | # Since there are multiple workflows, uncomment next line to ignore bower_components 232 | # (https://github.com/github/gitignore/pull/1529#issuecomment-104372622) 233 | #bower_components/ 234 | 235 | # RIA/Silverlight projects 236 | Generated_Code/ 237 | 238 | # Backup & report files from converting an old project file 239 | # to a newer Visual Studio version. Backup files are not needed, 240 | # because we have git ;-) 241 | _UpgradeReport_Files/ 242 | Backup*/ 243 | UpgradeLog*.XML 244 | UpgradeLog*.htm 245 | ServiceFabricBackup/ 246 | *.rptproj.bak 247 | 248 | # SQL Server files 249 | *.mdf 250 | *.ldf 251 | *.ndf 252 | 253 | # Business Intelligence projects 254 | *.rdl.data 255 | *.bim.layout 256 | *.bim_*.settings 257 | *.rptproj.rsuser 258 | *- Backup*.rdl 259 | 260 | # Microsoft Fakes 261 | FakesAssemblies/ 262 | 263 | # GhostDoc plugin setting file 264 | *.GhostDoc.xml 265 | 266 | # Node.js Tools for Visual Studio 267 | .ntvs_analysis.dat 268 | node_modules/ 269 | 270 | # Visual Studio 6 build log 271 | *.plg 272 | 273 | # Visual Studio 6 workspace options file 274 | *.opt 275 | 276 | # Visual Studio 6 auto-generated workspace file (contains which files were open etc.) 277 | *.vbw 278 | 279 | # Visual Studio LightSwitch build output 280 | **/*.HTMLClient/GeneratedArtifacts 281 | **/*.DesktopClient/GeneratedArtifacts 282 | **/*.DesktopClient/ModelManifest.xml 283 | **/*.Server/GeneratedArtifacts 284 | **/*.Server/ModelManifest.xml 285 | _Pvt_Extensions 286 | 287 | # Paket dependency manager 288 | .paket/paket.exe 289 | paket-files/ 290 | 291 | # FAKE - F# Make 292 | .fake/ 293 | 294 | # JetBrains Rider 295 | .idea/ 296 | *.sln.iml 297 | 298 | # CodeRush personal settings 299 | .cr/personal 300 | 301 | # Python Tools for Visual Studio (PTVS) 302 | __pycache__/ 303 | *.pyc 304 | 305 | # Cake - Uncomment if you are using it 306 | # tools/** 307 | # !tools/packages.config 308 | 309 | # Tabs Studio 310 | *.tss 311 | 312 | # Telerik's JustMock configuration file 313 | *.jmconfig 314 | 315 | # BizTalk build output 316 | *.btp.cs 317 | *.btm.cs 318 | *.odx.cs 319 | *.xsd.cs 320 | 321 | # OpenCover UI analysis results 322 | OpenCover/ 323 | 324 | # Azure Stream Analytics local run output 325 | ASALocalRun/ 326 | 327 | # MSBuild Binary and Structured Log 328 | *.binlog 329 | 330 | # NVidia Nsight GPU debugger configuration file 331 | *.nvuser 332 | 333 | # MFractors (Xamarin productivity tool) working folder 334 | .mfractor/ 335 | 336 | # Local History for Visual Studio 337 | .localhistory/ 338 | 339 | # BeatPulse healthcheck temp database 340 | healthchecksdb -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | Welcome to the WebSecure wiki by **Saineshwar Bageri**! 2 | 3 | Download Database :- https://payhip.com/b/9SoY 4 | 5 | # Custom authentication with ASP.NET Core With SHA512 algorithm 6 | Secure ASP.NET Core Application essential feature Using SHA512 algorithm. 7 | 8 | _**Everyone must store Salt in Different Database other than Main project Database For Security**_ 9 | 10 | Each time you create a new application you need essential feature such as 11 | * Registration 12 | * Login 13 | * ChangePassword 14 | * ResetPassword 15 | * Email Verification of registered User 16 | * Sending Email for Reset Password 17 | 18 | For Demo I have used gmail. 19 | (Application is Configured with Gmail For Sending Email enter details in appsettings.json) 20 | 21 | Making App Less Secure do at own Risk i am not responsible for it. 22 | 23 | * Open your Google Admin console (admin.google.com). 24 | * Click Security > Basic settings . 25 | * Under Less secure apps, select Go to settings for less secure apps . 26 | * In the subwindow, select the Enforce access to less secure apps for all users radio button. ... 27 | * Click the Save button. 28 | 29 | Enable less secure app on gmail for sending email from localhost :- https://hotter.io/docs/email-accounts/secure-app-gmail/ 30 | 31 | *** 32 | ## Getting Started 33 | 34 | ### Registation Process 35 | 36 | When User register clicks on submit button on Client-Side SHA512 Hash of the password is created and sent to the server on, on serverside salt is generated and combination **[ SHA512 Hash + Salt ]** is stored in **User** Table and salt is stored in **UserTokens** Table. 37 | 38 | A Verification Email is sent to entered email id. After the Verification, User will able to log into the application. 39 | While sending Email we generate **key** and **Unique Token**. the **key** is created using a combination of **(Ticks + UserId)** 40 | **_"More things can be added to make it more secure"_** which is Encrypted using AES algorithm. And **Unique Token** is generated using **RNGCryptoServiceProvider**. 41 | 42 | ` var linktoverify = _appSettings.VerifyRegistrationUrl + "?key=" + HttpUtility.UrlEncode(encrypt) + "&hashtoken=" + HttpUtility.UrlEncode(token);` 43 | 44 | 45 | 46 | *** 47 | ### Login Process 48 | 49 | When User Log into Application using Username and password, according to Username we get UserDetails of the User from **User** Table and on based of UserId we get User Salt which is stored in **UserTokens** Table. Next, we are going to combine Posted User **Password SHA512 Hash** with Stored **User Salt** and compare with Stored Hash in **User** Table. 50 | 51 | 52 | *** 53 | 54 | 55 | ### Reset Password Process 56 | Next in Forgot Password Process, we are going ask the user to enter Username and check Username exists in database then we are going to send an email with links to reset the password. 57 | 58 | ` var linktoverify = _appSettings.VerifyResetPasswordUrl + "?key=" + HttpUtility.UrlEncode(encrypt) + "&hashtoken=" + HttpUtility.UrlEncode(token);` 59 | 60 | After clicking on Reset Password Link it will redirect to Reset Password Page. where you will be entering New Password to change your Password. 61 | In the Reset Password process, New password hash and New Salt is created for more security. 62 | All Password History is Maintained in **PasswordHistory** Table. 63 | *** 64 | 65 | ### Change Password Process 66 | Next in Change Password Process, this process is done after login into the application there we are going to ask the user to enter Current password and New Password. 67 | All Password History is Maintained in **PasswordHistory** Table. 68 | 69 | ### About Platform Used 70 | Targeted Framework .Net Core 3.1 71 | 72 | ### Microsoft Visual Studio Community 2019
73 | Link to download Microsoft Visual Studio Community 2019: - https://visualstudio.microsoft.com/vs/ 74 | 75 | ### Microsoft SQL Server 2019
76 | Link to download SQL Server Express: - https://www.microsoft.com/en-us/sql-server/sql-server-downloads 77 | 78 | ### External packages which are used in .Net Core Project 79 | * Dapper ORM 80 | * Microsoft.EntityFrameworkCore 81 | * System.Data.SqlClient 82 | * Microsoft.EntityFrameworkCore.SqlServer 83 | 84 | ### External packages javascript used 85 | * js-sha256 86 | * js-sha512 87 | 88 | ## Getting Started 89 | 1. Restore Database Script 90 | 91 | ![](https://github.com/saineshwar/WebSecure/blob/master/WebSecure/Images/4.png) 92 | 93 | 2. Make changes in appsettings.json Settings 94 | 95 | ![](https://github.com/saineshwar/WebSecure/blob/master/WebSecure/Images/13.png) 96 | 97 | 3. Run Application 98 | 99 | ### Login Page 100 | 101 | ![](https://github.com/saineshwar/WebSecure/blob/master/WebSecure/Images/9.png) 102 | 103 | ### Registration Page 104 | 105 | ![](https://github.com/saineshwar/WebSecure/blob/master/WebSecure/Images/8.png) 106 | 107 | ### Email Verification of registered User 108 | 109 | ![](https://github.com/saineshwar/WebSecure/blob/master/WebSecure/Images/6.png) 110 | 111 | ### Forgot Password 112 | 113 | ![](https://github.com/saineshwar/WebSecure/blob/master/WebSecure/Images/10.png) 114 | 115 | ### Sending Email for Reset Password 116 | 117 | ![](https://github.com/saineshwar/WebSecure/blob/master/WebSecure/Images/11.png) 118 | 119 | ### Sending Email for Reset Password 120 | 121 | ![](https://github.com/saineshwar/WebSecure/blob/master/WebSecure/Images/7.png) 122 | 123 | ### Reset Password 124 | 125 | ![](https://github.com/saineshwar/WebSecure/blob/master/WebSecure/Images/12.png) 126 | 127 | ### Database 128 | 129 | ![](https://github.com/saineshwar/WebSecure/blob/master/WebSecure/Images/4.png) 130 | 131 | ### Tables 132 | 133 | ![](https://github.com/saineshwar/WebSecure/blob/master/WebSecure/Images/5.png) 134 | -------------------------------------------------------------------------------- /WebSecure.Models/RegisterVerification.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.ComponentModel.DataAnnotations; 4 | using System.ComponentModel.DataAnnotations.Schema; 5 | using System.Text; 6 | 7 | namespace WebSecure.Models 8 | { 9 | [Table("RegisterVerification")] 10 | public class RegisterVerification 11 | { 12 | [Key] 13 | public long RegisterVerificationId { get; set; } 14 | public string GeneratedToken { get; set; } 15 | public DateTime? GeneratedDate { get; set; } 16 | public bool VerificationStatus { get; set; } 17 | public bool Status { get; set; } 18 | public long UserId { get; set; } 19 | public DateTime? VerificationDate { get; set; } 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /WebSecure.Models/ResetPasswordVerification.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.ComponentModel.DataAnnotations; 4 | using System.ComponentModel.DataAnnotations.Schema; 5 | using System.Text; 6 | 7 | namespace WebSecure.Models 8 | { 9 | [Table("ResetPasswordVerification")] 10 | public class ResetPasswordVerification 11 | { 12 | [Key] 13 | public long ResetTokenId { get; set; } 14 | public string GeneratedToken { get; set; } 15 | public DateTime? GeneratedDate { get; set; } 16 | public bool VerificationStatus { get; set; } 17 | public bool Status { get; set; } 18 | public long UserId { get; set; } 19 | public DateTime? VerificationDate { get; set; } 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /WebSecure.Models/User.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.ComponentModel.DataAnnotations; 3 | using System.ComponentModel.DataAnnotations.Schema; 4 | 5 | namespace WebSecure.Models 6 | { 7 | [Table("User")] 8 | public class User 9 | { 10 | [Key] 11 | public long UserId { get; set; } 12 | public string FullName { get; set; } 13 | public string Username { get; set; } 14 | public string PasswordHash { get; set; } 15 | public bool Status { get; set; } 16 | public DateTime? CreatedDate { get; set; } 17 | public DateTime? UpdateDate { get; set; } 18 | public string Email { get; set; } 19 | public string Phoneno { get; set; } 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /WebSecure.Models/UserTokens.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.ComponentModel.DataAnnotations; 4 | using System.ComponentModel.DataAnnotations.Schema; 5 | using System.Text; 6 | 7 | namespace WebSecure.Models 8 | { 9 | [Table("UserTokens")] 10 | public class UserTokens 11 | { 12 | [Key] 13 | public long HashId { get; set; } 14 | public string PasswordSalt { get; set; } 15 | public long UserId { get; set; } 16 | public DateTime? CreatedDate { get; set; } 17 | public DateTime? UpdateDate { get; set; } 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /WebSecure.Models/WebSecure.Models.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | netcoreapp3.1 5 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /WebSecure.Repository/DatabaseContext.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Text; 4 | using Microsoft.EntityFrameworkCore; 5 | using WebSecure.Models; 6 | 7 | namespace WebSecure.Repository 8 | { 9 | public class DatabaseContext : DbContext 10 | { 11 | public DatabaseContext(DbContextOptions options) : base(options) 12 | { 13 | 14 | } 15 | 16 | public DbSet User { get; set; } 17 | public DbSet UserTokens { get; set; } 18 | public DbSet RegisterVerification { get; set; } 19 | public DbSet ResetPasswordVerification { get; set; } 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /WebSecure.Repository/IUserRepository.cs: -------------------------------------------------------------------------------- 1 | using WebSecure.Models; 2 | using WebSecure.ViewModel; 3 | 4 | namespace WebSecure.Repository 5 | { 6 | public interface IUserRepository 7 | { 8 | long RegisterUser(User user, string salt); 9 | User GetUserbyUserName(string username); 10 | User GetUserbyUserId(long userid); 11 | bool CheckUserExists(string username); 12 | UserTokens GetUserSaltbyUserid(long userId); 13 | bool CheckEmailExists(string emailid); 14 | bool CheckPhonenoExists(string phoneno); 15 | int UpdatePasswordandHistory(long userId, string passwordHash, string passwordSalt, string processType); 16 | } 17 | } -------------------------------------------------------------------------------- /WebSecure.Repository/IVerificationRepository.cs: -------------------------------------------------------------------------------- 1 | using WebSecure.Models; 2 | 3 | namespace WebSecure.Repository 4 | { 5 | public interface IVerificationRepository 6 | { 7 | void SendRegistrationVerificationToken(long userid, string verficationToken); 8 | RegisterVerification GetRegistrationGeneratedToken(string userid); 9 | ResetPasswordVerification GetResetGeneratedToken(string userid); 10 | bool UpdateRegisterVerification(long userid); 11 | bool CheckIsAlreadyVerifiedRegistration(long userid); 12 | void SendResetVerificationToken(long userid, string verficationToken); 13 | bool UpdateResetVerification(long userid); 14 | } 15 | } -------------------------------------------------------------------------------- /WebSecure.Repository/UserRepository.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Data; 4 | using System.Data.SqlClient; 5 | using System.Linq; 6 | using System.Text; 7 | using Dapper; 8 | using Microsoft.Extensions.Options; 9 | using WebSecure.Models; 10 | using WebSecure.ViewModel; 11 | 12 | namespace WebSecure.Repository 13 | { 14 | public class UserRepository : IUserRepository 15 | { 16 | private readonly DatabaseContext _databaseContext; 17 | private readonly ConnectionStrings _connectionStrings; 18 | public UserRepository(DatabaseContext databaseContext, IOptions connectionStrings) 19 | { 20 | _databaseContext = databaseContext; 21 | _connectionStrings = connectionStrings.Value; 22 | } 23 | 24 | public long RegisterUser(User user, string salt) 25 | { 26 | try 27 | { 28 | using (var dbContextTransaction = _databaseContext.Database.BeginTransaction()) 29 | { 30 | try 31 | { 32 | long result = 0; 33 | _databaseContext.User.Add(user); 34 | _databaseContext.SaveChanges(); 35 | result = user.UserId; 36 | 37 | UserTokens userTokens = new UserTokens() 38 | { 39 | UserId = result, 40 | HashId = 0, 41 | PasswordSalt = salt, 42 | CreatedDate = DateTime.Now 43 | }; 44 | 45 | _databaseContext.UserTokens.Add(userTokens); 46 | _databaseContext.SaveChanges(); 47 | 48 | dbContextTransaction.Commit(); 49 | return result; 50 | } 51 | catch (Exception) 52 | { 53 | dbContextTransaction.Rollback(); 54 | return 0; 55 | } 56 | } 57 | } 58 | catch (Exception) 59 | { 60 | 61 | throw; 62 | } 63 | } 64 | public User GetUserbyUserName(string username) 65 | { 66 | var userdata = (from tempuser in _databaseContext.User 67 | where tempuser.Username == username 68 | select tempuser).FirstOrDefault(); 69 | 70 | return userdata; 71 | } 72 | public User GetUserbyUserId(long userid) 73 | { 74 | var userdata = (from tempuser in _databaseContext.User 75 | where tempuser.UserId == userid 76 | select tempuser).FirstOrDefault(); 77 | 78 | return userdata; 79 | } 80 | public bool CheckUserExists(string username) 81 | { 82 | var userdata = (from tempuser in _databaseContext.User 83 | where tempuser.Username == username 84 | select tempuser).Any(); 85 | 86 | return userdata; 87 | } 88 | public bool CheckEmailExists(string emailid) 89 | { 90 | var userdata = (from tempuser in _databaseContext.User 91 | where tempuser.Email == emailid 92 | select tempuser).Any(); 93 | 94 | return userdata; 95 | } 96 | public bool CheckPhonenoExists(string phoneno) 97 | { 98 | var userdata = (from tempuser in _databaseContext.User 99 | where tempuser.Phoneno == phoneno 100 | select tempuser).Any(); 101 | 102 | return userdata; 103 | } 104 | public UserTokens GetUserSaltbyUserid(long userId) 105 | { 106 | var usertoken = (from tempuser in _databaseContext.UserTokens 107 | where tempuser.UserId == userId 108 | select tempuser).FirstOrDefault(); 109 | 110 | return usertoken; 111 | } 112 | 113 | // C and R processType || C:- Change Password R :- Reset Password 114 | public int UpdatePasswordandHistory(long userId, string passwordHash , string passwordSalt, string processType) 115 | { 116 | try 117 | { 118 | using (var con = new SqlConnection(_connectionStrings.DatabaseConnection)) 119 | { 120 | con.Open(); 121 | SqlTransaction transaction = con.BeginTransaction(); 122 | var param = new DynamicParameters(); 123 | param.Add("@UserId", userId); 124 | param.Add("@PasswordHash", passwordHash); 125 | param.Add("@PasswordSalt", passwordSalt); 126 | param.Add("@ProcessType", processType); 127 | var result = con.Execute("Usp_UpdatePassword", param, transaction, 0, CommandType.StoredProcedure); 128 | 129 | if (result > 0) 130 | { 131 | transaction.Commit(); 132 | return result; 133 | } 134 | else 135 | { 136 | transaction.Rollback(); 137 | return 0; 138 | } 139 | } 140 | } 141 | catch (Exception) 142 | { 143 | throw; 144 | } 145 | } 146 | 147 | } 148 | } 149 | -------------------------------------------------------------------------------- /WebSecure.Repository/VerificationRepository.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | using WebSecure.Models; 6 | 7 | namespace WebSecure.Repository 8 | { 9 | public class VerificationRepository : IVerificationRepository 10 | { 11 | private readonly DatabaseContext _databaseContext; 12 | public VerificationRepository(DatabaseContext databaseContext) 13 | { 14 | _databaseContext = databaseContext; 15 | } 16 | 17 | /// 18 | /// Here we can Send VerificationToken to User In Email or OTP On Mobile 19 | /// 20 | public void SendRegistrationVerificationToken(long userid, string verficationToken) 21 | { 22 | RegisterVerification registerVerification = new RegisterVerification() 23 | { 24 | RegisterVerificationId = 0, 25 | GeneratedDate = DateTime.Now, 26 | GeneratedToken = verficationToken, 27 | UserId = userid, 28 | Status = true, 29 | VerificationStatus = false 30 | }; 31 | 32 | _databaseContext.RegisterVerification.Add(registerVerification); 33 | _databaseContext.SaveChanges(); 34 | } 35 | 36 | public RegisterVerification GetRegistrationGeneratedToken(string userid) 37 | { 38 | var tempuserid = Convert.ToInt64(userid); 39 | 40 | var registerVerification = (from rv in _databaseContext.RegisterVerification 41 | orderby rv.RegisterVerificationId descending 42 | where rv.UserId == tempuserid 43 | select rv).FirstOrDefault(); 44 | 45 | return registerVerification; 46 | } 47 | 48 | 49 | public ResetPasswordVerification GetResetGeneratedToken(string userid) 50 | { 51 | var tempuserid = Convert.ToInt64(userid); 52 | 53 | var resetPasswordVerification = (from rv in _databaseContext.ResetPasswordVerification 54 | orderby rv.ResetTokenId descending 55 | where rv.UserId == tempuserid 56 | select rv).FirstOrDefault(); 57 | 58 | return resetPasswordVerification; 59 | } 60 | 61 | public bool UpdateRegisterVerification(long userid) 62 | { 63 | var registerVerification = (from rv in _databaseContext.RegisterVerification 64 | where rv.UserId == userid 65 | select rv).FirstOrDefault(); 66 | if (registerVerification != null) 67 | { 68 | registerVerification.VerificationStatus = true; 69 | registerVerification.VerificationDate = DateTime.Now; 70 | _databaseContext.RegisterVerification.Update(registerVerification); 71 | } 72 | 73 | return _databaseContext.SaveChanges() > 0; 74 | } 75 | 76 | public bool CheckIsAlreadyVerifiedRegistration(long userid) 77 | { 78 | var registerVerification = (from rv in _databaseContext.RegisterVerification 79 | where rv.UserId == userid && rv.VerificationStatus == true 80 | select rv).Any(); 81 | 82 | return registerVerification; 83 | } 84 | 85 | public void SendResetVerificationToken(long userid, string verficationToken) 86 | { 87 | ResetPasswordVerification registerVerification = new ResetPasswordVerification() 88 | { 89 | ResetTokenId = 0, 90 | GeneratedDate = DateTime.Now, 91 | GeneratedToken = verficationToken, 92 | UserId = userid, 93 | Status = true, 94 | VerificationStatus = false 95 | }; 96 | 97 | _databaseContext.ResetPasswordVerification.Add(registerVerification); 98 | _databaseContext.SaveChanges(); 99 | } 100 | 101 | public bool UpdateResetVerification(long userid) 102 | { 103 | var resetVerification = (from rv in _databaseContext.ResetPasswordVerification 104 | where rv.UserId == userid 105 | select rv).FirstOrDefault(); 106 | if (resetVerification != null) 107 | { 108 | resetVerification.VerificationStatus = true; 109 | resetVerification.VerificationDate = DateTime.Now; 110 | _databaseContext.ResetPasswordVerification.Update(resetVerification); 111 | } 112 | 113 | return _databaseContext.SaveChanges() > 0; 114 | } 115 | } 116 | } 117 | -------------------------------------------------------------------------------- /WebSecure.Repository/WebSecure.Repository.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | netcoreapp3.1 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | -------------------------------------------------------------------------------- /WebSecure.ViewModel/AppSettings.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Text; 4 | 5 | namespace WebSecure.ViewModel 6 | { 7 | public class AppSettings 8 | { 9 | public string EmailFrom { get; set; } 10 | public string Port { get; set; } 11 | public string Host { get; set; } 12 | public string Password { get; set; } 13 | public string VerifyRegistrationUrl { get; set; } 14 | public string WebsiteUrl { get; set; } 15 | public string VerifyResetPasswordUrl { get; set; } 16 | 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /WebSecure.ViewModel/ChangePasswordViewModel.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.ComponentModel.DataAnnotations; 4 | using System.Text; 5 | 6 | namespace WebSecure.ViewModel 7 | { 8 | public class ChangePasswordViewModel 9 | { 10 | [StringLength(150, ErrorMessage = "The {0} must be at least {2} characters long.", MinimumLength = 6)] 11 | [Required(ErrorMessage = "Current Password Required")] 12 | public string CurrentPassword { get; set; } 13 | 14 | [StringLength(150, ErrorMessage = "The {0} must be at least {2} characters long.", MinimumLength = 6)] 15 | [Required(ErrorMessage = "Password Required")] 16 | public string Password { get; set; } 17 | 18 | [Required(ErrorMessage = "Confirm Password Required")] 19 | [Compare("Password", ErrorMessage = "Enter Valid Password")] 20 | public string ConfirmPassword { get; set; } 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /WebSecure.ViewModel/ConnectionStrings.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Text; 4 | 5 | namespace WebSecure.ViewModel 6 | { 7 | public class ConnectionStrings 8 | { 9 | public string DatabaseConnection { get; set; } 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /WebSecure.ViewModel/ForgotPasswordViewModel.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.ComponentModel.DataAnnotations; 4 | using System.Text; 5 | 6 | namespace WebSecure.ViewModel 7 | { 8 | public class ForgotPasswordViewModel 9 | { 10 | [StringLength(30, ErrorMessage = "Not valid Username")] 11 | [Required(ErrorMessage = "Enter UserName")] 12 | public string UserName { get; set; } 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /WebSecure.ViewModel/LoginViewModel.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.ComponentModel.DataAnnotations; 3 | 4 | namespace WebSecure.ViewModel 5 | { 6 | public class LoginViewModel 7 | { 8 | [StringLength(30, ErrorMessage = "Not valid Username")] 9 | [Required(ErrorMessage = "Enter UserName")] 10 | public string UserName { get; set; } 11 | 12 | [Required(ErrorMessage = "Enter Password")] 13 | public string Password { get; set; } 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /WebSecure.ViewModel/RegisterViewModel.cs: -------------------------------------------------------------------------------- 1 | using System.ComponentModel.DataAnnotations; 2 | 3 | namespace WebSecure.ViewModel 4 | { 5 | public class RegisterViewModel 6 | { 7 | [StringLength(30, ErrorMessage = "The {0} must be at least {2} characters long.", MinimumLength = 4)] 8 | [Required(ErrorMessage = "Enter FullName")] 9 | public string FullName { get; set; } 10 | 11 | [StringLength(30, ErrorMessage = "The {0} must be at least {2} characters long.", MinimumLength = 4)] 12 | [Required(ErrorMessage = "Enter UserName")] 13 | public string UserName { get; set; } 14 | 15 | [StringLength(150, ErrorMessage = "The {0} must be at least {2} characters long.", MinimumLength = 6)] 16 | [Required(ErrorMessage = "Password Required")] 17 | public string Password { get; set; } 18 | 19 | [Required(ErrorMessage = "Confirm Password Required")] 20 | [Compare("Password", ErrorMessage = "Enter Valid Password")] 21 | public string ConfirmPassword { get; set; } 22 | 23 | [Required(ErrorMessage = "EmailId Required")] 24 | [RegularExpression(@"^([a-zA-Z0-9_\-\.]+)@((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.)|(([a-zA-Z0-9\-]+\.)+))([a-zA-Z]{2,4}|[0-9]{1,3})(\]?)$", ErrorMessage = "Please enter a valid e-mail address")] 25 | public string Email { get; set; } 26 | 27 | [Required(ErrorMessage = "Phoneno Required")] 28 | [RegularExpression(@"^(\d{10})$", ErrorMessage = "Wrong Phoneno")] 29 | [MaxLength(20)] 30 | public string Phoneno { get; set; } 31 | } 32 | } -------------------------------------------------------------------------------- /WebSecure.ViewModel/ResetPasswordViewModel.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.ComponentModel.DataAnnotations; 4 | using System.Text; 5 | 6 | namespace WebSecure.ViewModel 7 | { 8 | public class ResetPasswordViewModel 9 | { 10 | [StringLength(150, ErrorMessage = "The {0} must be at least {2} characters long.", MinimumLength = 6)] 11 | [Required(ErrorMessage = "Password Required")] 12 | public string Password { get; set; } 13 | 14 | [Required(ErrorMessage = "Confirm Password Required")] 15 | [Compare("Password", ErrorMessage = "Enter Valid Password")] 16 | public string ConfirmPassword { get; set; } 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /WebSecure.ViewModel/WebSecure.ViewModel.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | netcoreapp3.1 5 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /WebSecure.sln: -------------------------------------------------------------------------------- 1 |  2 | Microsoft Visual Studio Solution File, Format Version 12.00 3 | # Visual Studio Version 16 4 | VisualStudioVersion = 16.0.29613.14 5 | MinimumVisualStudioVersion = 10.0.40219.1 6 | Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "WebSecure", "WebSecure\WebSecure.csproj", "{BDC6AEC5-39B5-4F8F-8A75-6DB511C85323}" 7 | EndProject 8 | Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "WebSecure.Models", "WebSecure.Models\WebSecure.Models.csproj", "{C19D8EE1-9F1B-44C6-AB6F-B5D0C8D08148}" 9 | EndProject 10 | Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "WebSecure.Repository", "WebSecure.Repository\WebSecure.Repository.csproj", "{5BA97793-7B8D-482B-BA9F-9C342E946AD9}" 11 | EndProject 12 | Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "WebSecure.ViewModel", "WebSecure.ViewModel\WebSecure.ViewModel.csproj", "{F17C0FCE-30FE-49B6-AF91-597499C81290}" 13 | EndProject 14 | Global 15 | GlobalSection(SolutionConfigurationPlatforms) = preSolution 16 | Debug|Any CPU = Debug|Any CPU 17 | Release|Any CPU = Release|Any CPU 18 | EndGlobalSection 19 | GlobalSection(ProjectConfigurationPlatforms) = postSolution 20 | {BDC6AEC5-39B5-4F8F-8A75-6DB511C85323}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 21 | {BDC6AEC5-39B5-4F8F-8A75-6DB511C85323}.Debug|Any CPU.Build.0 = Debug|Any CPU 22 | {BDC6AEC5-39B5-4F8F-8A75-6DB511C85323}.Release|Any CPU.ActiveCfg = Release|Any CPU 23 | {BDC6AEC5-39B5-4F8F-8A75-6DB511C85323}.Release|Any CPU.Build.0 = Release|Any CPU 24 | {C19D8EE1-9F1B-44C6-AB6F-B5D0C8D08148}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 25 | {C19D8EE1-9F1B-44C6-AB6F-B5D0C8D08148}.Debug|Any CPU.Build.0 = Debug|Any CPU 26 | {C19D8EE1-9F1B-44C6-AB6F-B5D0C8D08148}.Release|Any CPU.ActiveCfg = Release|Any CPU 27 | {C19D8EE1-9F1B-44C6-AB6F-B5D0C8D08148}.Release|Any CPU.Build.0 = Release|Any CPU 28 | {5BA97793-7B8D-482B-BA9F-9C342E946AD9}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 29 | {5BA97793-7B8D-482B-BA9F-9C342E946AD9}.Debug|Any CPU.Build.0 = Debug|Any CPU 30 | {5BA97793-7B8D-482B-BA9F-9C342E946AD9}.Release|Any CPU.ActiveCfg = Release|Any CPU 31 | {5BA97793-7B8D-482B-BA9F-9C342E946AD9}.Release|Any CPU.Build.0 = Release|Any CPU 32 | {F17C0FCE-30FE-49B6-AF91-597499C81290}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 33 | {F17C0FCE-30FE-49B6-AF91-597499C81290}.Debug|Any CPU.Build.0 = Debug|Any CPU 34 | {F17C0FCE-30FE-49B6-AF91-597499C81290}.Release|Any CPU.ActiveCfg = Release|Any CPU 35 | {F17C0FCE-30FE-49B6-AF91-597499C81290}.Release|Any CPU.Build.0 = Release|Any CPU 36 | EndGlobalSection 37 | GlobalSection(SolutionProperties) = preSolution 38 | HideSolutionNode = FALSE 39 | EndGlobalSection 40 | GlobalSection(ExtensibilityGlobals) = postSolution 41 | SolutionGuid = {75A6CD3C-8490-40C9-BDE1-B18D14EFC13E} 42 | EndGlobalSection 43 | EndGlobal 44 | -------------------------------------------------------------------------------- /WebSecure/Controllers/ChangePasswordController.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text.RegularExpressions; 5 | using System.Threading.Tasks; 6 | using Microsoft.AspNetCore.Http; 7 | using Microsoft.AspNetCore.Mvc; 8 | using WebSecure.Filters; 9 | using WebSecure.Helpers; 10 | using WebSecure.Repository; 11 | using WebSecure.ViewModel; 12 | 13 | namespace WebSecure.Controllers 14 | { 15 | [AuthorizeUser] 16 | public class ChangePasswordController : Controller 17 | { 18 | private readonly IUserRepository _userRepository; 19 | private readonly IVerificationRepository _verificationRepository; 20 | public ChangePasswordController(IUserRepository userRepository, IVerificationRepository verificationRepository) 21 | { 22 | _userRepository = userRepository; 23 | _verificationRepository = verificationRepository; 24 | } 25 | 26 | public IActionResult Process() 27 | { 28 | return View(); 29 | } 30 | 31 | 32 | [HttpPost] 33 | [ValidateAntiForgeryToken] 34 | public IActionResult Process(ChangePasswordViewModel changePasswordViewModel) 35 | { 36 | if (ModelState.IsValid) 37 | { 38 | var userid = Convert.ToString(HttpContext.Session.GetString("UserId")); 39 | var getuserdetails = _userRepository.GetUserbyUserId(Convert.ToInt64(userid)); 40 | var usersalt = _userRepository.GetUserSaltbyUserid(getuserdetails.UserId); 41 | var generatehash = GenerateHashSha512.Sha512(changePasswordViewModel.CurrentPassword, usersalt.PasswordSalt); 42 | 43 | if (changePasswordViewModel.CurrentPassword == changePasswordViewModel.Password) 44 | { 45 | ModelState.AddModelError("", @"New Password Cannot be same as Old Password"); 46 | return View(changePasswordViewModel); 47 | } 48 | 49 | if (!string.Equals(getuserdetails.PasswordHash, generatehash, StringComparison.Ordinal)) 50 | { 51 | ModelState.AddModelError("", "Current Password Entered is InValid"); 52 | return View(changePasswordViewModel); 53 | } 54 | 55 | if (!string.Equals(changePasswordViewModel.Password, changePasswordViewModel.ConfirmPassword, StringComparison.Ordinal)) 56 | { 57 | TempData["Reset_Error_Message"] = "Password Does not Match"; 58 | return View(changePasswordViewModel); 59 | } 60 | else 61 | { 62 | var salt = GenerateRandomNumbers.RandomNumbers(20); 63 | var saltedpassword = GenerateHashSha512.Sha512(changePasswordViewModel.Password, salt); 64 | var result = _userRepository.UpdatePasswordandHistory(getuserdetails.UserId, saltedpassword, salt,"C"); 65 | 66 | if (result > 0) 67 | { 68 | // 69 | TempData["ChangePassword_Success_Message"] = "Password Changed Successfully"; 70 | var updateresult = _verificationRepository.UpdateRegisterVerification(getuserdetails.UserId); 71 | return RedirectToAction("Process", "ChangePassword"); 72 | } 73 | else 74 | { 75 | TempData["Reset_Error_Message"] = "Something Went Wrong Please try again!"; 76 | return View(changePasswordViewModel); 77 | } 78 | } 79 | } 80 | 81 | return View(changePasswordViewModel); 82 | } 83 | 84 | private void CheckIsPasswordAlreadyExists(ResetPasswordViewModel resetPasswordViewModel) 85 | { 86 | var salt = GenerateRandomNumbers.RandomNumbers(20); 87 | var saltedpassword = GenerateHashSha512.Sha512(resetPasswordViewModel.Password, salt); 88 | } 89 | 90 | } 91 | } -------------------------------------------------------------------------------- /WebSecure/Controllers/DashboardController.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Threading.Tasks; 5 | using Microsoft.AspNetCore.Mvc; 6 | using WebSecure.Filters; 7 | 8 | namespace WebSecure.Controllers 9 | { 10 | [AuthorizeUser] 11 | public class DashboardController : Controller 12 | { 13 | public IActionResult Dashboard() 14 | { 15 | return View(); 16 | } 17 | 18 | public IActionResult Logout() 19 | { 20 | HttpContext.Session.Clear(); 21 | return RedirectToAction("Login", "Portal"); 22 | } 23 | } 24 | } -------------------------------------------------------------------------------- /WebSecure/Controllers/ErrorController.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Threading.Tasks; 5 | using Microsoft.AspNetCore.Mvc; 6 | 7 | namespace WebSecure.Controllers 8 | { 9 | public class ErrorController : Controller 10 | { 11 | public IActionResult Error() 12 | { 13 | return View(); 14 | } 15 | } 16 | } -------------------------------------------------------------------------------- /WebSecure/Controllers/ForgotPasswordController.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Net.Mail; 5 | using System.Text; 6 | using System.Threading.Tasks; 7 | using System.Web; 8 | using Microsoft.AspNetCore.Http; 9 | using Microsoft.AspNetCore.Mvc; 10 | using Microsoft.Extensions.Options; 11 | using WebSecure.Helpers; 12 | using WebSecure.Models; 13 | using WebSecure.Repository; 14 | using WebSecure.ViewModel; 15 | 16 | namespace WebSecure.Controllers 17 | { 18 | public class ForgotPasswordController : Controller 19 | { 20 | private readonly IUserRepository _userRepository; 21 | private readonly AppSettings _appSettings; 22 | private readonly IVerificationRepository _verificationRepository; 23 | public ForgotPasswordController(IUserRepository userRepository, IOptions appSettings, IVerificationRepository verificationRepository) 24 | { 25 | _userRepository = userRepository; 26 | _verificationRepository = verificationRepository; 27 | _appSettings = appSettings.Value; 28 | } 29 | 30 | [HttpGet] 31 | public IActionResult Process() 32 | { 33 | return View(); 34 | } 35 | 36 | [HttpPost] 37 | public IActionResult Process(ForgotPasswordViewModel forgotPasswordViewModel) 38 | { 39 | if (!_userRepository.CheckUserExists(forgotPasswordViewModel.UserName)) 40 | { 41 | ModelState.AddModelError("", "Entered Username or Password is Invalid"); 42 | } 43 | else 44 | { 45 | var userdetails = _userRepository.GetUserbyUserName(forgotPasswordViewModel.UserName); 46 | Send(userdetails); 47 | //HttpContext.Session.SetString("TempUserName", Convert.ToString(forgotPasswordViewModel.UserName)); 48 | TempData["ForgotPasswordMessage"] = "An email has been sent to the address you have registered." + 49 | "Please follow the link in the email to complete your password reset request"; 50 | return RedirectToAction("Process", "ForgotPassword"); 51 | } 52 | 53 | return View(); 54 | } 55 | 56 | private void Send(User user) 57 | { 58 | var emailVerficationToken = GenerateHashSha256.ComputeSha256Hash((GenerateRandomNumbers.RandomNumbers(6))); 59 | _verificationRepository.SendResetVerificationToken(user.UserId, emailVerficationToken); 60 | 61 | MailMessage message = new MailMessage(); 62 | SmtpClient smtpClient = new SmtpClient(); 63 | try 64 | { 65 | MailAddress fromAddress = new MailAddress(_appSettings.EmailFrom); 66 | message.From = fromAddress; 67 | message.To.Add(user.Email); 68 | message.Subject = "Welcome to Web Secure"; 69 | message.IsBodyHtml = true; 70 | message.Body = SendVerificationEmail(user, emailVerficationToken); 71 | smtpClient.Host = _appSettings.Host; 72 | smtpClient.Port = Convert.ToInt32(_appSettings.Port); 73 | smtpClient.EnableSsl = true; 74 | smtpClient.UseDefaultCredentials = false; 75 | smtpClient.Credentials = new System.Net.NetworkCredential(_appSettings.EmailFrom, _appSettings.Password); 76 | smtpClient.Send(message); 77 | } 78 | catch (Exception) 79 | { 80 | throw; 81 | } 82 | } 83 | 84 | public string SendVerificationEmail(User user, string token) 85 | { 86 | AesAlgorithm aesAlgorithm = new AesAlgorithm(); 87 | var key = string.Join(":", new string[] { DateTime.Now.Ticks.ToString(), user.UserId.ToString() }); 88 | var encrypt = aesAlgorithm.EncryptToBase64String(key); 89 | 90 | var linktoverify = _appSettings.VerifyResetPasswordUrl + "?key=" + HttpUtility.UrlEncode(encrypt) + "&hashtoken=" + HttpUtility.UrlEncode(token); 91 | var stringtemplate = new StringBuilder(); 92 | stringtemplate.Append("Welcome"); 93 | stringtemplate.Append("
"); 94 | stringtemplate.Append("Dear " + user.FullName); 95 | stringtemplate.Append("
"); 96 | stringtemplate.Append("Please click the following link to reset your password."); 97 | stringtemplate.Append("
"); 98 | stringtemplate.Append("Reset password link : Link"); 99 | stringtemplate.Append("
"); 100 | stringtemplate.Append("If the link does not work, copy and paste the URL into a new browser window. The URL will expire in 24 hours for security reasons."); 101 | stringtemplate.Append("
"); 102 | stringtemplate.Append("Best regards,"); 103 | stringtemplate.Append("Saineshwar Begari"); 104 | stringtemplate.Append("
"); 105 | return stringtemplate.ToString(); 106 | } 107 | } 108 | } -------------------------------------------------------------------------------- /WebSecure/Controllers/HomeController.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Diagnostics; 4 | using System.Linq; 5 | using System.Threading.Tasks; 6 | using Microsoft.AspNetCore.Mvc; 7 | using Microsoft.Extensions.Logging; 8 | using WebSecure.Models; 9 | 10 | namespace WebSecure.Controllers 11 | { 12 | public class HomeController : Controller 13 | { 14 | private readonly ILogger _logger; 15 | 16 | public HomeController(ILogger logger) 17 | { 18 | _logger = logger; 19 | } 20 | 21 | public IActionResult Index() 22 | { 23 | return View(); 24 | } 25 | 26 | public IActionResult Privacy() 27 | { 28 | return View(); 29 | } 30 | 31 | [ResponseCache(Duration = 0, Location = ResponseCacheLocation.None, NoStore = true)] 32 | public IActionResult Error() 33 | { 34 | return View(new ErrorViewModel { RequestId = Activity.Current?.Id ?? HttpContext.TraceIdentifier }); 35 | } 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /WebSecure/Controllers/PortalController.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Threading.Tasks; 5 | using Microsoft.AspNetCore.Http; 6 | using Microsoft.AspNetCore.Mvc; 7 | using WebSecure.Helpers; 8 | using WebSecure.Repository; 9 | using WebSecure.ViewModel; 10 | 11 | namespace WebSecure.Controllers 12 | { 13 | public class PortalController : Controller 14 | { 15 | private readonly IUserRepository _userRepository; 16 | private readonly IVerificationRepository _verificationRepository; 17 | public PortalController(IUserRepository userRepository, IVerificationRepository verificationRepository) 18 | { 19 | _userRepository = userRepository; 20 | _verificationRepository = verificationRepository; 21 | } 22 | 23 | [HttpGet] 24 | public IActionResult Login() 25 | { 26 | return View(); 27 | } 28 | 29 | [HttpPost] 30 | public IActionResult Login(LoginViewModel loginViewModel) 31 | { 32 | if (ModelState.IsValid) 33 | { 34 | if (!_userRepository.CheckUserExists(loginViewModel.UserName)) 35 | { 36 | ModelState.AddModelError("", "Entered Username or Password is Invalid"); 37 | } 38 | else 39 | { 40 | var getuserdetails = _userRepository.GetUserbyUserName(loginViewModel.UserName); 41 | 42 | if (getuserdetails == null) 43 | { 44 | ModelState.AddModelError("", "Entered Username or Password is Invalid"); 45 | return View(); 46 | } 47 | 48 | var usersalt = _userRepository.GetUserSaltbyUserid(getuserdetails.UserId); 49 | if (usersalt == null) 50 | { 51 | ModelState.AddModelError("", "Entered Username or Password is Invalid"); 52 | return View(); 53 | } 54 | 55 | if (!_verificationRepository.CheckIsAlreadyVerifiedRegistration(getuserdetails.UserId)) 56 | { 57 | ModelState.AddModelError("", "Email Verification Pending"); 58 | return View(); 59 | } 60 | 61 | var generatehash = GenerateHashSha512.Sha512(loginViewModel.Password, usersalt.PasswordSalt); 62 | 63 | if (string.Equals(getuserdetails.PasswordHash, generatehash, StringComparison.Ordinal)) 64 | { 65 | HttpContext.Session.SetString("UserId", Convert.ToString(getuserdetails.UserId)); 66 | HttpContext.Session.SetString("UserName", Convert.ToString(getuserdetails.Username)); 67 | 68 | return RedirectToAction("Dashboard", "Dashboard"); 69 | } 70 | else 71 | { 72 | ModelState.AddModelError("", "Entered Username or Password is Invalid"); 73 | } 74 | 75 | return View(); 76 | } 77 | } 78 | 79 | return View(); 80 | } 81 | } 82 | } -------------------------------------------------------------------------------- /WebSecure/Controllers/RegistrationController.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Net.Mail; 5 | using System.Text; 6 | using System.Threading.Tasks; 7 | using System.Web; 8 | using Microsoft.AspNetCore.Authorization; 9 | using Microsoft.AspNetCore.Mvc; 10 | using Microsoft.Extensions.Options; 11 | using WebSecure.Helpers; 12 | using WebSecure.Models; 13 | using WebSecure.Repository; 14 | using WebSecure.ViewModel; 15 | 16 | namespace WebSecure.Controllers 17 | { 18 | [AllowAnonymous] 19 | public class RegistrationController : Controller 20 | { 21 | private readonly IUserRepository _userRepository; 22 | private readonly IVerificationRepository _verificationRepository; 23 | private readonly AppSettings _appSettings; 24 | public RegistrationController(IUserRepository userRepository, IVerificationRepository verificationRepository, IOptions appSettings) 25 | { 26 | _userRepository = userRepository; 27 | _verificationRepository = verificationRepository; 28 | _appSettings = appSettings.Value; 29 | } 30 | 31 | [HttpGet] 32 | public IActionResult Register() 33 | { 34 | return View(); 35 | } 36 | 37 | [HttpPost] 38 | [ValidateAntiForgeryToken] 39 | public IActionResult Register(RegisterViewModel registerViewModel) 40 | { 41 | if (ModelState.IsValid) 42 | { 43 | if (_userRepository.CheckUserExists(registerViewModel.UserName)) 44 | { 45 | ModelState.AddModelError("", "Entered Username Already Exists"); 46 | return View(registerViewModel); 47 | } 48 | 49 | if (_userRepository.CheckUserExists(registerViewModel.Email)) 50 | { 51 | ModelState.AddModelError("", "Entered EmailId Already Exists"); 52 | return View(registerViewModel); 53 | } 54 | 55 | if (_userRepository.CheckUserExists(registerViewModel.Phoneno)) 56 | { 57 | ModelState.AddModelError("", "Entered Phoneno Already Exists"); 58 | return View(registerViewModel); 59 | } 60 | 61 | if (!string.Equals(registerViewModel.Password, registerViewModel.ConfirmPassword, 62 | StringComparison.Ordinal)) 63 | { 64 | TempData["Registered_Error_Message"] = "Password Does not Match"; 65 | return View(registerViewModel); 66 | } 67 | 68 | var salt = GenerateRandomNumbers.RandomNumbers(20); 69 | var saltedpassword = GenerateHashSha512.Sha512(registerViewModel.Password, salt); 70 | 71 | User user = new User() 72 | { 73 | FullName = registerViewModel.FullName, 74 | CreatedDate = DateTime.Now, 75 | PasswordHash = saltedpassword, 76 | Status = true, 77 | UserId = 0, 78 | Username = registerViewModel.UserName, 79 | Email= registerViewModel.Email, 80 | Phoneno =registerViewModel.Phoneno 81 | }; 82 | 83 | var userId = _userRepository.RegisterUser(user, salt); 84 | if (userId > 0) 85 | { 86 | Send(userId, registerViewModel); 87 | TempData["Registered_Success_Message"] = "User Registered Successfully"; 88 | } 89 | else 90 | { 91 | TempData["Registered_Error_Message"] = "Error While Registrating User Successfully"; 92 | } 93 | } 94 | 95 | return RedirectToAction("Register", "Registration"); 96 | } 97 | 98 | 99 | private void Send(long userid, RegisterViewModel registerViewModel) 100 | { 101 | var emailVerficationToken = GenerateHashSha256.ComputeSha256Hash((GenerateRandomNumbers.RandomNumbers(6))); 102 | _verificationRepository.SendRegistrationVerificationToken(userid, emailVerficationToken); 103 | 104 | MailMessage message = new MailMessage(); 105 | SmtpClient smtpClient = new SmtpClient(); 106 | try 107 | { 108 | MailAddress fromAddress = new MailAddress(_appSettings.EmailFrom); 109 | message.From = fromAddress; 110 | message.To.Add(registerViewModel.Email); 111 | message.Subject = "Welcome to Web Secure"; 112 | message.IsBodyHtml = true; 113 | message.Body = SendVerificationEmail(registerViewModel, emailVerficationToken, userid); 114 | smtpClient.Host = _appSettings.Host; 115 | smtpClient.Port = Convert.ToInt32(_appSettings.Port); 116 | smtpClient.EnableSsl = true; 117 | smtpClient.UseDefaultCredentials = false; 118 | smtpClient.Credentials = new System.Net.NetworkCredential(_appSettings.EmailFrom, _appSettings.Password); 119 | smtpClient.Send(message); 120 | } 121 | catch (Exception) 122 | { 123 | throw; 124 | } 125 | } 126 | 127 | public string SendVerificationEmail(RegisterViewModel registerViewModel, string token , long userid) 128 | { 129 | AesAlgorithm aesAlgorithm = new AesAlgorithm(); 130 | var key = string.Join(":", new string[] { DateTime.Now.Ticks.ToString(), userid.ToString() }); 131 | var encrypt = aesAlgorithm.EncryptToBase64String(key); 132 | 133 | var linktoverify = _appSettings.VerifyRegistrationUrl + "?key=" + HttpUtility.UrlEncode(encrypt) + "&hashtoken=" + HttpUtility.UrlEncode(token); 134 | var stringtemplate = new StringBuilder(); 135 | stringtemplate.Append("Welcome"); 136 | stringtemplate.Append("
"); 137 | stringtemplate.Append("Dear " + registerViewModel.FullName); 138 | stringtemplate.Append("
"); 139 | stringtemplate.Append("Thanks for joining Web Secure."); 140 | stringtemplate.Append("
"); 141 | stringtemplate.Append("To activate your Web Secure account, please confirm your email address."); 142 | stringtemplate.Append("
"); 143 | stringtemplate.Append("Confirm Email"); 144 | stringtemplate.Append("
"); 145 | stringtemplate.Append("Yours sincerely,"); 146 | stringtemplate.Append("
"); 147 | stringtemplate.Append("Ticket's"); 148 | stringtemplate.Append("
"); 149 | return stringtemplate.ToString(); 150 | } 151 | } 152 | } -------------------------------------------------------------------------------- /WebSecure/Controllers/ResetPasswordController.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Threading.Tasks; 5 | using Microsoft.AspNetCore.Http; 6 | using Microsoft.AspNetCore.Mvc; 7 | using WebSecure.Filters; 8 | using WebSecure.Helpers; 9 | using WebSecure.Repository; 10 | using WebSecure.ViewModel; 11 | 12 | namespace WebSecure.Controllers 13 | { 14 | [AuthorizeResetPassword] 15 | public class ResetPasswordController : Controller 16 | { 17 | private readonly IUserRepository _userRepository; 18 | private readonly IVerificationRepository _verificationRepository; 19 | public ResetPasswordController(IUserRepository userRepository, IVerificationRepository verificationRepository) 20 | { 21 | _userRepository = userRepository; 22 | _verificationRepository = verificationRepository; 23 | } 24 | 25 | [HttpGet] 26 | public IActionResult Reset() 27 | { 28 | return View(new ResetPasswordViewModel()); 29 | } 30 | 31 | [HttpPost] 32 | [ValidateAntiForgeryToken] 33 | public IActionResult Reset(ResetPasswordViewModel resetPasswordViewModel) 34 | { 35 | if (ModelState.IsValid) 36 | { 37 | var userid = Convert.ToString(HttpContext.Session.GetString("VerificationUserId")); 38 | var getuserdetails = _userRepository.GetUserbyUserId(Convert.ToInt64(userid)); 39 | 40 | if (!string.Equals(resetPasswordViewModel.Password, resetPasswordViewModel.ConfirmPassword, StringComparison.Ordinal)) 41 | { 42 | TempData["Reset_Error_Message"] = "Password Does not Match"; 43 | return View(resetPasswordViewModel); 44 | } 45 | else 46 | { 47 | var salt = GenerateRandomNumbers.RandomNumbers(20); 48 | var saltedpassword = GenerateHashSha512.Sha512(resetPasswordViewModel.Password, salt); 49 | var result = _userRepository.UpdatePasswordandHistory(getuserdetails.UserId, saltedpassword, salt,"R"); 50 | 51 | if (result > 0) 52 | { 53 | var updateresult = _verificationRepository.UpdateResetVerification(getuserdetails.UserId); 54 | return RedirectToAction("Login", "Portal"); 55 | } 56 | else 57 | { 58 | TempData["Reset_Error_Message"] = "Something Went Wrong Please try again!"; 59 | return View(resetPasswordViewModel); 60 | } 61 | 62 | } 63 | } 64 | 65 | return View(resetPasswordViewModel); 66 | } 67 | 68 | private void CheckIsPasswordAlreadyExists(ResetPasswordViewModel resetPasswordViewModel) 69 | { 70 | var salt = GenerateRandomNumbers.RandomNumbers(20); 71 | var saltedpassword = GenerateHashSha512.Sha512(resetPasswordViewModel.Password, salt); 72 | } 73 | 74 | 75 | 76 | } 77 | } -------------------------------------------------------------------------------- /WebSecure/Controllers/VerifyRegistrationController.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | using System.Threading.Tasks; 6 | using Microsoft.AspNetCore.Http; 7 | using Microsoft.AspNetCore.Mvc; 8 | using WebSecure.Helpers; 9 | using WebSecure.Repository; 10 | 11 | namespace WebSecure.Controllers 12 | { 13 | public class VerifyRegistrationController : Controller 14 | { 15 | private readonly IVerificationRepository _verificationRepository; 16 | public VerifyRegistrationController(IVerificationRepository verificationRepository) 17 | { 18 | _verificationRepository = verificationRepository; 19 | } 20 | 21 | 22 | [HttpGet] 23 | public IActionResult Verify(string key, string hashtoken) 24 | { 25 | try 26 | { 27 | if (!string.IsNullOrEmpty(key) && !string.IsNullOrEmpty(hashtoken)) 28 | { 29 | var arrayVakue = SecurityManager.SplitToken(key); 30 | if (arrayVakue != null) 31 | { 32 | // arrayVakue[1] "UserId" 33 | var rvModel = _verificationRepository.GetRegistrationGeneratedToken(arrayVakue[1]); 34 | if (rvModel != null) 35 | { 36 | var result = SecurityManager.IsTokenValid(arrayVakue, hashtoken, rvModel.GeneratedToken); 37 | 38 | if (result == 1) 39 | { 40 | TempData["TokenErrorMessage"] = "Sorry Verification Link Expired Please request a new Verification link!"; 41 | return RedirectToAction("Login", "Portal"); 42 | } 43 | 44 | if (result == 2) 45 | { 46 | TempData["TokenErrorMessage"] = "Sorry Verification Link Expired Please request a new Verification link!"; 47 | return RedirectToAction("Login", "Portal"); 48 | } 49 | 50 | if (result == 0) 51 | { 52 | if (_verificationRepository.CheckIsAlreadyVerifiedRegistration(Convert.ToInt64(arrayVakue[1]))) 53 | { 54 | TempData["TokenErrorMessage"] = "Sorry Link Expired"; 55 | return RedirectToAction("Login", "Portal"); 56 | } 57 | 58 | HttpContext.Session.SetString("VerificationUserId", arrayVakue[1]); 59 | var updateresult = _verificationRepository.UpdateRegisterVerification(Convert.ToInt64(arrayVakue[1])); 60 | if (updateresult) 61 | { 62 | TempData["Verify"] = "Done"; 63 | return RedirectToAction("Completed", "VerifyRegistration"); 64 | } 65 | else 66 | { 67 | TempData["TokenErrorMessage"] = "Sorry Verification Failed Please request a new Verification link!"; 68 | return RedirectToAction("Login", "Portal"); 69 | } 70 | 71 | } 72 | 73 | } 74 | } 75 | } 76 | } 77 | catch (Exception) 78 | { 79 | TempData["TokenMessage"] = "Sorry Verification Failed Please request a new Verification link!"; 80 | return RedirectToAction("Login", "Portal"); 81 | } 82 | 83 | TempData["TokenMessage"] = "Sorry Verification Failed Please request a new Verification link!"; 84 | return RedirectToAction("Login", "Portal"); 85 | } 86 | 87 | 88 | [HttpGet] 89 | public IActionResult Completed() 90 | { 91 | if (Convert.ToString(TempData["Verify"]) == "Done") 92 | { 93 | TempData["RegistrationCompleted"] = "Registration Process Completed. Now you can Login and Access Account."; 94 | return View(); 95 | } 96 | else 97 | { 98 | TempData["TokenMessage"] = "Sorry Verification Failed Please request a new Verification link!"; 99 | return RedirectToAction("Login", "Portal"); 100 | } 101 | 102 | } 103 | 104 | } 105 | } -------------------------------------------------------------------------------- /WebSecure/Controllers/VerifyResetPasswordController.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Threading.Tasks; 5 | using Microsoft.AspNetCore.Http; 6 | using Microsoft.AspNetCore.Mvc; 7 | using WebSecure.Helpers; 8 | using WebSecure.Repository; 9 | 10 | namespace WebSecure.Controllers 11 | { 12 | public class VerifyResetPasswordController : Controller 13 | { 14 | private readonly IVerificationRepository _verificationRepository; 15 | public VerifyResetPasswordController(IVerificationRepository verificationRepository) 16 | { 17 | _verificationRepository = verificationRepository; 18 | } 19 | 20 | 21 | [HttpGet] 22 | public IActionResult Verify(string key, string hashtoken) 23 | { 24 | try 25 | { 26 | if (!string.IsNullOrEmpty(key) && !string.IsNullOrEmpty(hashtoken)) 27 | { 28 | var arrayVakue = SecurityManager.SplitToken(key); 29 | if (arrayVakue != null) 30 | { 31 | // arrayVakue[1] "UserId" 32 | var rvModel = _verificationRepository.GetResetGeneratedToken(arrayVakue[1]); 33 | if (rvModel != null) 34 | { 35 | var result = SecurityManager.IsTokenValid(arrayVakue, hashtoken, rvModel.GeneratedToken); 36 | 37 | if (result == 1) 38 | { 39 | TempData["TokenMessage"] = "Sorry Verification Link Expired Please request a new Verification link!"; 40 | return RedirectToAction("Login", "Portal"); 41 | } 42 | 43 | if (result == 2) 44 | { 45 | TempData["TokenMessage"] = "Sorry Verification Link Expired Please request a new Verification link!"; 46 | return RedirectToAction("Login", "Portal"); 47 | } 48 | 49 | if (result == 0) 50 | { 51 | HttpContext.Session.SetString("VerificationUserId", arrayVakue[1]); 52 | HttpContext.Session.SetString("ActiveVerification", "1"); 53 | return RedirectToAction("Reset", "ResetPassword"); 54 | } 55 | 56 | } 57 | } 58 | } 59 | } 60 | catch (Exception) 61 | { 62 | TempData["TokenMessage"] = "Sorry Verification Failed Please request a new Verification link!"; 63 | return RedirectToAction("Login", "Portal"); 64 | } 65 | 66 | TempData["TokenMessage"] = "Sorry Verification Failed Please request a new Verification link!"; 67 | return RedirectToAction("Login", "Portal"); 68 | } 69 | } 70 | } -------------------------------------------------------------------------------- /WebSecure/Filters/AuthorizeResetPasswordAttribute.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Threading.Tasks; 5 | using Microsoft.AspNetCore.Http; 6 | using Microsoft.AspNetCore.Mvc; 7 | using Microsoft.AspNetCore.Mvc.Filters; 8 | 9 | namespace WebSecure.Filters 10 | { 11 | public class AuthorizeResetPasswordAttribute : ActionFilterAttribute 12 | { 13 | public override void OnActionExecuting(ActionExecutingContext context) 14 | { 15 | if (!string.IsNullOrEmpty(Convert.ToString(context.HttpContext.Session.GetString("ActiveVerification")))) 16 | { 17 | string activeVerificationvalue = (string)context.HttpContext.Session.GetString("ActiveVerification"); 18 | 19 | if ("1" != activeVerificationvalue) 20 | { 21 | ViewResult result = new ViewResult(); 22 | result.ViewName = "Error"; 23 | 24 | if (context.Controller is Controller controller) 25 | { 26 | controller.TempData["ErrorMessage"] = "Sorry Verification Failed Please request a new Verification link!"; 27 | } 28 | 29 | context.Result = result; 30 | } 31 | } 32 | else 33 | { 34 | ViewResult result = new ViewResult(); 35 | result.ViewName = "Error"; 36 | 37 | if (context.Controller is Controller controller) 38 | { 39 | controller.TempData["ErrorMessage"] = "Sorry Verification Failed Please request a new Verification link!"; 40 | } 41 | 42 | context.Result = result; 43 | 44 | } 45 | } 46 | } 47 | } 48 | -------------------------------------------------------------------------------- /WebSecure/Filters/AuthorizeUserAttribute.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Threading.Tasks; 5 | using Microsoft.AspNetCore.Http; 6 | using Microsoft.AspNetCore.Mvc; 7 | using Microsoft.AspNetCore.Mvc.Filters; 8 | 9 | namespace WebSecure.Filters 10 | { 11 | public class AuthorizeUserAttribute : ActionFilterAttribute 12 | { 13 | public override void OnActionExecuting(ActionExecutingContext context) 14 | { 15 | if (string.IsNullOrEmpty(Convert.ToString(context.HttpContext.Session.GetString("UserId")))) 16 | { 17 | 18 | ViewResult result = new ViewResult(); 19 | result.ViewName = "Error"; 20 | 21 | if (context.Controller is Controller controller) 22 | { 23 | controller.TempData["ErrorMessage"] = "Sorry Verification Failed Please request a new Verification link!"; 24 | } 25 | 26 | context.Result = result; 27 | 28 | } 29 | } 30 | } 31 | } -------------------------------------------------------------------------------- /WebSecure/Helpers/AesAlgorithm.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Security.Cryptography; 5 | using System.Text; 6 | using System.Threading.Tasks; 7 | 8 | namespace WebSecure.Helpers 9 | { 10 | public class AesAlgorithm 11 | { 12 | private static readonly RijndaelManaged Rijndael = new RijndaelManaged(); 13 | private static readonly System.Text.UnicodeEncoding UnicodeEncoding = new UnicodeEncoding(); 14 | 15 | private const int ChunkSize = 128; 16 | private const string Base64Key = "ZVRoV21acTR0N3cheiVDKg=="; 17 | private const string Base64Iv = "RChHK0tiUGRTZ1ZrWXAzcw=="; 18 | 19 | private void InitializeRijndael() 20 | { 21 | Rijndael.Mode = CipherMode.CBC; 22 | Rijndael.Padding = PaddingMode.PKCS7; 23 | } 24 | 25 | public AesAlgorithm() 26 | { 27 | InitializeRijndael(); 28 | 29 | Rijndael.KeySize = ChunkSize; 30 | Rijndael.BlockSize = ChunkSize; 31 | 32 | Rijndael.Key = Convert.FromBase64String(Base64Key); 33 | Rijndael.IV = Convert.FromBase64String(Base64Iv); 34 | } 35 | 36 | public AesAlgorithm(byte[] key, byte[] iv) 37 | { 38 | InitializeRijndael(); 39 | 40 | Rijndael.Key = key; 41 | Rijndael.IV = iv; 42 | } 43 | 44 | public string Decrypt(byte[] cipher) 45 | { 46 | ICryptoTransform transform = Rijndael.CreateDecryptor(); 47 | byte[] decryptedValue = transform.TransformFinalBlock(cipher, 0, cipher.Length); 48 | return UnicodeEncoding.GetString(decryptedValue); 49 | } 50 | 51 | public string DecryptFromBase64String(string base64Cipher) 52 | { 53 | return Decrypt(Convert.FromBase64String(base64Cipher)); 54 | } 55 | 56 | public byte[] EncryptToByte(string plain) 57 | { 58 | ICryptoTransform encryptor = Rijndael.CreateEncryptor(); 59 | byte[] cipher = UnicodeEncoding.GetBytes(plain); 60 | byte[] encryptedValue = encryptor.TransformFinalBlock(cipher, 0, cipher.Length); 61 | return encryptedValue; 62 | } 63 | 64 | public string EncryptToBase64String(string plain) 65 | { 66 | return Convert.ToBase64String(EncryptToByte(plain)); 67 | } 68 | 69 | public string GetKey() 70 | { 71 | return Convert.ToBase64String(Rijndael.Key); 72 | } 73 | 74 | public string GetIV() 75 | { 76 | return Convert.ToBase64String(Rijndael.IV); 77 | } 78 | 79 | public override string ToString() 80 | { 81 | return "KEY:" + GetKey() + Environment.NewLine + "IV:" + GetIV(); 82 | } 83 | } 84 | } 85 | -------------------------------------------------------------------------------- /WebSecure/Helpers/GenerateHashSha256.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Security.Cryptography; 5 | using System.Text; 6 | using System.Threading.Tasks; 7 | 8 | namespace WebSecure.Helpers 9 | { 10 | public static class GenerateHashSha256 11 | { 12 | public static string ComputeSha256Hash(string rawData) 13 | { 14 | // Create a SHA256 15 | using (SHA256 sha256Hash = SHA256.Create()) 16 | { 17 | // ComputeHash - returns byte array 18 | byte[] bytes = sha256Hash.ComputeHash(Encoding.UTF8.GetBytes(rawData)); 19 | 20 | // Convert byte array to a string 21 | StringBuilder builder = new StringBuilder(); 22 | foreach (var t in bytes) 23 | { 24 | builder.Append(t.ToString("x2")); 25 | } 26 | 27 | return builder.ToString(); 28 | } 29 | } 30 | } 31 | 32 | public static class GeneratePageHash 33 | { 34 | public static string Hash(string valuetohash) 35 | { 36 | if (!string.IsNullOrEmpty(valuetohash)) 37 | { 38 | return GenerateHashSha256.ComputeSha256Hash(valuetohash); 39 | } 40 | else 41 | { 42 | throw new System.ArgumentException("Parameter cannot be null", $"GeneratePageHash:valuetohash"); 43 | } 44 | 45 | } 46 | } 47 | } 48 | -------------------------------------------------------------------------------- /WebSecure/Helpers/GenerateHashSha512.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Threading.Tasks; 5 | 6 | namespace WebSecure.Helpers 7 | { 8 | public class GenerateHashSha512 9 | { 10 | public static string Sha512(string hashpassword,string salt) 11 | { 12 | string saltAndPwd = String.Concat(hashpassword, salt); 13 | var bytes = System.Text.Encoding.UTF8.GetBytes(saltAndPwd); 14 | using var hash = System.Security.Cryptography.SHA512.Create(); 15 | var hashedInputBytes = hash.ComputeHash(bytes); 16 | var hashedInputStringBuilder = new System.Text.StringBuilder(128); 17 | foreach (var b in hashedInputBytes) 18 | { 19 | hashedInputStringBuilder.Append(b.ToString("X2")); 20 | } 21 | 22 | return hashedInputStringBuilder.ToString(); 23 | } 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /WebSecure/Helpers/GenerateRandomNumbers.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Security.Cryptography; 5 | using System.Text; 6 | using System.Threading.Tasks; 7 | 8 | namespace WebSecure.Helpers 9 | { 10 | public class GenerateRandomNumbers 11 | { 12 | public static string RandomNumbers(int length) 13 | { 14 | const string valid = "1234567890"; 15 | StringBuilder res = new StringBuilder(); 16 | using RNGCryptoServiceProvider rng = new RNGCryptoServiceProvider(); 17 | byte[] uintBuffer = new byte[sizeof(uint)]; 18 | 19 | while (length-- > 0) 20 | { 21 | rng.GetBytes(uintBuffer); 22 | uint num = BitConverter.ToUInt32(uintBuffer, 0); 23 | res.Append(valid[(int)(num % (uint)valid.Length)]); 24 | } 25 | 26 | return res.ToString(); 27 | } 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /WebSecure/Helpers/SecurityManager.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Threading.Tasks; 5 | 6 | namespace WebSecure.Helpers 7 | { 8 | public class SecurityManager 9 | { 10 | private static readonly int _expirationMinutes = 1440; 11 | 12 | public static string[] SplitToken(string key) 13 | { 14 | if (key == null) throw new ArgumentNullException(nameof(key)); 15 | AesAlgorithm aesAlgorithm = new AesAlgorithm(); 16 | var decryptkey = aesAlgorithm.DecryptFromBase64String(key); 17 | string[] parts = decryptkey.Split(new char[] {':'}); 18 | return parts; 19 | } 20 | 21 | public static Int16 IsTokenValid(string[] parts, string receivedtoken, string storedtoken) 22 | { 23 | if (!string.Equals(receivedtoken, storedtoken, StringComparison.Ordinal)) 24 | { 25 | return 1; 26 | } 27 | 28 | long ticks = long.Parse(parts[0]); 29 | string userid = parts[1]; 30 | DateTime timeStamp = new DateTime(ticks); 31 | bool expired = Math.Abs((DateTime.UtcNow - timeStamp).TotalMinutes) > _expirationMinutes; 32 | if (expired) 33 | { 34 | return 2; 35 | } 36 | 37 | return 0; 38 | } 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /WebSecure/Images/1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/saineshwar/WebSecure/85a1749464c547444b1c942fc0902a6fa15479c7/WebSecure/Images/1.png -------------------------------------------------------------------------------- /WebSecure/Images/10.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/saineshwar/WebSecure/85a1749464c547444b1c942fc0902a6fa15479c7/WebSecure/Images/10.png -------------------------------------------------------------------------------- /WebSecure/Images/11.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/saineshwar/WebSecure/85a1749464c547444b1c942fc0902a6fa15479c7/WebSecure/Images/11.png -------------------------------------------------------------------------------- /WebSecure/Images/12.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/saineshwar/WebSecure/85a1749464c547444b1c942fc0902a6fa15479c7/WebSecure/Images/12.png -------------------------------------------------------------------------------- /WebSecure/Images/13.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/saineshwar/WebSecure/85a1749464c547444b1c942fc0902a6fa15479c7/WebSecure/Images/13.png -------------------------------------------------------------------------------- /WebSecure/Images/2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/saineshwar/WebSecure/85a1749464c547444b1c942fc0902a6fa15479c7/WebSecure/Images/2.png -------------------------------------------------------------------------------- /WebSecure/Images/3.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/saineshwar/WebSecure/85a1749464c547444b1c942fc0902a6fa15479c7/WebSecure/Images/3.png -------------------------------------------------------------------------------- /WebSecure/Images/4.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/saineshwar/WebSecure/85a1749464c547444b1c942fc0902a6fa15479c7/WebSecure/Images/4.png -------------------------------------------------------------------------------- /WebSecure/Images/5.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/saineshwar/WebSecure/85a1749464c547444b1c942fc0902a6fa15479c7/WebSecure/Images/5.png -------------------------------------------------------------------------------- /WebSecure/Images/6.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/saineshwar/WebSecure/85a1749464c547444b1c942fc0902a6fa15479c7/WebSecure/Images/6.png -------------------------------------------------------------------------------- /WebSecure/Images/7.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/saineshwar/WebSecure/85a1749464c547444b1c942fc0902a6fa15479c7/WebSecure/Images/7.png -------------------------------------------------------------------------------- /WebSecure/Images/8.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/saineshwar/WebSecure/85a1749464c547444b1c942fc0902a6fa15479c7/WebSecure/Images/8.png -------------------------------------------------------------------------------- /WebSecure/Images/9.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/saineshwar/WebSecure/85a1749464c547444b1c942fc0902a6fa15479c7/WebSecure/Images/9.png -------------------------------------------------------------------------------- /WebSecure/Models/ErrorViewModel.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | 3 | namespace WebSecure.Models 4 | { 5 | public class ErrorViewModel 6 | { 7 | public string RequestId { get; set; } 8 | 9 | public bool ShowRequestId => !string.IsNullOrEmpty(RequestId); 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /WebSecure/Program.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Threading.Tasks; 5 | using Microsoft.AspNetCore.Hosting; 6 | using Microsoft.Extensions.Configuration; 7 | using Microsoft.Extensions.Hosting; 8 | using Microsoft.Extensions.Logging; 9 | 10 | namespace WebSecure 11 | { 12 | public class Program 13 | { 14 | public static void Main(string[] args) 15 | { 16 | CreateHostBuilder(args).Build().Run(); 17 | } 18 | 19 | public static IHostBuilder CreateHostBuilder(string[] args) => 20 | Host.CreateDefaultBuilder(args) 21 | .ConfigureWebHostDefaults(webBuilder => 22 | { 23 | webBuilder.UseStartup(); 24 | }); 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /WebSecure/Properties/launchSettings.json: -------------------------------------------------------------------------------- 1 | { 2 | "iisSettings": { 3 | "windowsAuthentication": false, 4 | "anonymousAuthentication": true, 5 | "iisExpress": { 6 | "applicationUrl": "http://localhost:51710", 7 | "sslPort": 44347 8 | } 9 | }, 10 | "profiles": { 11 | "IIS Express": { 12 | "commandName": "IISExpress", 13 | "launchBrowser": true, 14 | "environmentVariables": { 15 | "ASPNETCORE_ENVIRONMENT": "Development" 16 | } 17 | }, 18 | "WebSecure": { 19 | "commandName": "Project", 20 | "launchBrowser": true, 21 | "applicationUrl": "https://localhost:5001;http://localhost:5000", 22 | "environmentVariables": { 23 | "ASPNETCORE_ENVIRONMENT": "Development" 24 | } 25 | } 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /WebSecure/Startup.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Threading.Tasks; 5 | using Microsoft.AspNetCore.Builder; 6 | using Microsoft.AspNetCore.Hosting; 7 | using Microsoft.AspNetCore.HttpsPolicy; 8 | using Microsoft.EntityFrameworkCore; 9 | using Microsoft.Extensions.Configuration; 10 | using Microsoft.Extensions.DependencyInjection; 11 | using Microsoft.Extensions.Hosting; 12 | using WebSecure.Repository; 13 | using WebSecure.ViewModel; 14 | 15 | namespace WebSecure 16 | { 17 | public class Startup 18 | { 19 | public Startup(IConfiguration configuration) 20 | { 21 | Configuration = configuration; 22 | } 23 | 24 | public IConfiguration Configuration { get; } 25 | 26 | // This method gets called by the runtime. Use this method to add services to the container. 27 | public void ConfigureServices(IServiceCollection services) 28 | { 29 | var connection = Configuration.GetConnectionString("DatabaseConnection"); 30 | 31 | // UseRowNumberForPaging for Using Skip and Take in .Net Core 32 | services.AddDbContext(options => options.UseSqlServer(connection)); 33 | 34 | services.AddControllersWithViews(); 35 | services.AddTransient(); 36 | services.AddTransient(); 37 | 38 | services.Configure(Configuration.GetSection("ApplicationSettings")); 39 | services.Configure(Configuration.GetSection("ConnectionStrings")); 40 | 41 | // For Setting Session Timeout 42 | services.AddSession(options => 43 | { 44 | // Set a short timeout for easy testing. 45 | options.IdleTimeout = TimeSpan.FromHours(1); 46 | options.Cookie.HttpOnly = true; 47 | // Make the session cookie essential 48 | options.Cookie.IsEssential = true; 49 | }); 50 | } 51 | 52 | // This method gets called by the runtime. Use this method to configure the HTTP request pipeline. 53 | public void Configure(IApplicationBuilder app, IWebHostEnvironment env) 54 | { 55 | if (env.IsDevelopment()) 56 | { 57 | app.UseDeveloperExceptionPage(); 58 | } 59 | else 60 | { 61 | app.UseExceptionHandler("/Home/Error"); 62 | // The default HSTS value is 30 days. You may want to change this for production scenarios, see https://aka.ms/aspnetcore-hsts. 63 | app.UseHsts(); 64 | } 65 | app.UseHttpsRedirection(); 66 | app.UseStaticFiles(); 67 | app.UseRouting(); 68 | app.UseSession(); 69 | app.UseEndpoints(endpoints => 70 | { 71 | endpoints.MapControllerRoute( 72 | name: "default", 73 | pattern: "{controller=Portal}/{action=Login}/{id?}"); 74 | }); 75 | } 76 | } 77 | } 78 | -------------------------------------------------------------------------------- /WebSecure/Views/ChangePassword/Process.cshtml: -------------------------------------------------------------------------------- 1 | @model WebSecure.ViewModel.ChangePasswordViewModel 2 | @{ 3 | ViewData["Title"] = "Reset"; 4 | Layout= "~/Views/Shared/_UserLayout.cshtml"; 5 | } 6 | 7 |
Change Password
8 | 9 |
10 |
11 | @Html.ValidationSummary(false, "", new { @class = "text-danger" }) 12 | @if (TempData["ChangePassword_Error_Message"] != null) 13 | { 14 |
15 | 16 | Message! @TempData["Reset_Error_Message"] 17 |
18 | } 19 | @if (TempData["ChangePassword_Success_Message"] != null) 20 | { 21 |
22 | 23 | Message! @TempData["ChangePassword_Success_Message"] 24 |
25 | } 26 | 27 |
28 | 29 | @Html.PasswordFor(model => model.CurrentPassword, new { @class = "form-control", @placeholder = "Current Password", @maxlength = 150, @autocomplete = "off" }) 30 | @Html.ValidationMessageFor(model => model.CurrentPassword, "", new { @class = "text-danger" }) 31 |
32 |
33 | 34 | @Html.PasswordFor(model => model.Password, new { @class = "form-control", @placeholder = "Password", @maxlength = 150, @autocomplete = "off" }) 35 | @Html.ValidationMessageFor(model => model.Password, "", new { @class = "text-danger" }) 36 |
37 |
38 | 39 | @Html.PasswordFor(model => model.ConfirmPassword, new { @class = "form-control", @placeholder = "Confirm Password", @maxlength = 150, @autocomplete = "off" }) 40 | @Html.ValidationMessageFor(model => model.ConfirmPassword, "", new { @class = "text-danger" }) 41 |
42 | 43 | 44 |
45 |
46 | 47 | @section Scripts{ 48 | 49 | 50 | 51 | 52 | 111 | } -------------------------------------------------------------------------------- /WebSecure/Views/Dashboard/Dashboard.cshtml: -------------------------------------------------------------------------------- 1 |  2 | @{ 3 | ViewData["Title"] = "Dashboard"; 4 | Layout = "~/Views/Shared/_UserLayout.cshtml"; 5 | } 6 |
Dashboard
7 | 8 | -------------------------------------------------------------------------------- /WebSecure/Views/ForgotPassword/Process.cshtml: -------------------------------------------------------------------------------- 1 | @model WebSecure.ViewModel.ForgotPasswordViewModel 2 | @{ 3 | ViewData["Title"] = "Process"; 4 | } 5 | 6 |
Forgot Password
7 |
8 |
9 | 10 | @if (TempData["ForgotPasswordMessage"] != null) 11 | { 12 |
13 | 14 | Message! @TempData["ForgotPasswordMessage"] 15 |
16 | } 17 | @Html.ValidationSummary(false, "", new { @class = "text-danger" }) 18 | 19 | @Html.AntiForgeryToken() 20 |
21 | 22 | @Html.TextBoxFor(model => model.UserName, new { @class = "form-control", @placeholder = "Username", @maxlength = 20, @autocomplete = "off" }) 23 | @Html.ValidationMessageFor(model => model.UserName, "", new { @class = "text-danger" }) 24 |
25 | 26 |
27 |
28 | 29 | @section Scripts{ 30 | 31 | 32 | } -------------------------------------------------------------------------------- /WebSecure/Views/Home/Index.cshtml: -------------------------------------------------------------------------------- 1 | @{ 2 | ViewData["Title"] = "Home Page"; 3 | } 4 | 5 |
6 |

Welcome

7 |

Learn about building Web apps with ASP.NET Core.

8 |
9 | -------------------------------------------------------------------------------- /WebSecure/Views/Home/Privacy.cshtml: -------------------------------------------------------------------------------- 1 | @{ 2 | ViewData["Title"] = "Privacy Policy"; 3 | } 4 |

@ViewData["Title"]

5 | 6 |

Use this page to detail your site's privacy policy.

7 | -------------------------------------------------------------------------------- /WebSecure/Views/Portal/Login.cshtml: -------------------------------------------------------------------------------- 1 | @model WebSecure.ViewModel.LoginViewModel 2 | @{ 3 | ViewData["Title"] = "Register"; 4 | } 5 | 6 |
Login
7 |
8 |
9 | @Html.ValidationSummary(false, "", new { @class = "text-danger" }) 10 | @if (TempData["TokenErrorMessage"] != null) 11 | { 12 |
13 | 14 | Message! @TempData["TokenErrorMessage"] 15 |
16 | } 17 | 18 | @if (TempData["TokenMessage"] != null) 19 | { 20 |
21 | 22 | Message! @TempData["TokenMessage"] 23 |
24 | } 25 | 26 | 27 | @Html.AntiForgeryToken() 28 |
29 | 30 | @Html.TextBoxFor(model => model.UserName, new { @class = "form-control", @placeholder = "Username", @maxlength = 20, @autocomplete = "off" }) 31 | @Html.ValidationMessageFor(model => model.UserName, "", new { @class = "text-danger" }) 32 |
33 |
34 | 35 | @Html.PasswordFor(model => model.Password, new { @class = "form-control", @placeholder = "Password", @maxlength = 150, @autocomplete = "off" }) 36 | @Html.ValidationMessageFor(model => model.Password, "", new { @class = "text-danger" }) 37 |
38 | 39 | Forgot Password | 40 | Registration 41 |
42 |
43 | 44 | @section Scripts{ 45 | 46 | 47 | 48 | 49 | 64 | } -------------------------------------------------------------------------------- /WebSecure/Views/Registration/Register.cshtml: -------------------------------------------------------------------------------- 1 | @model WebSecure.ViewModel.RegisterViewModel 2 | @{ 3 | ViewData["Title"] = "Register"; 4 | } 5 | 6 |
Register
7 |
8 | 9 | @if (TempData["Registered_Error_Message"] != null) 10 | { 11 |
12 | 13 | Message! @TempData["Registered_Error_Message"] 14 |
15 | } 16 | 17 | @if (TempData["Registered_Success_Message"] != null) 18 | { 19 |
20 | 21 | Message! @TempData["Registered_Success_Message"] 22 |
23 | } 24 | 25 |
26 | @Html.ValidationSummary(false, "", new { @class = "text-danger" }) 27 |
28 | 29 | @Html.TextBoxFor(model => model.FullName, new { @class = "form-control", @placeholder = "FullName", @maxlength = 50, @autocomplete = "off" }) 30 | @Html.ValidationMessageFor(model => model.FullName, "", new { @class = "text-danger" }) 31 |
32 |
33 | 34 | @Html.TextBoxFor(model => model.UserName, new { @class = "form-control", @placeholder = "Username", @maxlength = 50, @autocomplete = "off" }) 35 | @Html.ValidationMessageFor(model => model.UserName, "", new { @class = "text-danger" }) 36 |
37 |
38 | 39 | @Html.TextBoxFor(model => model.Email, new { @class = "form-control", @placeholder = "Email", @maxlength = 100, @autocomplete = "off" }) 40 | @Html.ValidationMessageFor(model => model.Email, "", new { @class = "text-danger" }) 41 |
42 |
43 | 44 | @Html.TextBoxFor(model => model.Phoneno, new { @class = "form-control", @placeholder = "Phoneno", @maxlength = 20, @autocomplete = "off" }) 45 | @Html.ValidationMessageFor(model => model.Phoneno, "", new { @class = "text-danger" }) 46 |
47 |
48 | 49 | @Html.PasswordFor(model => model.Password, new { @class = "form-control", @placeholder = "Password", @maxlength = 150, @autocomplete = "off" }) 50 | @Html.ValidationMessageFor(model => model.Password, "", new { @class = "text-danger" }) 51 |
52 |
53 | 54 | @Html.PasswordFor(model => model.ConfirmPassword, new { @class = "form-control", @placeholder = "ConfirmPassword", @maxlength = 150, @autocomplete = "off" }) 55 | @Html.ValidationMessageFor(model => model.ConfirmPassword, "", new { @class = "text-danger" }) 56 |
57 | 58 | 59 |
60 |
61 | @section Scripts{ 62 | 63 | 64 | 65 | 66 | 114 | } 115 | -------------------------------------------------------------------------------- /WebSecure/Views/ResetPassword/Reset.cshtml: -------------------------------------------------------------------------------- 1 | @model WebSecure.ViewModel.ResetPasswordViewModel 2 | @{ 3 | ViewData["Title"] = "Reset"; 4 | } 5 | 6 |
Reset Password
7 | 8 |
9 |
10 | 11 | @if (TempData["Reset_Error_Message"] != null) 12 | { 13 |
14 | 15 | Message! @TempData["Reset_Error_Message"] 16 |
17 | } 18 | @Html.ValidationSummary(false, "", new { @class = "text-danger" }) 19 |
20 | 21 | @Html.PasswordFor(model => model.Password, new { @class = "form-control", @placeholder = "Password", @maxlength = 150, @autocomplete = "off" }) 22 | @Html.ValidationMessageFor(model => model.Password, "", new { @class = "text-danger" }) 23 |
24 |
25 | 26 | @Html.PasswordFor(model => model.ConfirmPassword, new { @class = "form-control", @placeholder = "ConfirmPassword", @maxlength = 150, @autocomplete = "off" }) 27 | @Html.ValidationMessageFor(model => model.ConfirmPassword, "", new { @class = "text-danger" }) 28 |
29 | 30 | 31 |
32 |
33 | 34 | @section Scripts{ 35 | 36 | 37 | 38 | 39 | 86 | } -------------------------------------------------------------------------------- /WebSecure/Views/Shared/Error.cshtml: -------------------------------------------------------------------------------- 1 | @model ErrorViewModel 2 | @{ 3 | ViewData["Title"] = "Error"; 4 | } 5 | 6 |

Error.

7 |

An error occurred while processing your request.

8 | 9 | @if (Model.ShowRequestId) 10 | { 11 |

12 | Request ID: @Model.RequestId 13 |

14 | } 15 | 16 |

Development Mode

17 |

18 | Swapping to Development environment will display more detailed information about the error that occurred. 19 |

20 |

21 | The Development environment shouldn't be enabled for deployed applications. 22 | It can result in displaying sensitive information from exceptions to end users. 23 | For local debugging, enable the Development environment by setting the ASPNETCORE_ENVIRONMENT environment variable to Development 24 | and restarting the app. 25 |

26 | -------------------------------------------------------------------------------- /WebSecure/Views/Shared/_Layout.cshtml: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | 6 | @ViewData["Title"] - WebSecure 7 | 8 | 9 | 10 | 11 |
12 | 26 |
27 |
28 |
29 | @RenderBody() 30 |
31 |
32 | 33 |
34 |
35 | © 2020 - WebSecure - Privacy 36 |
37 |
38 | 39 | 40 | 41 | @RenderSection("Scripts", required: false) 42 | 43 | 44 | -------------------------------------------------------------------------------- /WebSecure/Views/Shared/_UserLayout.cshtml: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | 6 | @ViewData["Title"] - WebSecure 7 | 8 | 9 | 10 | 11 |
12 | 31 |
32 |
33 |
34 | @RenderBody() 35 |
36 |
37 | 38 |
39 |
40 | © 2020 - WebSecure - Privacy 41 |
42 |
43 | 44 | 45 | 46 | @RenderSection("Scripts", required: false) 47 | 48 | 49 | -------------------------------------------------------------------------------- /WebSecure/Views/Shared/_ValidationScriptsPartial.cshtml: -------------------------------------------------------------------------------- 1 |  2 | 3 | -------------------------------------------------------------------------------- /WebSecure/Views/VerifyRegistration/Completed.cshtml: -------------------------------------------------------------------------------- 1 |  2 | @{ 3 | ViewData["Title"] = "Completed"; 4 | } 5 | 6 | 7 | @if (TempData["RegistrationCompleted"] != null) 8 | { 9 |
10 | 11 | Message! @TempData["RegistrationCompleted"] Login Link. 12 |
13 | } 14 | -------------------------------------------------------------------------------- /WebSecure/Views/_ViewImports.cshtml: -------------------------------------------------------------------------------- 1 | @using WebSecure 2 | @using WebSecure.Models 3 | @addTagHelper *, Microsoft.AspNetCore.Mvc.TagHelpers 4 | -------------------------------------------------------------------------------- /WebSecure/Views/_ViewStart.cshtml: -------------------------------------------------------------------------------- 1 | @{ 2 | Layout = "_Layout"; 3 | } 4 | -------------------------------------------------------------------------------- /WebSecure/WebSecure.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | netcoreapp3.1 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | -------------------------------------------------------------------------------- /WebSecure/appsettings.Development.json: -------------------------------------------------------------------------------- 1 | { 2 | "Logging": { 3 | "LogLevel": { 4 | "Default": "Information", 5 | "Microsoft": "Warning", 6 | "Microsoft.Hosting.Lifetime": "Information" 7 | } 8 | } 9 | } 10 | -------------------------------------------------------------------------------- /WebSecure/appsettings.json: -------------------------------------------------------------------------------- 1 | { 2 | "Logging": { 3 | "LogLevel": { 4 | "Default": "Information", 5 | "Microsoft": "Warning", 6 | "Microsoft.Hosting.Lifetime": "Information" 7 | } 8 | }, 9 | "AllowedHosts": "*", 10 | "ConnectionStrings": { 11 | "DatabaseConnection": "Data Source=DESKTOP-DUM6D15\\MSSQLSERVERSTD; initial catalog=CustomerDB; user id=sa; password=Pass$123" 12 | }, 13 | "ApplicationSettings": { 14 | "EmailFrom": "demo@gmail.com", 15 | "Password": "@@@@@@@@@@", 16 | "Port": "587", 17 | "Host": "smtp.gmail.com", 18 | "VerifyRegistrationUrl": "https://localhost:44347/VerifyRegistration/Verify", 19 | "VerifyResetPasswordUrl": "https://localhost:44347/VerifyResetPassword/Verify", 20 | "WebsiteURL": "https://localhost:44347/PasswordReset/Reset" 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /WebSecure/wwwroot/crypto/sha256.min.js: -------------------------------------------------------------------------------- 1 | /** 2 | * [js-sha256]{@link https://github.com/emn178/js-sha256} 3 | * 4 | * @version 0.9.0 5 | * @author Chen, Yi-Cyuan [emn178@gmail.com] 6 | * @copyright Chen, Yi-Cyuan 2014-2017 7 | * @license MIT 8 | */ 9 | !function(){"use strict";function t(t,i){i?(d[0]=d[16]=d[1]=d[2]=d[3]=d[4]=d[5]=d[6]=d[7]=d[8]=d[9]=d[10]=d[11]=d[12]=d[13]=d[14]=d[15]=0,this.blocks=d):this.blocks=[0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0],t?(this.h0=3238371032,this.h1=914150663,this.h2=812702999,this.h3=4144912697,this.h4=4290775857,this.h5=1750603025,this.h6=1694076839,this.h7=3204075428):(this.h0=1779033703,this.h1=3144134277,this.h2=1013904242,this.h3=2773480762,this.h4=1359893119,this.h5=2600822924,this.h6=528734635,this.h7=1541459225),this.block=this.start=this.bytes=this.hBytes=0,this.finalized=this.hashed=!1,this.first=!0,this.is224=t}function i(i,r,s){var e,n=typeof i;if("string"===n){var o,a=[],u=i.length,c=0;for(e=0;e>6,a[c++]=128|63&o):o<55296||o>=57344?(a[c++]=224|o>>12,a[c++]=128|o>>6&63,a[c++]=128|63&o):(o=65536+((1023&o)<<10|1023&i.charCodeAt(++e)),a[c++]=240|o>>18,a[c++]=128|o>>12&63,a[c++]=128|o>>6&63,a[c++]=128|63&o);i=a}else{if("object"!==n)throw new Error(h);if(null===i)throw new Error(h);if(f&&i.constructor===ArrayBuffer)i=new Uint8Array(i);else if(!(Array.isArray(i)||f&&ArrayBuffer.isView(i)))throw new Error(h)}i.length>64&&(i=new t(r,!0).update(i).array());var y=[],p=[];for(e=0;e<64;++e){var l=i[e]||0;y[e]=92^l,p[e]=54^l}t.call(this,r,s),this.update(p),this.oKeyPad=y,this.inner=!0,this.sharedMemory=s}var h="input is invalid type",r="object"==typeof window,s=r?window:{};s.JS_SHA256_NO_WINDOW&&(r=!1);var e=!r&&"object"==typeof self,n=!s.JS_SHA256_NO_NODE_JS&&"object"==typeof process&&process.versions&&process.versions.node;n?s=global:e&&(s=self);var o=!s.JS_SHA256_NO_COMMON_JS&&"object"==typeof module&&module.exports,a="function"==typeof define&&define.amd,f=!s.JS_SHA256_NO_ARRAY_BUFFER&&"undefined"!=typeof ArrayBuffer,u="0123456789abcdef".split(""),c=[-2147483648,8388608,32768,128],y=[24,16,8,0],p=[1116352408,1899447441,3049323471,3921009573,961987163,1508970993,2453635748,2870763221,3624381080,310598401,607225278,1426881987,1925078388,2162078206,2614888103,3248222580,3835390401,4022224774,264347078,604807628,770255983,1249150122,1555081692,1996064986,2554220882,2821834349,2952996808,3210313671,3336571891,3584528711,113926993,338241895,666307205,773529912,1294757372,1396182291,1695183700,1986661051,2177026350,2456956037,2730485921,2820302411,3259730800,3345764771,3516065817,3600352804,4094571909,275423344,430227734,506948616,659060556,883997877,958139571,1322822218,1537002063,1747873779,1955562222,2024104815,2227730452,2361852424,2428436474,2756734187,3204031479,3329325298],l=["hex","array","digest","arrayBuffer"],d=[];!s.JS_SHA256_NO_NODE_JS&&Array.isArray||(Array.isArray=function(t){return"[object Array]"===Object.prototype.toString.call(t)}),!f||!s.JS_SHA256_NO_ARRAY_BUFFER_IS_VIEW&&ArrayBuffer.isView||(ArrayBuffer.isView=function(t){return"object"==typeof t&&t.buffer&&t.buffer.constructor===ArrayBuffer});var A=function(i,h){return function(r){return new t(h,!0).update(r)[i]()}},w=function(i){var h=A("hex",i);n&&(h=b(h,i)),h.create=function(){return new t(i)},h.update=function(t){return h.create().update(t)};for(var r=0;r>2]|=t[n]<>2]|=s<>2]|=(192|s>>6)<>2]|=(128|63&s)<=57344?(a[e>>2]|=(224|s>>12)<>2]|=(128|s>>6&63)<>2]|=(128|63&s)<>2]|=(240|s>>18)<>2]|=(128|s>>12&63)<>2]|=(128|s>>6&63)<>2]|=(128|63&s)<=64?(this.block=a[16],this.start=e-64,this.hash(),this.hashed=!0):this.start=e}return this.bytes>4294967295&&(this.hBytes+=this.bytes/4294967296<<0,this.bytes=this.bytes%4294967296),this}},t.prototype.finalize=function(){if(!this.finalized){this.finalized=!0;var t=this.blocks,i=this.lastByteIndex;t[16]=this.block,t[i>>2]|=c[3&i],this.block=t[16],i>=56&&(this.hashed||this.hash(),t[0]=this.block,t[16]=t[1]=t[2]=t[3]=t[4]=t[5]=t[6]=t[7]=t[8]=t[9]=t[10]=t[11]=t[12]=t[13]=t[14]=t[15]=0),t[14]=this.hBytes<<3|this.bytes>>>29,t[15]=this.bytes<<3,this.hash()}},t.prototype.hash=function(){var t,i,h,r,s,e,n,o,a,f=this.h0,u=this.h1,c=this.h2,y=this.h3,l=this.h4,d=this.h5,A=this.h6,w=this.h7,b=this.blocks;for(t=16;t<64;++t)i=((s=b[t-15])>>>7|s<<25)^(s>>>18|s<<14)^s>>>3,h=((s=b[t-2])>>>17|s<<15)^(s>>>19|s<<13)^s>>>10,b[t]=b[t-16]+i+b[t-7]+h<<0;for(a=u&c,t=0;t<64;t+=4)this.first?(this.is224?(e=300032,w=(s=b[0]-1413257819)-150054599<<0,y=s+24177077<<0):(e=704751109,w=(s=b[0]-210244248)-1521486534<<0,y=s+143694565<<0),this.first=!1):(i=(f>>>2|f<<30)^(f>>>13|f<<19)^(f>>>22|f<<10),r=(e=f&u)^f&c^a,w=y+(s=w+(h=(l>>>6|l<<26)^(l>>>11|l<<21)^(l>>>25|l<<7))+(l&d^~l&A)+p[t]+b[t])<<0,y=s+(i+r)<<0),i=(y>>>2|y<<30)^(y>>>13|y<<19)^(y>>>22|y<<10),r=(n=y&f)^y&u^e,A=c+(s=A+(h=(w>>>6|w<<26)^(w>>>11|w<<21)^(w>>>25|w<<7))+(w&l^~w&d)+p[t+1]+b[t+1])<<0,i=((c=s+(i+r)<<0)>>>2|c<<30)^(c>>>13|c<<19)^(c>>>22|c<<10),r=(o=c&y)^c&f^n,d=u+(s=d+(h=(A>>>6|A<<26)^(A>>>11|A<<21)^(A>>>25|A<<7))+(A&w^~A&l)+p[t+2]+b[t+2])<<0,i=((u=s+(i+r)<<0)>>>2|u<<30)^(u>>>13|u<<19)^(u>>>22|u<<10),r=(a=u&c)^u&y^o,l=f+(s=l+(h=(d>>>6|d<<26)^(d>>>11|d<<21)^(d>>>25|d<<7))+(d&A^~d&w)+p[t+3]+b[t+3])<<0,f=s+(i+r)<<0;this.h0=this.h0+f<<0,this.h1=this.h1+u<<0,this.h2=this.h2+c<<0,this.h3=this.h3+y<<0,this.h4=this.h4+l<<0,this.h5=this.h5+d<<0,this.h6=this.h6+A<<0,this.h7=this.h7+w<<0},t.prototype.hex=function(){this.finalize();var t=this.h0,i=this.h1,h=this.h2,r=this.h3,s=this.h4,e=this.h5,n=this.h6,o=this.h7,a=u[t>>28&15]+u[t>>24&15]+u[t>>20&15]+u[t>>16&15]+u[t>>12&15]+u[t>>8&15]+u[t>>4&15]+u[15&t]+u[i>>28&15]+u[i>>24&15]+u[i>>20&15]+u[i>>16&15]+u[i>>12&15]+u[i>>8&15]+u[i>>4&15]+u[15&i]+u[h>>28&15]+u[h>>24&15]+u[h>>20&15]+u[h>>16&15]+u[h>>12&15]+u[h>>8&15]+u[h>>4&15]+u[15&h]+u[r>>28&15]+u[r>>24&15]+u[r>>20&15]+u[r>>16&15]+u[r>>12&15]+u[r>>8&15]+u[r>>4&15]+u[15&r]+u[s>>28&15]+u[s>>24&15]+u[s>>20&15]+u[s>>16&15]+u[s>>12&15]+u[s>>8&15]+u[s>>4&15]+u[15&s]+u[e>>28&15]+u[e>>24&15]+u[e>>20&15]+u[e>>16&15]+u[e>>12&15]+u[e>>8&15]+u[e>>4&15]+u[15&e]+u[n>>28&15]+u[n>>24&15]+u[n>>20&15]+u[n>>16&15]+u[n>>12&15]+u[n>>8&15]+u[n>>4&15]+u[15&n];return this.is224||(a+=u[o>>28&15]+u[o>>24&15]+u[o>>20&15]+u[o>>16&15]+u[o>>12&15]+u[o>>8&15]+u[o>>4&15]+u[15&o]),a},t.prototype.toString=t.prototype.hex,t.prototype.digest=function(){this.finalize();var t=this.h0,i=this.h1,h=this.h2,r=this.h3,s=this.h4,e=this.h5,n=this.h6,o=this.h7,a=[t>>24&255,t>>16&255,t>>8&255,255&t,i>>24&255,i>>16&255,i>>8&255,255&i,h>>24&255,h>>16&255,h>>8&255,255&h,r>>24&255,r>>16&255,r>>8&255,255&r,s>>24&255,s>>16&255,s>>8&255,255&s,e>>24&255,e>>16&255,e>>8&255,255&e,n>>24&255,n>>16&255,n>>8&255,255&n];return this.is224||a.push(o>>24&255,o>>16&255,o>>8&255,255&o),a},t.prototype.array=t.prototype.digest,t.prototype.arrayBuffer=function(){this.finalize();var t=new ArrayBuffer(this.is224?28:32),i=new DataView(t);return i.setUint32(0,this.h0),i.setUint32(4,this.h1),i.setUint32(8,this.h2),i.setUint32(12,this.h3),i.setUint32(16,this.h4),i.setUint32(20,this.h5),i.setUint32(24,this.h6),this.is224||i.setUint32(28,this.h7),t},i.prototype=new t,i.prototype.finalize=function(){if(t.prototype.finalize.call(this),this.inner){this.inner=!1;var i=this.array();t.call(this,this.is224,this.sharedMemory),this.update(this.oKeyPad),this.update(i),t.prototype.finalize.call(this)}};var B=w();B.sha256=B,B.sha224=w(!0),B.sha256.hmac=_(),B.sha224.hmac=_(!0),o?module.exports=B:(s.sha256=B.sha256,s.sha224=B.sha224,a&&define(function(){return B}))}(); -------------------------------------------------------------------------------- /WebSecure/wwwroot/crypto/sha512.min.js: -------------------------------------------------------------------------------- 1 | /* 2 | * [js-sha512]{@link https://github.com/emn178/js-sha512} 3 | * 4 | * @version 0.8.0 5 | * @author Chen, Yi-Cyuan [emn178@gmail.com] 6 | * @copyright Chen, Yi-Cyuan 2014-2018 7 | * @license MIT 8 | */ 9 | !function(){"use strict";function h(h,t){t?(p[0]=p[1]=p[2]=p[3]=p[4]=p[5]=p[6]=p[7]=p[8]=p[9]=p[10]=p[11]=p[12]=p[13]=p[14]=p[15]=p[16]=p[17]=p[18]=p[19]=p[20]=p[21]=p[22]=p[23]=p[24]=p[25]=p[26]=p[27]=p[28]=p[29]=p[30]=p[31]=p[32]=0,this.blocks=p):this.blocks=[0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0],384==h?(this.h0h=3418070365,this.h0l=3238371032,this.h1h=1654270250,this.h1l=914150663,this.h2h=2438529370,this.h2l=812702999,this.h3h=355462360,this.h3l=4144912697,this.h4h=1731405415,this.h4l=4290775857,this.h5h=2394180231,this.h5l=1750603025,this.h6h=3675008525,this.h6l=1694076839,this.h7h=1203062813,this.h7l=3204075428):256==h?(this.h0h=573645204,this.h0l=4230739756,this.h1h=2673172387,this.h1l=3360449730,this.h2h=596883563,this.h2l=1867755857,this.h3h=2520282905,this.h3l=1497426621,this.h4h=2519219938,this.h4l=2827943907,this.h5h=3193839141,this.h5l=1401305490,this.h6h=721525244,this.h6l=746961066,this.h7h=246885852,this.h7l=2177182882):224==h?(this.h0h=2352822216,this.h0l=424955298,this.h1h=1944164710,this.h1l=2312950998,this.h2h=502970286,this.h2l=855612546,this.h3h=1738396948,this.h3l=1479516111,this.h4h=258812777,this.h4l=2077511080,this.h5h=2011393907,this.h5l=79989058,this.h6h=1067287976,this.h6l=1780299464,this.h7h=286451373,this.h7l=2446758561):(this.h0h=1779033703,this.h0l=4089235720,this.h1h=3144134277,this.h1l=2227873595,this.h2h=1013904242,this.h2l=4271175723,this.h3h=2773480762,this.h3l=1595750129,this.h4h=1359893119,this.h4l=2917565137,this.h5h=2600822924,this.h5l=725511199,this.h6h=528734635,this.h6l=4215389547,this.h7h=1541459225,this.h7l=327033209),this.bits=h,this.block=this.start=this.bytes=this.hBytes=0,this.finalized=this.hashed=!1}function t(t,s,e){var r,n=typeof t;if("string"!==n){if("object"!==n)throw new Error(i);if(null===t)throw new Error(i);if(a&&t.constructor===ArrayBuffer)t=new Uint8Array(t);else if(!(Array.isArray(t)||a&&ArrayBuffer.isView(t)))throw new Error(i);r=!0}var o=t.length;if(!r){for(var l,f=[],c=(o=t.length,0),u=0;u>6,f[c++]=128|63&l):l<55296||l>=57344?(f[c++]=224|l>>12,f[c++]=128|l>>6&63,f[c++]=128|63&l):(l=65536+((1023&l)<<10|1023&t.charCodeAt(++u)),f[c++]=240|l>>18,f[c++]=128|l>>12&63,f[c++]=128|l>>6&63,f[c++]=128|63&l);t=f}t.length>128&&(t=new h(s,!0).update(t).array());var y=[],p=[];for(u=0;u<128;++u){var d=t[u]||0;y[u]=92^d,p[u]=54^d}h.call(this,s,e),this.update(p),this.oKeyPad=y,this.inner=!0,this.sharedMemory=e}var i="input is invalid type",s="object"==typeof window,e=s?window:{};e.JS_SHA512_NO_WINDOW&&(s=!1);var r=!s&&"object"==typeof self;!e.JS_SHA512_NO_NODE_JS&&"object"==typeof process&&process.versions&&process.versions.node?e=global:r&&(e=self);var n=!e.JS_SHA512_NO_COMMON_JS&&"object"==typeof module&&module.exports,o="function"==typeof define&&define.amd,a=!e.JS_SHA512_NO_ARRAY_BUFFER&&"undefined"!=typeof ArrayBuffer,l="0123456789abcdef".split(""),f=[-2147483648,8388608,32768,128],c=[24,16,8,0],u=[1116352408,3609767458,1899447441,602891725,3049323471,3964484399,3921009573,2173295548,961987163,4081628472,1508970993,3053834265,2453635748,2937671579,2870763221,3664609560,3624381080,2734883394,310598401,1164996542,607225278,1323610764,1426881987,3590304994,1925078388,4068182383,2162078206,991336113,2614888103,633803317,3248222580,3479774868,3835390401,2666613458,4022224774,944711139,264347078,2341262773,604807628,2007800933,770255983,1495990901,1249150122,1856431235,1555081692,3175218132,1996064986,2198950837,2554220882,3999719339,2821834349,766784016,2952996808,2566594879,3210313671,3203337956,3336571891,1034457026,3584528711,2466948901,113926993,3758326383,338241895,168717936,666307205,1188179964,773529912,1546045734,1294757372,1522805485,1396182291,2643833823,1695183700,2343527390,1986661051,1014477480,2177026350,1206759142,2456956037,344077627,2730485921,1290863460,2820302411,3158454273,3259730800,3505952657,3345764771,106217008,3516065817,3606008344,3600352804,1432725776,4094571909,1467031594,275423344,851169720,430227734,3100823752,506948616,1363258195,659060556,3750685593,883997877,3785050280,958139571,3318307427,1322822218,3812723403,1537002063,2003034995,1747873779,3602036899,1955562222,1575990012,2024104815,1125592928,2227730452,2716904306,2361852424,442776044,2428436474,593698344,2756734187,3733110249,3204031479,2999351573,3329325298,3815920427,3391569614,3928383900,3515267271,566280711,3940187606,3454069534,4118630271,4000239992,116418474,1914138554,174292421,2731055270,289380356,3203993006,460393269,320620315,685471733,587496836,852142971,1086792851,1017036298,365543100,1126000580,2618297676,1288033470,3409855158,1501505948,4234509866,1607167915,987167468,1816402316,1246189591],y=["hex","array","digest","arrayBuffer"],p=[];!e.JS_SHA512_NO_NODE_JS&&Array.isArray||(Array.isArray=function(h){return"[object Array]"===Object.prototype.toString.call(h)}),!a||!e.JS_SHA512_NO_ARRAY_BUFFER_IS_VIEW&&ArrayBuffer.isView||(ArrayBuffer.isView=function(h){return"object"==typeof h&&h.buffer&&h.buffer.constructor===ArrayBuffer});var d=function(t,i){return function(s){return new h(i,!0).update(s)[t]()}},b=function(t){var i=d("hex",t);i.create=function(){return new h(t)},i.update=function(h){return i.create().update(h)};for(var s=0;s>2]|=h[n]<>2]|=e<>2]|=(192|e>>6)<>2]|=(128|63&e)<=57344?(l[r>>2]|=(224|e>>12)<>2]|=(128|e>>6&63)<>2]|=(128|63&e)<>2]|=(240|e>>18)<>2]|=(128|e>>12&63)<>2]|=(128|e>>6&63)<>2]|=(128|63&e)<=128?(this.block=l[32],this.start=r-128,this.hash(),this.hashed=!0):this.start=r}return this.bytes>4294967295&&(this.hBytes+=this.bytes/4294967296<<0,this.bytes=this.bytes%4294967296),this},h.prototype.finalize=function(){if(!this.finalized){this.finalized=!0;var h=this.blocks,t=this.lastByteIndex;h[32]=this.block,h[t>>2]|=f[3&t],this.block=h[32],t>=112&&(this.hashed||this.hash(),h[0]=this.block,h[1]=h[2]=h[3]=h[4]=h[5]=h[6]=h[7]=h[8]=h[9]=h[10]=h[11]=h[12]=h[13]=h[14]=h[15]=h[16]=h[17]=h[18]=h[19]=h[20]=h[21]=h[22]=h[23]=h[24]=h[25]=h[26]=h[27]=h[28]=h[29]=h[30]=h[31]=h[32]=0),h[30]=this.hBytes<<3|this.bytes>>>29,h[31]=this.bytes<<3,this.hash()}},h.prototype.hash=function(){var h,t,i,s,e,r,n,o,a,l,f,c,y,p,d,b,w,A,_,v,B,U,S,g,k,z=this.h0h,E=this.h0l,O=this.h1h,m=this.h1l,x=this.h2h,N=this.h2l,j=this.h3h,J=this.h3l,H=this.h4h,I=this.h4l,R=this.h5h,V=this.h5l,C=this.h6h,K=this.h6l,P=this.h7h,D=this.h7l,F=this.blocks;for(h=32;h<160;h+=2)t=((v=F[h-30])>>>1|(B=F[h-29])<<31)^(v>>>8|B<<24)^v>>>7,i=(B>>>1|v<<31)^(B>>>8|v<<24)^(B>>>7|v<<25),s=((v=F[h-4])>>>19|(B=F[h-3])<<13)^(B>>>29|v<<3)^v>>>6,e=(B>>>19|v<<13)^(v>>>29|B<<3)^(B>>>6|v<<26),v=F[h-32],B=F[h-31],a=((U=F[h-14])>>>16)+(v>>>16)+(t>>>16)+(s>>>16)+((o=(65535&U)+(65535&v)+(65535&t)+(65535&s)+((n=((S=F[h-13])>>>16)+(B>>>16)+(i>>>16)+(e>>>16)+((r=(65535&S)+(65535&B)+(65535&i)+(65535&e))>>>16))>>>16))>>>16),F[h]=a<<16|65535&o,F[h+1]=n<<16|65535&r;var M=z,T=E,W=O,Y=m,q=x,G=N,L=j,Q=J,X=H,Z=I,$=R,hh=V,th=C,ih=K,sh=P,eh=D;for(b=W&q,w=Y&G,h=0;h<160;h+=8)t=(M>>>28|T<<4)^(T>>>2|M<<30)^(T>>>7|M<<25),i=(T>>>28|M<<4)^(M>>>2|T<<30)^(M>>>7|T<<25),s=(X>>>14|Z<<18)^(X>>>18|Z<<14)^(Z>>>9|X<<23),e=(Z>>>14|X<<18)^(Z>>>18|X<<14)^(X>>>9|Z<<23),A=(l=M&W)^M&q^b,_=(f=T&Y)^T&G^w,g=X&$^~X&th,k=Z&hh^~Z&ih,v=F[h],B=F[h+1],v=(a=((U=u[h])>>>16)+(v>>>16)+(g>>>16)+(s>>>16)+(sh>>>16)+((o=(65535&U)+(65535&v)+(65535&g)+(65535&s)+(65535&sh)+((n=((S=u[h+1])>>>16)+(B>>>16)+(k>>>16)+(e>>>16)+(eh>>>16)+((r=(65535&S)+(65535&B)+(65535&k)+(65535&e)+(65535&eh))>>>16))>>>16))>>>16))<<16|65535&o,B=n<<16|65535&r,U=(a=(A>>>16)+(t>>>16)+((o=(65535&A)+(65535&t)+((n=(_>>>16)+(i>>>16)+((r=(65535&_)+(65535&i))>>>16))>>>16))>>>16))<<16|65535&o,S=n<<16|65535&r,sh=(a=(L>>>16)+(v>>>16)+((o=(65535&L)+(65535&v)+((n=(Q>>>16)+(B>>>16)+((r=(65535&Q)+(65535&B))>>>16))>>>16))>>>16))<<16|65535&o,eh=n<<16|65535&r,t=((L=(a=(U>>>16)+(v>>>16)+((o=(65535&U)+(65535&v)+((n=(S>>>16)+(B>>>16)+((r=(65535&S)+(65535&B))>>>16))>>>16))>>>16))<<16|65535&o)>>>28|(Q=n<<16|65535&r)<<4)^(Q>>>2|L<<30)^(Q>>>7|L<<25),i=(Q>>>28|L<<4)^(L>>>2|Q<<30)^(L>>>7|Q<<25),s=(sh>>>14|eh<<18)^(sh>>>18|eh<<14)^(eh>>>9|sh<<23),e=(eh>>>14|sh<<18)^(eh>>>18|sh<<14)^(sh>>>9|eh<<23),A=(c=L&M)^L&W^l,_=(y=Q&T)^Q&Y^f,g=sh&X^~sh&$,k=eh&Z^~eh&hh,v=F[h+2],B=F[h+3],v=(a=((U=u[h+2])>>>16)+(v>>>16)+(g>>>16)+(s>>>16)+(th>>>16)+((o=(65535&U)+(65535&v)+(65535&g)+(65535&s)+(65535&th)+((n=((S=u[h+3])>>>16)+(B>>>16)+(k>>>16)+(e>>>16)+(ih>>>16)+((r=(65535&S)+(65535&B)+(65535&k)+(65535&e)+(65535&ih))>>>16))>>>16))>>>16))<<16|65535&o,B=n<<16|65535&r,U=(a=(A>>>16)+(t>>>16)+((o=(65535&A)+(65535&t)+((n=(_>>>16)+(i>>>16)+((r=(65535&_)+(65535&i))>>>16))>>>16))>>>16))<<16|65535&o,S=n<<16|65535&r,th=(a=(q>>>16)+(v>>>16)+((o=(65535&q)+(65535&v)+((n=(G>>>16)+(B>>>16)+((r=(65535&G)+(65535&B))>>>16))>>>16))>>>16))<<16|65535&o,ih=n<<16|65535&r,t=((q=(a=(U>>>16)+(v>>>16)+((o=(65535&U)+(65535&v)+((n=(S>>>16)+(B>>>16)+((r=(65535&S)+(65535&B))>>>16))>>>16))>>>16))<<16|65535&o)>>>28|(G=n<<16|65535&r)<<4)^(G>>>2|q<<30)^(G>>>7|q<<25),i=(G>>>28|q<<4)^(q>>>2|G<<30)^(q>>>7|G<<25),s=(th>>>14|ih<<18)^(th>>>18|ih<<14)^(ih>>>9|th<<23),e=(ih>>>14|th<<18)^(ih>>>18|th<<14)^(th>>>9|ih<<23),A=(p=q&L)^q&M^c,_=(d=G&Q)^G&T^y,g=th&sh^~th&X,k=ih&eh^~ih&Z,v=F[h+4],B=F[h+5],v=(a=((U=u[h+4])>>>16)+(v>>>16)+(g>>>16)+(s>>>16)+($>>>16)+((o=(65535&U)+(65535&v)+(65535&g)+(65535&s)+(65535&$)+((n=((S=u[h+5])>>>16)+(B>>>16)+(k>>>16)+(e>>>16)+(hh>>>16)+((r=(65535&S)+(65535&B)+(65535&k)+(65535&e)+(65535&hh))>>>16))>>>16))>>>16))<<16|65535&o,B=n<<16|65535&r,U=(a=(A>>>16)+(t>>>16)+((o=(65535&A)+(65535&t)+((n=(_>>>16)+(i>>>16)+((r=(65535&_)+(65535&i))>>>16))>>>16))>>>16))<<16|65535&o,S=n<<16|65535&r,$=(a=(W>>>16)+(v>>>16)+((o=(65535&W)+(65535&v)+((n=(Y>>>16)+(B>>>16)+((r=(65535&Y)+(65535&B))>>>16))>>>16))>>>16))<<16|65535&o,hh=n<<16|65535&r,t=((W=(a=(U>>>16)+(v>>>16)+((o=(65535&U)+(65535&v)+((n=(S>>>16)+(B>>>16)+((r=(65535&S)+(65535&B))>>>16))>>>16))>>>16))<<16|65535&o)>>>28|(Y=n<<16|65535&r)<<4)^(Y>>>2|W<<30)^(Y>>>7|W<<25),i=(Y>>>28|W<<4)^(W>>>2|Y<<30)^(W>>>7|Y<<25),s=($>>>14|hh<<18)^($>>>18|hh<<14)^(hh>>>9|$<<23),e=(hh>>>14|$<<18)^(hh>>>18|$<<14)^($>>>9|hh<<23),A=(b=W&q)^W&L^p,_=(w=Y&G)^Y&Q^d,g=$&th^~$&sh,k=hh&ih^~hh&eh,v=F[h+6],B=F[h+7],v=(a=((U=u[h+6])>>>16)+(v>>>16)+(g>>>16)+(s>>>16)+(X>>>16)+((o=(65535&U)+(65535&v)+(65535&g)+(65535&s)+(65535&X)+((n=((S=u[h+7])>>>16)+(B>>>16)+(k>>>16)+(e>>>16)+(Z>>>16)+((r=(65535&S)+(65535&B)+(65535&k)+(65535&e)+(65535&Z))>>>16))>>>16))>>>16))<<16|65535&o,B=n<<16|65535&r,U=(a=(A>>>16)+(t>>>16)+((o=(65535&A)+(65535&t)+((n=(_>>>16)+(i>>>16)+((r=(65535&_)+(65535&i))>>>16))>>>16))>>>16))<<16|65535&o,S=n<<16|65535&r,X=(a=(M>>>16)+(v>>>16)+((o=(65535&M)+(65535&v)+((n=(T>>>16)+(B>>>16)+((r=(65535&T)+(65535&B))>>>16))>>>16))>>>16))<<16|65535&o,Z=n<<16|65535&r,M=(a=(U>>>16)+(v>>>16)+((o=(65535&U)+(65535&v)+((n=(S>>>16)+(B>>>16)+((r=(65535&S)+(65535&B))>>>16))>>>16))>>>16))<<16|65535&o,T=n<<16|65535&r;a=(z>>>16)+(M>>>16)+((o=(65535&z)+(65535&M)+((n=(E>>>16)+(T>>>16)+((r=(65535&E)+(65535&T))>>>16))>>>16))>>>16),this.h0h=a<<16|65535&o,this.h0l=n<<16|65535&r,a=(O>>>16)+(W>>>16)+((o=(65535&O)+(65535&W)+((n=(m>>>16)+(Y>>>16)+((r=(65535&m)+(65535&Y))>>>16))>>>16))>>>16),this.h1h=a<<16|65535&o,this.h1l=n<<16|65535&r,a=(x>>>16)+(q>>>16)+((o=(65535&x)+(65535&q)+((n=(N>>>16)+(G>>>16)+((r=(65535&N)+(65535&G))>>>16))>>>16))>>>16),this.h2h=a<<16|65535&o,this.h2l=n<<16|65535&r,a=(j>>>16)+(L>>>16)+((o=(65535&j)+(65535&L)+((n=(J>>>16)+(Q>>>16)+((r=(65535&J)+(65535&Q))>>>16))>>>16))>>>16),this.h3h=a<<16|65535&o,this.h3l=n<<16|65535&r,a=(H>>>16)+(X>>>16)+((o=(65535&H)+(65535&X)+((n=(I>>>16)+(Z>>>16)+((r=(65535&I)+(65535&Z))>>>16))>>>16))>>>16),this.h4h=a<<16|65535&o,this.h4l=n<<16|65535&r,a=(R>>>16)+($>>>16)+((o=(65535&R)+(65535&$)+((n=(V>>>16)+(hh>>>16)+((r=(65535&V)+(65535&hh))>>>16))>>>16))>>>16),this.h5h=a<<16|65535&o,this.h5l=n<<16|65535&r,a=(C>>>16)+(th>>>16)+((o=(65535&C)+(65535&th)+((n=(K>>>16)+(ih>>>16)+((r=(65535&K)+(65535&ih))>>>16))>>>16))>>>16),this.h6h=a<<16|65535&o,this.h6l=n<<16|65535&r,a=(P>>>16)+(sh>>>16)+((o=(65535&P)+(65535&sh)+((n=(D>>>16)+(eh>>>16)+((r=(65535&D)+(65535&eh))>>>16))>>>16))>>>16),this.h7h=a<<16|65535&o,this.h7l=n<<16|65535&r},h.prototype.hex=function(){this.finalize();var h=this.h0h,t=this.h0l,i=this.h1h,s=this.h1l,e=this.h2h,r=this.h2l,n=this.h3h,o=this.h3l,a=this.h4h,f=this.h4l,c=this.h5h,u=this.h5l,y=this.h6h,p=this.h6l,d=this.h7h,b=this.h7l,w=this.bits,A=l[h>>28&15]+l[h>>24&15]+l[h>>20&15]+l[h>>16&15]+l[h>>12&15]+l[h>>8&15]+l[h>>4&15]+l[15&h]+l[t>>28&15]+l[t>>24&15]+l[t>>20&15]+l[t>>16&15]+l[t>>12&15]+l[t>>8&15]+l[t>>4&15]+l[15&t]+l[i>>28&15]+l[i>>24&15]+l[i>>20&15]+l[i>>16&15]+l[i>>12&15]+l[i>>8&15]+l[i>>4&15]+l[15&i]+l[s>>28&15]+l[s>>24&15]+l[s>>20&15]+l[s>>16&15]+l[s>>12&15]+l[s>>8&15]+l[s>>4&15]+l[15&s]+l[e>>28&15]+l[e>>24&15]+l[e>>20&15]+l[e>>16&15]+l[e>>12&15]+l[e>>8&15]+l[e>>4&15]+l[15&e]+l[r>>28&15]+l[r>>24&15]+l[r>>20&15]+l[r>>16&15]+l[r>>12&15]+l[r>>8&15]+l[r>>4&15]+l[15&r]+l[n>>28&15]+l[n>>24&15]+l[n>>20&15]+l[n>>16&15]+l[n>>12&15]+l[n>>8&15]+l[n>>4&15]+l[15&n];return w>=256&&(A+=l[o>>28&15]+l[o>>24&15]+l[o>>20&15]+l[o>>16&15]+l[o>>12&15]+l[o>>8&15]+l[o>>4&15]+l[15&o]),w>=384&&(A+=l[a>>28&15]+l[a>>24&15]+l[a>>20&15]+l[a>>16&15]+l[a>>12&15]+l[a>>8&15]+l[a>>4&15]+l[15&a]+l[f>>28&15]+l[f>>24&15]+l[f>>20&15]+l[f>>16&15]+l[f>>12&15]+l[f>>8&15]+l[f>>4&15]+l[15&f]+l[c>>28&15]+l[c>>24&15]+l[c>>20&15]+l[c>>16&15]+l[c>>12&15]+l[c>>8&15]+l[c>>4&15]+l[15&c]+l[u>>28&15]+l[u>>24&15]+l[u>>20&15]+l[u>>16&15]+l[u>>12&15]+l[u>>8&15]+l[u>>4&15]+l[15&u]),512==w&&(A+=l[y>>28&15]+l[y>>24&15]+l[y>>20&15]+l[y>>16&15]+l[y>>12&15]+l[y>>8&15]+l[y>>4&15]+l[15&y]+l[p>>28&15]+l[p>>24&15]+l[p>>20&15]+l[p>>16&15]+l[p>>12&15]+l[p>>8&15]+l[p>>4&15]+l[15&p]+l[d>>28&15]+l[d>>24&15]+l[d>>20&15]+l[d>>16&15]+l[d>>12&15]+l[d>>8&15]+l[d>>4&15]+l[15&d]+l[b>>28&15]+l[b>>24&15]+l[b>>20&15]+l[b>>16&15]+l[b>>12&15]+l[b>>8&15]+l[b>>4&15]+l[15&b]),A},h.prototype.toString=h.prototype.hex,h.prototype.digest=function(){this.finalize();var h=this.h0h,t=this.h0l,i=this.h1h,s=this.h1l,e=this.h2h,r=this.h2l,n=this.h3h,o=this.h3l,a=this.h4h,l=this.h4l,f=this.h5h,c=this.h5l,u=this.h6h,y=this.h6l,p=this.h7h,d=this.h7l,b=this.bits,w=[h>>24&255,h>>16&255,h>>8&255,255&h,t>>24&255,t>>16&255,t>>8&255,255&t,i>>24&255,i>>16&255,i>>8&255,255&i,s>>24&255,s>>16&255,s>>8&255,255&s,e>>24&255,e>>16&255,e>>8&255,255&e,r>>24&255,r>>16&255,r>>8&255,255&r,n>>24&255,n>>16&255,n>>8&255,255&n];return b>=256&&w.push(o>>24&255,o>>16&255,o>>8&255,255&o),b>=384&&w.push(a>>24&255,a>>16&255,a>>8&255,255&a,l>>24&255,l>>16&255,l>>8&255,255&l,f>>24&255,f>>16&255,f>>8&255,255&f,c>>24&255,c>>16&255,c>>8&255,255&c),512==b&&w.push(u>>24&255,u>>16&255,u>>8&255,255&u,y>>24&255,y>>16&255,y>>8&255,255&y,p>>24&255,p>>16&255,p>>8&255,255&p,d>>24&255,d>>16&255,d>>8&255,255&d),w},h.prototype.array=h.prototype.digest,h.prototype.arrayBuffer=function(){this.finalize();var h=this.bits,t=new ArrayBuffer(h/8),i=new DataView(t);return i.setUint32(0,this.h0h),i.setUint32(4,this.h0l),i.setUint32(8,this.h1h),i.setUint32(12,this.h1l),i.setUint32(16,this.h2h),i.setUint32(20,this.h2l),i.setUint32(24,this.h3h),h>=256&&i.setUint32(28,this.h3l),h>=384&&(i.setUint32(32,this.h4h),i.setUint32(36,this.h4l),i.setUint32(40,this.h5h),i.setUint32(44,this.h5l)),512==h&&(i.setUint32(48,this.h6h),i.setUint32(52,this.h6l),i.setUint32(56,this.h7h),i.setUint32(60,this.h7l)),t},h.prototype.clone=function(){var t=new h(this.bits,!1);return this.copyTo(t),t},h.prototype.copyTo=function(h){var t=0,i=["h0h","h0l","h1h","h1l","h2h","h2l","h3h","h3l","h4h","h4l","h5h","h5l","h6h","h6l","h7h","h7l","start","bytes","hBytes","finalized","hashed","lastByteIndex"];for(t=0;t .nav-link { 22 | color: #fff; 23 | background-color: #1b6ec2; 24 | border-color: #1861ac; 25 | } 26 | 27 | /* Sticky footer styles 28 | -------------------------------------------------- */ 29 | html { 30 | font-size: 14px; 31 | } 32 | @media (min-width: 768px) { 33 | html { 34 | font-size: 16px; 35 | } 36 | } 37 | 38 | .border-top { 39 | border-top: 1px solid #e5e5e5; 40 | } 41 | .border-bottom { 42 | border-bottom: 1px solid #e5e5e5; 43 | } 44 | 45 | .box-shadow { 46 | box-shadow: 0 .25rem .75rem rgba(0, 0, 0, .05); 47 | } 48 | 49 | button.accept-policy { 50 | font-size: 1rem; 51 | line-height: inherit; 52 | } 53 | 54 | /* Sticky footer styles 55 | -------------------------------------------------- */ 56 | html { 57 | position: relative; 58 | min-height: 100%; 59 | } 60 | 61 | body { 62 | /* Margin bottom by footer height */ 63 | margin-bottom: 60px; 64 | } 65 | .footer { 66 | position: absolute; 67 | bottom: 0; 68 | width: 100%; 69 | white-space: nowrap; 70 | line-height: 60px; /* Vertically center the text there */ 71 | } 72 | -------------------------------------------------------------------------------- /WebSecure/wwwroot/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/saineshwar/WebSecure/85a1749464c547444b1c942fc0902a6fa15479c7/WebSecure/wwwroot/favicon.ico -------------------------------------------------------------------------------- /WebSecure/wwwroot/js/site.js: -------------------------------------------------------------------------------- 1 | // Please see documentation at https://docs.microsoft.com/aspnet/core/client-side/bundling-and-minification 2 | // for details on configuring this project to bundle and minify static web assets. 3 | 4 | // Write your JavaScript code. 5 | -------------------------------------------------------------------------------- /WebSecure/wwwroot/lib/bootstrap/LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2011-2018 Twitter, Inc. 4 | Copyright (c) 2011-2018 The Bootstrap Authors 5 | 6 | Permission is hereby granted, free of charge, to any person obtaining a copy 7 | of this software and associated documentation files (the "Software"), to deal 8 | in the Software without restriction, including without limitation the rights 9 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | copies of the Software, and to permit persons to whom the Software is 11 | furnished to do so, subject to the following conditions: 12 | 13 | The above copyright notice and this permission notice shall be included in 14 | all copies or substantial portions of the Software. 15 | 16 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 22 | THE SOFTWARE. 23 | -------------------------------------------------------------------------------- /WebSecure/wwwroot/lib/bootstrap/dist/css/bootstrap-reboot.css: -------------------------------------------------------------------------------- 1 | /*! 2 | * Bootstrap Reboot v4.3.1 (https://getbootstrap.com/) 3 | * Copyright 2011-2019 The Bootstrap Authors 4 | * Copyright 2011-2019 Twitter, Inc. 5 | * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE) 6 | * Forked from Normalize.css, licensed MIT (https://github.com/necolas/normalize.css/blob/master/LICENSE.md) 7 | */ 8 | *, 9 | *::before, 10 | *::after { 11 | box-sizing: border-box; 12 | } 13 | 14 | html { 15 | font-family: sans-serif; 16 | line-height: 1.15; 17 | -webkit-text-size-adjust: 100%; 18 | -webkit-tap-highlight-color: rgba(0, 0, 0, 0); 19 | } 20 | 21 | article, aside, figcaption, figure, footer, header, hgroup, main, nav, section { 22 | display: block; 23 | } 24 | 25 | body { 26 | margin: 0; 27 | font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, "Noto Sans", sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol", "Noto Color Emoji"; 28 | font-size: 1rem; 29 | font-weight: 400; 30 | line-height: 1.5; 31 | color: #212529; 32 | text-align: left; 33 | background-color: #fff; 34 | } 35 | 36 | [tabindex="-1"]:focus { 37 | outline: 0 !important; 38 | } 39 | 40 | hr { 41 | box-sizing: content-box; 42 | height: 0; 43 | overflow: visible; 44 | } 45 | 46 | h1, h2, h3, h4, h5, h6 { 47 | margin-top: 0; 48 | margin-bottom: 0.5rem; 49 | } 50 | 51 | p { 52 | margin-top: 0; 53 | margin-bottom: 1rem; 54 | } 55 | 56 | abbr[title], 57 | abbr[data-original-title] { 58 | text-decoration: underline; 59 | -webkit-text-decoration: underline dotted; 60 | text-decoration: underline dotted; 61 | cursor: help; 62 | border-bottom: 0; 63 | -webkit-text-decoration-skip-ink: none; 64 | text-decoration-skip-ink: none; 65 | } 66 | 67 | address { 68 | margin-bottom: 1rem; 69 | font-style: normal; 70 | line-height: inherit; 71 | } 72 | 73 | ol, 74 | ul, 75 | dl { 76 | margin-top: 0; 77 | margin-bottom: 1rem; 78 | } 79 | 80 | ol ol, 81 | ul ul, 82 | ol ul, 83 | ul ol { 84 | margin-bottom: 0; 85 | } 86 | 87 | dt { 88 | font-weight: 700; 89 | } 90 | 91 | dd { 92 | margin-bottom: .5rem; 93 | margin-left: 0; 94 | } 95 | 96 | blockquote { 97 | margin: 0 0 1rem; 98 | } 99 | 100 | b, 101 | strong { 102 | font-weight: bolder; 103 | } 104 | 105 | small { 106 | font-size: 80%; 107 | } 108 | 109 | sub, 110 | sup { 111 | position: relative; 112 | font-size: 75%; 113 | line-height: 0; 114 | vertical-align: baseline; 115 | } 116 | 117 | sub { 118 | bottom: -.25em; 119 | } 120 | 121 | sup { 122 | top: -.5em; 123 | } 124 | 125 | a { 126 | color: #007bff; 127 | text-decoration: none; 128 | background-color: transparent; 129 | } 130 | 131 | a:hover { 132 | color: #0056b3; 133 | text-decoration: underline; 134 | } 135 | 136 | a:not([href]):not([tabindex]) { 137 | color: inherit; 138 | text-decoration: none; 139 | } 140 | 141 | a:not([href]):not([tabindex]):hover, a:not([href]):not([tabindex]):focus { 142 | color: inherit; 143 | text-decoration: none; 144 | } 145 | 146 | a:not([href]):not([tabindex]):focus { 147 | outline: 0; 148 | } 149 | 150 | pre, 151 | code, 152 | kbd, 153 | samp { 154 | font-family: SFMono-Regular, Menlo, Monaco, Consolas, "Liberation Mono", "Courier New", monospace; 155 | font-size: 1em; 156 | } 157 | 158 | pre { 159 | margin-top: 0; 160 | margin-bottom: 1rem; 161 | overflow: auto; 162 | } 163 | 164 | figure { 165 | margin: 0 0 1rem; 166 | } 167 | 168 | img { 169 | vertical-align: middle; 170 | border-style: none; 171 | } 172 | 173 | svg { 174 | overflow: hidden; 175 | vertical-align: middle; 176 | } 177 | 178 | table { 179 | border-collapse: collapse; 180 | } 181 | 182 | caption { 183 | padding-top: 0.75rem; 184 | padding-bottom: 0.75rem; 185 | color: #6c757d; 186 | text-align: left; 187 | caption-side: bottom; 188 | } 189 | 190 | th { 191 | text-align: inherit; 192 | } 193 | 194 | label { 195 | display: inline-block; 196 | margin-bottom: 0.5rem; 197 | } 198 | 199 | button { 200 | border-radius: 0; 201 | } 202 | 203 | button:focus { 204 | outline: 1px dotted; 205 | outline: 5px auto -webkit-focus-ring-color; 206 | } 207 | 208 | input, 209 | button, 210 | select, 211 | optgroup, 212 | textarea { 213 | margin: 0; 214 | font-family: inherit; 215 | font-size: inherit; 216 | line-height: inherit; 217 | } 218 | 219 | button, 220 | input { 221 | overflow: visible; 222 | } 223 | 224 | button, 225 | select { 226 | text-transform: none; 227 | } 228 | 229 | select { 230 | word-wrap: normal; 231 | } 232 | 233 | button, 234 | [type="button"], 235 | [type="reset"], 236 | [type="submit"] { 237 | -webkit-appearance: button; 238 | } 239 | 240 | button:not(:disabled), 241 | [type="button"]:not(:disabled), 242 | [type="reset"]:not(:disabled), 243 | [type="submit"]:not(:disabled) { 244 | cursor: pointer; 245 | } 246 | 247 | button::-moz-focus-inner, 248 | [type="button"]::-moz-focus-inner, 249 | [type="reset"]::-moz-focus-inner, 250 | [type="submit"]::-moz-focus-inner { 251 | padding: 0; 252 | border-style: none; 253 | } 254 | 255 | input[type="radio"], 256 | input[type="checkbox"] { 257 | box-sizing: border-box; 258 | padding: 0; 259 | } 260 | 261 | input[type="date"], 262 | input[type="time"], 263 | input[type="datetime-local"], 264 | input[type="month"] { 265 | -webkit-appearance: listbox; 266 | } 267 | 268 | textarea { 269 | overflow: auto; 270 | resize: vertical; 271 | } 272 | 273 | fieldset { 274 | min-width: 0; 275 | padding: 0; 276 | margin: 0; 277 | border: 0; 278 | } 279 | 280 | legend { 281 | display: block; 282 | width: 100%; 283 | max-width: 100%; 284 | padding: 0; 285 | margin-bottom: .5rem; 286 | font-size: 1.5rem; 287 | line-height: inherit; 288 | color: inherit; 289 | white-space: normal; 290 | } 291 | 292 | progress { 293 | vertical-align: baseline; 294 | } 295 | 296 | [type="number"]::-webkit-inner-spin-button, 297 | [type="number"]::-webkit-outer-spin-button { 298 | height: auto; 299 | } 300 | 301 | [type="search"] { 302 | outline-offset: -2px; 303 | -webkit-appearance: none; 304 | } 305 | 306 | [type="search"]::-webkit-search-decoration { 307 | -webkit-appearance: none; 308 | } 309 | 310 | ::-webkit-file-upload-button { 311 | font: inherit; 312 | -webkit-appearance: button; 313 | } 314 | 315 | output { 316 | display: inline-block; 317 | } 318 | 319 | summary { 320 | display: list-item; 321 | cursor: pointer; 322 | } 323 | 324 | template { 325 | display: none; 326 | } 327 | 328 | [hidden] { 329 | display: none !important; 330 | } 331 | /*# sourceMappingURL=bootstrap-reboot.css.map */ -------------------------------------------------------------------------------- /WebSecure/wwwroot/lib/bootstrap/dist/css/bootstrap-reboot.min.css: -------------------------------------------------------------------------------- 1 | /*! 2 | * Bootstrap Reboot v4.3.1 (https://getbootstrap.com/) 3 | * Copyright 2011-2019 The Bootstrap Authors 4 | * Copyright 2011-2019 Twitter, Inc. 5 | * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE) 6 | * Forked from Normalize.css, licensed MIT (https://github.com/necolas/normalize.css/blob/master/LICENSE.md) 7 | */*,::after,::before{box-sizing:border-box}html{font-family:sans-serif;line-height:1.15;-webkit-text-size-adjust:100%;-webkit-tap-highlight-color:transparent}article,aside,figcaption,figure,footer,header,hgroup,main,nav,section{display:block}body{margin:0;font-family:-apple-system,BlinkMacSystemFont,"Segoe UI",Roboto,"Helvetica Neue",Arial,"Noto Sans",sans-serif,"Apple Color Emoji","Segoe UI Emoji","Segoe UI Symbol","Noto Color Emoji";font-size:1rem;font-weight:400;line-height:1.5;color:#212529;text-align:left;background-color:#fff}[tabindex="-1"]:focus{outline:0!important}hr{box-sizing:content-box;height:0;overflow:visible}h1,h2,h3,h4,h5,h6{margin-top:0;margin-bottom:.5rem}p{margin-top:0;margin-bottom:1rem}abbr[data-original-title],abbr[title]{text-decoration:underline;-webkit-text-decoration:underline dotted;text-decoration:underline dotted;cursor:help;border-bottom:0;-webkit-text-decoration-skip-ink:none;text-decoration-skip-ink:none}address{margin-bottom:1rem;font-style:normal;line-height:inherit}dl,ol,ul{margin-top:0;margin-bottom:1rem}ol ol,ol ul,ul ol,ul ul{margin-bottom:0}dt{font-weight:700}dd{margin-bottom:.5rem;margin-left:0}blockquote{margin:0 0 1rem}b,strong{font-weight:bolder}small{font-size:80%}sub,sup{position:relative;font-size:75%;line-height:0;vertical-align:baseline}sub{bottom:-.25em}sup{top:-.5em}a{color:#007bff;text-decoration:none;background-color:transparent}a:hover{color:#0056b3;text-decoration:underline}a:not([href]):not([tabindex]){color:inherit;text-decoration:none}a:not([href]):not([tabindex]):focus,a:not([href]):not([tabindex]):hover{color:inherit;text-decoration:none}a:not([href]):not([tabindex]):focus{outline:0}code,kbd,pre,samp{font-family:SFMono-Regular,Menlo,Monaco,Consolas,"Liberation Mono","Courier New",monospace;font-size:1em}pre{margin-top:0;margin-bottom:1rem;overflow:auto}figure{margin:0 0 1rem}img{vertical-align:middle;border-style:none}svg{overflow:hidden;vertical-align:middle}table{border-collapse:collapse}caption{padding-top:.75rem;padding-bottom:.75rem;color:#6c757d;text-align:left;caption-side:bottom}th{text-align:inherit}label{display:inline-block;margin-bottom:.5rem}button{border-radius:0}button:focus{outline:1px dotted;outline:5px auto -webkit-focus-ring-color}button,input,optgroup,select,textarea{margin:0;font-family:inherit;font-size:inherit;line-height:inherit}button,input{overflow:visible}button,select{text-transform:none}select{word-wrap:normal}[type=button],[type=reset],[type=submit],button{-webkit-appearance:button}[type=button]:not(:disabled),[type=reset]:not(:disabled),[type=submit]:not(:disabled),button:not(:disabled){cursor:pointer}[type=button]::-moz-focus-inner,[type=reset]::-moz-focus-inner,[type=submit]::-moz-focus-inner,button::-moz-focus-inner{padding:0;border-style:none}input[type=checkbox],input[type=radio]{box-sizing:border-box;padding:0}input[type=date],input[type=datetime-local],input[type=month],input[type=time]{-webkit-appearance:listbox}textarea{overflow:auto;resize:vertical}fieldset{min-width:0;padding:0;margin:0;border:0}legend{display:block;width:100%;max-width:100%;padding:0;margin-bottom:.5rem;font-size:1.5rem;line-height:inherit;color:inherit;white-space:normal}progress{vertical-align:baseline}[type=number]::-webkit-inner-spin-button,[type=number]::-webkit-outer-spin-button{height:auto}[type=search]{outline-offset:-2px;-webkit-appearance:none}[type=search]::-webkit-search-decoration{-webkit-appearance:none}::-webkit-file-upload-button{font:inherit;-webkit-appearance:button}output{display:inline-block}summary{display:list-item;cursor:pointer}template{display:none}[hidden]{display:none!important} 8 | /*# sourceMappingURL=bootstrap-reboot.min.css.map */ -------------------------------------------------------------------------------- /WebSecure/wwwroot/lib/jquery-validation-unobtrusive/LICENSE.txt: -------------------------------------------------------------------------------- 1 | Copyright (c) .NET Foundation. All rights reserved. 2 | 3 | Licensed under the Apache License, Version 2.0 (the "License"); you may not use 4 | these files except in compliance with the License. You may obtain a copy of the 5 | License at 6 | 7 | http://www.apache.org/licenses/LICENSE-2.0 8 | 9 | Unless required by applicable law or agreed to in writing, software distributed 10 | under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR 11 | CONDITIONS OF ANY KIND, either express or implied. See the License for the 12 | specific language governing permissions and limitations under the License. 13 | -------------------------------------------------------------------------------- /WebSecure/wwwroot/lib/jquery-validation-unobtrusive/jquery.validate.unobtrusive.js: -------------------------------------------------------------------------------- 1 | // Unobtrusive validation support library for jQuery and jQuery Validate 2 | // Copyright (c) .NET Foundation. All rights reserved. 3 | // Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. 4 | // @version v3.2.11 5 | 6 | /*jslint white: true, browser: true, onevar: true, undef: true, nomen: true, eqeqeq: true, plusplus: true, bitwise: true, regexp: true, newcap: true, immed: true, strict: false */ 7 | /*global document: false, jQuery: false */ 8 | 9 | (function (factory) { 10 | if (typeof define === 'function' && define.amd) { 11 | // AMD. Register as an anonymous module. 12 | define("jquery.validate.unobtrusive", ['jquery-validation'], factory); 13 | } else if (typeof module === 'object' && module.exports) { 14 | // CommonJS-like environments that support module.exports 15 | module.exports = factory(require('jquery-validation')); 16 | } else { 17 | // Browser global 18 | jQuery.validator.unobtrusive = factory(jQuery); 19 | } 20 | }(function ($) { 21 | var $jQval = $.validator, 22 | adapters, 23 | data_validation = "unobtrusiveValidation"; 24 | 25 | function setValidationValues(options, ruleName, value) { 26 | options.rules[ruleName] = value; 27 | if (options.message) { 28 | options.messages[ruleName] = options.message; 29 | } 30 | } 31 | 32 | function splitAndTrim(value) { 33 | return value.replace(/^\s+|\s+$/g, "").split(/\s*,\s*/g); 34 | } 35 | 36 | function escapeAttributeValue(value) { 37 | // As mentioned on http://api.jquery.com/category/selectors/ 38 | return value.replace(/([!"#$%&'()*+,./:;<=>?@\[\\\]^`{|}~])/g, "\\$1"); 39 | } 40 | 41 | function getModelPrefix(fieldName) { 42 | return fieldName.substr(0, fieldName.lastIndexOf(".") + 1); 43 | } 44 | 45 | function appendModelPrefix(value, prefix) { 46 | if (value.indexOf("*.") === 0) { 47 | value = value.replace("*.", prefix); 48 | } 49 | return value; 50 | } 51 | 52 | function onError(error, inputElement) { // 'this' is the form element 53 | var container = $(this).find("[data-valmsg-for='" + escapeAttributeValue(inputElement[0].name) + "']"), 54 | replaceAttrValue = container.attr("data-valmsg-replace"), 55 | replace = replaceAttrValue ? $.parseJSON(replaceAttrValue) !== false : null; 56 | 57 | container.removeClass("field-validation-valid").addClass("field-validation-error"); 58 | error.data("unobtrusiveContainer", container); 59 | 60 | if (replace) { 61 | container.empty(); 62 | error.removeClass("input-validation-error").appendTo(container); 63 | } 64 | else { 65 | error.hide(); 66 | } 67 | } 68 | 69 | function onErrors(event, validator) { // 'this' is the form element 70 | var container = $(this).find("[data-valmsg-summary=true]"), 71 | list = container.find("ul"); 72 | 73 | if (list && list.length && validator.errorList.length) { 74 | list.empty(); 75 | container.addClass("validation-summary-errors").removeClass("validation-summary-valid"); 76 | 77 | $.each(validator.errorList, function () { 78 | $("
  • ").html(this.message).appendTo(list); 79 | }); 80 | } 81 | } 82 | 83 | function onSuccess(error) { // 'this' is the form element 84 | var container = error.data("unobtrusiveContainer"); 85 | 86 | if (container) { 87 | var replaceAttrValue = container.attr("data-valmsg-replace"), 88 | replace = replaceAttrValue ? $.parseJSON(replaceAttrValue) : null; 89 | 90 | container.addClass("field-validation-valid").removeClass("field-validation-error"); 91 | error.removeData("unobtrusiveContainer"); 92 | 93 | if (replace) { 94 | container.empty(); 95 | } 96 | } 97 | } 98 | 99 | function onReset(event) { // 'this' is the form element 100 | var $form = $(this), 101 | key = '__jquery_unobtrusive_validation_form_reset'; 102 | if ($form.data(key)) { 103 | return; 104 | } 105 | // Set a flag that indicates we're currently resetting the form. 106 | $form.data(key, true); 107 | try { 108 | $form.data("validator").resetForm(); 109 | } finally { 110 | $form.removeData(key); 111 | } 112 | 113 | $form.find(".validation-summary-errors") 114 | .addClass("validation-summary-valid") 115 | .removeClass("validation-summary-errors"); 116 | $form.find(".field-validation-error") 117 | .addClass("field-validation-valid") 118 | .removeClass("field-validation-error") 119 | .removeData("unobtrusiveContainer") 120 | .find(">*") // If we were using valmsg-replace, get the underlying error 121 | .removeData("unobtrusiveContainer"); 122 | } 123 | 124 | function validationInfo(form) { 125 | var $form = $(form), 126 | result = $form.data(data_validation), 127 | onResetProxy = $.proxy(onReset, form), 128 | defaultOptions = $jQval.unobtrusive.options || {}, 129 | execInContext = function (name, args) { 130 | var func = defaultOptions[name]; 131 | func && $.isFunction(func) && func.apply(form, args); 132 | }; 133 | 134 | if (!result) { 135 | result = { 136 | options: { // options structure passed to jQuery Validate's validate() method 137 | errorClass: defaultOptions.errorClass || "input-validation-error", 138 | errorElement: defaultOptions.errorElement || "span", 139 | errorPlacement: function () { 140 | onError.apply(form, arguments); 141 | execInContext("errorPlacement", arguments); 142 | }, 143 | invalidHandler: function () { 144 | onErrors.apply(form, arguments); 145 | execInContext("invalidHandler", arguments); 146 | }, 147 | messages: {}, 148 | rules: {}, 149 | success: function () { 150 | onSuccess.apply(form, arguments); 151 | execInContext("success", arguments); 152 | } 153 | }, 154 | attachValidation: function () { 155 | $form 156 | .off("reset." + data_validation, onResetProxy) 157 | .on("reset." + data_validation, onResetProxy) 158 | .validate(this.options); 159 | }, 160 | validate: function () { // a validation function that is called by unobtrusive Ajax 161 | $form.validate(); 162 | return $form.valid(); 163 | } 164 | }; 165 | $form.data(data_validation, result); 166 | } 167 | 168 | return result; 169 | } 170 | 171 | $jQval.unobtrusive = { 172 | adapters: [], 173 | 174 | parseElement: function (element, skipAttach) { 175 | /// 176 | /// Parses a single HTML element for unobtrusive validation attributes. 177 | /// 178 | /// The HTML element to be parsed. 179 | /// [Optional] true to skip attaching the 180 | /// validation to the form. If parsing just this single element, you should specify true. 181 | /// If parsing several elements, you should specify false, and manually attach the validation 182 | /// to the form when you are finished. The default is false. 183 | var $element = $(element), 184 | form = $element.parents("form")[0], 185 | valInfo, rules, messages; 186 | 187 | if (!form) { // Cannot do client-side validation without a form 188 | return; 189 | } 190 | 191 | valInfo = validationInfo(form); 192 | valInfo.options.rules[element.name] = rules = {}; 193 | valInfo.options.messages[element.name] = messages = {}; 194 | 195 | $.each(this.adapters, function () { 196 | var prefix = "data-val-" + this.name, 197 | message = $element.attr(prefix), 198 | paramValues = {}; 199 | 200 | if (message !== undefined) { // Compare against undefined, because an empty message is legal (and falsy) 201 | prefix += "-"; 202 | 203 | $.each(this.params, function () { 204 | paramValues[this] = $element.attr(prefix + this); 205 | }); 206 | 207 | this.adapt({ 208 | element: element, 209 | form: form, 210 | message: message, 211 | params: paramValues, 212 | rules: rules, 213 | messages: messages 214 | }); 215 | } 216 | }); 217 | 218 | $.extend(rules, { "__dummy__": true }); 219 | 220 | if (!skipAttach) { 221 | valInfo.attachValidation(); 222 | } 223 | }, 224 | 225 | parse: function (selector) { 226 | /// 227 | /// Parses all the HTML elements in the specified selector. It looks for input elements decorated 228 | /// with the [data-val=true] attribute value and enables validation according to the data-val-* 229 | /// attribute values. 230 | /// 231 | /// Any valid jQuery selector. 232 | 233 | // $forms includes all forms in selector's DOM hierarchy (parent, children and self) that have at least one 234 | // element with data-val=true 235 | var $selector = $(selector), 236 | $forms = $selector.parents() 237 | .addBack() 238 | .filter("form") 239 | .add($selector.find("form")) 240 | .has("[data-val=true]"); 241 | 242 | $selector.find("[data-val=true]").each(function () { 243 | $jQval.unobtrusive.parseElement(this, true); 244 | }); 245 | 246 | $forms.each(function () { 247 | var info = validationInfo(this); 248 | if (info) { 249 | info.attachValidation(); 250 | } 251 | }); 252 | } 253 | }; 254 | 255 | adapters = $jQval.unobtrusive.adapters; 256 | 257 | adapters.add = function (adapterName, params, fn) { 258 | /// Adds a new adapter to convert unobtrusive HTML into a jQuery Validate validation. 259 | /// The name of the adapter to be added. This matches the name used 260 | /// in the data-val-nnnn HTML attribute (where nnnn is the adapter name). 261 | /// [Optional] An array of parameter names (strings) that will 262 | /// be extracted from the data-val-nnnn-mmmm HTML attributes (where nnnn is the adapter name, and 263 | /// mmmm is the parameter name). 264 | /// The function to call, which adapts the values from the HTML 265 | /// attributes into jQuery Validate rules and/or messages. 266 | /// 267 | if (!fn) { // Called with no params, just a function 268 | fn = params; 269 | params = []; 270 | } 271 | this.push({ name: adapterName, params: params, adapt: fn }); 272 | return this; 273 | }; 274 | 275 | adapters.addBool = function (adapterName, ruleName) { 276 | /// Adds a new adapter to convert unobtrusive HTML into a jQuery Validate validation, where 277 | /// the jQuery Validate validation rule has no parameter values. 278 | /// The name of the adapter to be added. This matches the name used 279 | /// in the data-val-nnnn HTML attribute (where nnnn is the adapter name). 280 | /// [Optional] The name of the jQuery Validate rule. If not provided, the value 281 | /// of adapterName will be used instead. 282 | /// 283 | return this.add(adapterName, function (options) { 284 | setValidationValues(options, ruleName || adapterName, true); 285 | }); 286 | }; 287 | 288 | adapters.addMinMax = function (adapterName, minRuleName, maxRuleName, minMaxRuleName, minAttribute, maxAttribute) { 289 | /// Adds a new adapter to convert unobtrusive HTML into a jQuery Validate validation, where 290 | /// the jQuery Validate validation has three potential rules (one for min-only, one for max-only, and 291 | /// one for min-and-max). The HTML parameters are expected to be named -min and -max. 292 | /// The name of the adapter to be added. This matches the name used 293 | /// in the data-val-nnnn HTML attribute (where nnnn is the adapter name). 294 | /// The name of the jQuery Validate rule to be used when you only 295 | /// have a minimum value. 296 | /// The name of the jQuery Validate rule to be used when you only 297 | /// have a maximum value. 298 | /// The name of the jQuery Validate rule to be used when you 299 | /// have both a minimum and maximum value. 300 | /// [Optional] The name of the HTML attribute that 301 | /// contains the minimum value. The default is "min". 302 | /// [Optional] The name of the HTML attribute that 303 | /// contains the maximum value. The default is "max". 304 | /// 305 | return this.add(adapterName, [minAttribute || "min", maxAttribute || "max"], function (options) { 306 | var min = options.params.min, 307 | max = options.params.max; 308 | 309 | if (min && max) { 310 | setValidationValues(options, minMaxRuleName, [min, max]); 311 | } 312 | else if (min) { 313 | setValidationValues(options, minRuleName, min); 314 | } 315 | else if (max) { 316 | setValidationValues(options, maxRuleName, max); 317 | } 318 | }); 319 | }; 320 | 321 | adapters.addSingleVal = function (adapterName, attribute, ruleName) { 322 | /// Adds a new adapter to convert unobtrusive HTML into a jQuery Validate validation, where 323 | /// the jQuery Validate validation rule has a single value. 324 | /// The name of the adapter to be added. This matches the name used 325 | /// in the data-val-nnnn HTML attribute(where nnnn is the adapter name). 326 | /// [Optional] The name of the HTML attribute that contains the value. 327 | /// The default is "val". 328 | /// [Optional] The name of the jQuery Validate rule. If not provided, the value 329 | /// of adapterName will be used instead. 330 | /// 331 | return this.add(adapterName, [attribute || "val"], function (options) { 332 | setValidationValues(options, ruleName || adapterName, options.params[attribute]); 333 | }); 334 | }; 335 | 336 | $jQval.addMethod("__dummy__", function (value, element, params) { 337 | return true; 338 | }); 339 | 340 | $jQval.addMethod("regex", function (value, element, params) { 341 | var match; 342 | if (this.optional(element)) { 343 | return true; 344 | } 345 | 346 | match = new RegExp(params).exec(value); 347 | return (match && (match.index === 0) && (match[0].length === value.length)); 348 | }); 349 | 350 | $jQval.addMethod("nonalphamin", function (value, element, nonalphamin) { 351 | var match; 352 | if (nonalphamin) { 353 | match = value.match(/\W/g); 354 | match = match && match.length >= nonalphamin; 355 | } 356 | return match; 357 | }); 358 | 359 | if ($jQval.methods.extension) { 360 | adapters.addSingleVal("accept", "mimtype"); 361 | adapters.addSingleVal("extension", "extension"); 362 | } else { 363 | // for backward compatibility, when the 'extension' validation method does not exist, such as with versions 364 | // of JQuery Validation plugin prior to 1.10, we should use the 'accept' method for 365 | // validating the extension, and ignore mime-type validations as they are not supported. 366 | adapters.addSingleVal("extension", "extension", "accept"); 367 | } 368 | 369 | adapters.addSingleVal("regex", "pattern"); 370 | adapters.addBool("creditcard").addBool("date").addBool("digits").addBool("email").addBool("number").addBool("url"); 371 | adapters.addMinMax("length", "minlength", "maxlength", "rangelength").addMinMax("range", "min", "max", "range"); 372 | adapters.addMinMax("minlength", "minlength").addMinMax("maxlength", "minlength", "maxlength"); 373 | adapters.add("equalto", ["other"], function (options) { 374 | var prefix = getModelPrefix(options.element.name), 375 | other = options.params.other, 376 | fullOtherName = appendModelPrefix(other, prefix), 377 | element = $(options.form).find(":input").filter("[name='" + escapeAttributeValue(fullOtherName) + "']")[0]; 378 | 379 | setValidationValues(options, "equalTo", element); 380 | }); 381 | adapters.add("required", function (options) { 382 | // jQuery Validate equates "required" with "mandatory" for checkbox elements 383 | if (options.element.tagName.toUpperCase() !== "INPUT" || options.element.type.toUpperCase() !== "CHECKBOX") { 384 | setValidationValues(options, "required", true); 385 | } 386 | }); 387 | adapters.add("remote", ["url", "type", "additionalfields"], function (options) { 388 | var value = { 389 | url: options.params.url, 390 | type: options.params.type || "GET", 391 | data: {} 392 | }, 393 | prefix = getModelPrefix(options.element.name); 394 | 395 | $.each(splitAndTrim(options.params.additionalfields || options.element.name), function (i, fieldName) { 396 | var paramName = appendModelPrefix(fieldName, prefix); 397 | value.data[paramName] = function () { 398 | var field = $(options.form).find(":input").filter("[name='" + escapeAttributeValue(paramName) + "']"); 399 | // For checkboxes and radio buttons, only pick up values from checked fields. 400 | if (field.is(":checkbox")) { 401 | return field.filter(":checked").val() || field.filter(":hidden").val() || ''; 402 | } 403 | else if (field.is(":radio")) { 404 | return field.filter(":checked").val() || ''; 405 | } 406 | return field.val(); 407 | }; 408 | }); 409 | 410 | setValidationValues(options, "remote", value); 411 | }); 412 | adapters.add("password", ["min", "nonalphamin", "regex"], function (options) { 413 | if (options.params.min) { 414 | setValidationValues(options, "minlength", options.params.min); 415 | } 416 | if (options.params.nonalphamin) { 417 | setValidationValues(options, "nonalphamin", options.params.nonalphamin); 418 | } 419 | if (options.params.regex) { 420 | setValidationValues(options, "regex", options.params.regex); 421 | } 422 | }); 423 | adapters.add("fileextensions", ["extensions"], function (options) { 424 | setValidationValues(options, "extension", options.params.extensions); 425 | }); 426 | 427 | $(function () { 428 | $jQval.unobtrusive.parse(document); 429 | }); 430 | 431 | return $jQval.unobtrusive; 432 | })); 433 | -------------------------------------------------------------------------------- /WebSecure/wwwroot/lib/jquery-validation-unobtrusive/jquery.validate.unobtrusive.min.js: -------------------------------------------------------------------------------- 1 | // Unobtrusive validation support library for jQuery and jQuery Validate 2 | // Copyright (c) .NET Foundation. All rights reserved. 3 | // Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. 4 | // @version v3.2.11 5 | !function(a){"function"==typeof define&&define.amd?define("jquery.validate.unobtrusive",["jquery-validation"],a):"object"==typeof module&&module.exports?module.exports=a(require("jquery-validation")):jQuery.validator.unobtrusive=a(jQuery)}(function(a){function e(a,e,n){a.rules[e]=n,a.message&&(a.messages[e]=a.message)}function n(a){return a.replace(/^\s+|\s+$/g,"").split(/\s*,\s*/g)}function t(a){return a.replace(/([!"#$%&'()*+,.\/:;<=>?@\[\\\]^`{|}~])/g,"\\$1")}function r(a){return a.substr(0,a.lastIndexOf(".")+1)}function i(a,e){return 0===a.indexOf("*.")&&(a=a.replace("*.",e)),a}function o(e,n){var r=a(this).find("[data-valmsg-for='"+t(n[0].name)+"']"),i=r.attr("data-valmsg-replace"),o=i?a.parseJSON(i)!==!1:null;r.removeClass("field-validation-valid").addClass("field-validation-error"),e.data("unobtrusiveContainer",r),o?(r.empty(),e.removeClass("input-validation-error").appendTo(r)):e.hide()}function d(e,n){var t=a(this).find("[data-valmsg-summary=true]"),r=t.find("ul");r&&r.length&&n.errorList.length&&(r.empty(),t.addClass("validation-summary-errors").removeClass("validation-summary-valid"),a.each(n.errorList,function(){a("
  • ").html(this.message).appendTo(r)}))}function s(e){var n=e.data("unobtrusiveContainer");if(n){var t=n.attr("data-valmsg-replace"),r=t?a.parseJSON(t):null;n.addClass("field-validation-valid").removeClass("field-validation-error"),e.removeData("unobtrusiveContainer"),r&&n.empty()}}function l(e){var n=a(this),t="__jquery_unobtrusive_validation_form_reset";if(!n.data(t)){n.data(t,!0);try{n.data("validator").resetForm()}finally{n.removeData(t)}n.find(".validation-summary-errors").addClass("validation-summary-valid").removeClass("validation-summary-errors"),n.find(".field-validation-error").addClass("field-validation-valid").removeClass("field-validation-error").removeData("unobtrusiveContainer").find(">*").removeData("unobtrusiveContainer")}}function u(e){var n=a(e),t=n.data(v),r=a.proxy(l,e),i=f.unobtrusive.options||{},u=function(n,t){var r=i[n];r&&a.isFunction(r)&&r.apply(e,t)};return t||(t={options:{errorClass:i.errorClass||"input-validation-error",errorElement:i.errorElement||"span",errorPlacement:function(){o.apply(e,arguments),u("errorPlacement",arguments)},invalidHandler:function(){d.apply(e,arguments),u("invalidHandler",arguments)},messages:{},rules:{},success:function(){s.apply(e,arguments),u("success",arguments)}},attachValidation:function(){n.off("reset."+v,r).on("reset."+v,r).validate(this.options)},validate:function(){return n.validate(),n.valid()}},n.data(v,t)),t}var m,f=a.validator,v="unobtrusiveValidation";return f.unobtrusive={adapters:[],parseElement:function(e,n){var t,r,i,o=a(e),d=o.parents("form")[0];d&&(t=u(d),t.options.rules[e.name]=r={},t.options.messages[e.name]=i={},a.each(this.adapters,function(){var n="data-val-"+this.name,t=o.attr(n),s={};void 0!==t&&(n+="-",a.each(this.params,function(){s[this]=o.attr(n+this)}),this.adapt({element:e,form:d,message:t,params:s,rules:r,messages:i}))}),a.extend(r,{__dummy__:!0}),n||t.attachValidation())},parse:function(e){var n=a(e),t=n.parents().addBack().filter("form").add(n.find("form")).has("[data-val=true]");n.find("[data-val=true]").each(function(){f.unobtrusive.parseElement(this,!0)}),t.each(function(){var a=u(this);a&&a.attachValidation()})}},m=f.unobtrusive.adapters,m.add=function(a,e,n){return n||(n=e,e=[]),this.push({name:a,params:e,adapt:n}),this},m.addBool=function(a,n){return this.add(a,function(t){e(t,n||a,!0)})},m.addMinMax=function(a,n,t,r,i,o){return this.add(a,[i||"min",o||"max"],function(a){var i=a.params.min,o=a.params.max;i&&o?e(a,r,[i,o]):i?e(a,n,i):o&&e(a,t,o)})},m.addSingleVal=function(a,n,t){return this.add(a,[n||"val"],function(r){e(r,t||a,r.params[n])})},f.addMethod("__dummy__",function(a,e,n){return!0}),f.addMethod("regex",function(a,e,n){var t;return!!this.optional(e)||(t=new RegExp(n).exec(a),t&&0===t.index&&t[0].length===a.length)}),f.addMethod("nonalphamin",function(a,e,n){var t;return n&&(t=a.match(/\W/g),t=t&&t.length>=n),t}),f.methods.extension?(m.addSingleVal("accept","mimtype"),m.addSingleVal("extension","extension")):m.addSingleVal("extension","extension","accept"),m.addSingleVal("regex","pattern"),m.addBool("creditcard").addBool("date").addBool("digits").addBool("email").addBool("number").addBool("url"),m.addMinMax("length","minlength","maxlength","rangelength").addMinMax("range","min","max","range"),m.addMinMax("minlength","minlength").addMinMax("maxlength","minlength","maxlength"),m.add("equalto",["other"],function(n){var o=r(n.element.name),d=n.params.other,s=i(d,o),l=a(n.form).find(":input").filter("[name='"+t(s)+"']")[0];e(n,"equalTo",l)}),m.add("required",function(a){"INPUT"===a.element.tagName.toUpperCase()&&"CHECKBOX"===a.element.type.toUpperCase()||e(a,"required",!0)}),m.add("remote",["url","type","additionalfields"],function(o){var d={url:o.params.url,type:o.params.type||"GET",data:{}},s=r(o.element.name);a.each(n(o.params.additionalfields||o.element.name),function(e,n){var r=i(n,s);d.data[r]=function(){var e=a(o.form).find(":input").filter("[name='"+t(r)+"']");return e.is(":checkbox")?e.filter(":checked").val()||e.filter(":hidden").val()||"":e.is(":radio")?e.filter(":checked").val()||"":e.val()}}),e(o,"remote",d)}),m.add("password",["min","nonalphamin","regex"],function(a){a.params.min&&e(a,"minlength",a.params.min),a.params.nonalphamin&&e(a,"nonalphamin",a.params.nonalphamin),a.params.regex&&e(a,"regex",a.params.regex)}),m.add("fileextensions",["extensions"],function(a){e(a,"extension",a.params.extensions)}),a(function(){f.unobtrusive.parse(document)}),f.unobtrusive}); -------------------------------------------------------------------------------- /WebSecure/wwwroot/lib/jquery-validation/LICENSE.md: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | ===================== 3 | 4 | Copyright Jörn Zaefferer 5 | 6 | Permission is hereby granted, free of charge, to any person obtaining a copy 7 | of this software and associated documentation files (the "Software"), to deal 8 | in the Software without restriction, including without limitation the rights 9 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | copies of the Software, and to permit persons to whom the Software is 11 | furnished to do so, subject to the following conditions: 12 | 13 | The above copyright notice and this permission notice shall be included in 14 | all copies or substantial portions of the Software. 15 | 16 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 22 | THE SOFTWARE. 23 | -------------------------------------------------------------------------------- /WebSecure/wwwroot/lib/jquery-validation/dist/additional-methods.min.js: -------------------------------------------------------------------------------- 1 | /*! jQuery Validation Plugin - v1.17.0 - 7/29/2017 2 | * https://jqueryvalidation.org/ 3 | * Copyright (c) 2017 Jörn Zaefferer; Licensed MIT */ 4 | !function(a){"function"==typeof define&&define.amd?define(["jquery","./jquery.validate.min"],a):"object"==typeof module&&module.exports?module.exports=a(require("jquery")):a(jQuery)}(function(a){return function(){function b(a){return a.replace(/<.[^<>]*?>/g," ").replace(/ | /gi," ").replace(/[.(),;:!?%#$'\"_+=\/\-“”’]*/g,"")}a.validator.addMethod("maxWords",function(a,c,d){return this.optional(c)||b(a).match(/\b\w+\b/g).length<=d},a.validator.format("Please enter {0} words or less.")),a.validator.addMethod("minWords",function(a,c,d){return this.optional(c)||b(a).match(/\b\w+\b/g).length>=d},a.validator.format("Please enter at least {0} words.")),a.validator.addMethod("rangeWords",function(a,c,d){var e=b(a),f=/\b\w+\b/g;return this.optional(c)||e.match(f).length>=d[0]&&e.match(f).length<=d[1]},a.validator.format("Please enter between {0} and {1} words."))}(),a.validator.addMethod("accept",function(b,c,d){var e,f,g,h="string"==typeof d?d.replace(/\s/g,""):"image/*",i=this.optional(c);if(i)return i;if("file"===a(c).attr("type")&&(h=h.replace(/[\-\[\]\/\{\}\(\)\+\?\.\\\^\$\|]/g,"\\$&").replace(/,/g,"|").replace(/\/\*/g,"/.*"),c.files&&c.files.length))for(g=new RegExp(".?("+h+")$","i"),e=0;e9?"0":f,g="JABCDEFGHI".substr(f,1).toString(),i.match(/[ABEH]/)?k===f:i.match(/[KPQS]/)?k===g:k===f||k===g},"Please specify a valid CIF number."),a.validator.addMethod("cpfBR",function(a){if(a=a.replace(/([~!@#$%^&*()_+=`{}\[\]\-|\\:;'<>,.\/? ])+/g,""),11!==a.length)return!1;var b,c,d,e,f=0;if(b=parseInt(a.substring(9,10),10),c=parseInt(a.substring(10,11),10),d=function(a,b){var c=10*a%11;return 10!==c&&11!==c||(c=0),c===b},""===a||"00000000000"===a||"11111111111"===a||"22222222222"===a||"33333333333"===a||"44444444444"===a||"55555555555"===a||"66666666666"===a||"77777777777"===a||"88888888888"===a||"99999999999"===a)return!1;for(e=1;e<=9;e++)f+=parseInt(a.substring(e-1,e),10)*(11-e);if(d(f,b)){for(f=0,e=1;e<=10;e++)f+=parseInt(a.substring(e-1,e),10)*(12-e);return d(f,c)}return!1},"Please specify a valid CPF number"),a.validator.addMethod("creditcard",function(a,b){if(this.optional(b))return"dependency-mismatch";if(/[^0-9 \-]+/.test(a))return!1;var c,d,e=0,f=0,g=!1;if(a=a.replace(/\D/g,""),a.length<13||a.length>19)return!1;for(c=a.length-1;c>=0;c--)d=a.charAt(c),f=parseInt(d,10),g&&(f*=2)>9&&(f-=9),e+=f,g=!g;return e%10===0},"Please enter a valid credit card number."),a.validator.addMethod("creditcardtypes",function(a,b,c){if(/[^0-9\-]+/.test(a))return!1;a=a.replace(/\D/g,"");var d=0;return c.mastercard&&(d|=1),c.visa&&(d|=2),c.amex&&(d|=4),c.dinersclub&&(d|=8),c.enroute&&(d|=16),c.discover&&(d|=32),c.jcb&&(d|=64),c.unknown&&(d|=128),c.all&&(d=255),1&d&&/^(5[12345])/.test(a)?16===a.length:2&d&&/^(4)/.test(a)?16===a.length:4&d&&/^(3[47])/.test(a)?15===a.length:8&d&&/^(3(0[012345]|[68]))/.test(a)?14===a.length:16&d&&/^(2(014|149))/.test(a)?15===a.length:32&d&&/^(6011)/.test(a)?16===a.length:64&d&&/^(3)/.test(a)?16===a.length:64&d&&/^(2131|1800)/.test(a)?15===a.length:!!(128&d)},"Please enter a valid credit card number."),a.validator.addMethod("currency",function(a,b,c){var d,e="string"==typeof c,f=e?c:c[0],g=!!e||c[1];return f=f.replace(/,/g,""),f=g?f+"]":f+"]?",d="^["+f+"([1-9]{1}[0-9]{0,2}(\\,[0-9]{3})*(\\.[0-9]{0,2})?|[1-9]{1}[0-9]{0,}(\\.[0-9]{0,2})?|0(\\.[0-9]{0,2})?|(\\.[0-9]{1,2})?)$",d=new RegExp(d),this.optional(b)||d.test(a)},"Please specify a valid currency"),a.validator.addMethod("dateFA",function(a,b){return this.optional(b)||/^[1-4]\d{3}\/((0?[1-6]\/((3[0-1])|([1-2][0-9])|(0?[1-9])))|((1[0-2]|(0?[7-9]))\/(30|([1-2][0-9])|(0?[1-9]))))$/.test(a)},a.validator.messages.date),a.validator.addMethod("dateITA",function(a,b){var c,d,e,f,g,h=!1,i=/^\d{1,2}\/\d{1,2}\/\d{4}$/;return i.test(a)?(c=a.split("/"),d=parseInt(c[0],10),e=parseInt(c[1],10),f=parseInt(c[2],10),g=new Date(Date.UTC(f,e-1,d,12,0,0,0)),h=g.getUTCFullYear()===f&&g.getUTCMonth()===e-1&&g.getUTCDate()===d):h=!1,this.optional(b)||h},a.validator.messages.date),a.validator.addMethod("dateNL",function(a,b){return this.optional(b)||/^(0?[1-9]|[12]\d|3[01])[\.\/\-](0?[1-9]|1[012])[\.\/\-]([12]\d)?(\d\d)$/.test(a)},a.validator.messages.date),a.validator.addMethod("extension",function(a,b,c){return c="string"==typeof c?c.replace(/,/g,"|"):"png|jpe?g|gif",this.optional(b)||a.match(new RegExp("\\.("+c+")$","i"))},a.validator.format("Please enter a value with a valid extension.")),a.validator.addMethod("giroaccountNL",function(a,b){return this.optional(b)||/^[0-9]{1,7}$/.test(a)},"Please specify a valid giro account number"),a.validator.addMethod("iban",function(a,b){if(this.optional(b))return!0;var c,d,e,f,g,h,i,j,k,l=a.replace(/ /g,"").toUpperCase(),m="",n=!0,o="",p="",q=5;if(l.length9&&a.match(/^(?:(?:(?:00\s?|\+)44\s?|0)7(?:[1345789]\d{2}|624)\s?\d{3}\s?\d{3})$/)},"Please specify a valid mobile number"),a.validator.addMethod("netmask",function(a,b){return this.optional(b)||/^(254|252|248|240|224|192|128)\.0\.0\.0|255\.(254|252|248|240|224|192|128|0)\.0\.0|255\.255\.(254|252|248|240|224|192|128|0)\.0|255\.255\.255\.(254|252|248|240|224|192|128|0)/i.test(a)},"Please enter a valid netmask."),a.validator.addMethod("nieES",function(a,b){"use strict";if(this.optional(b))return!0;var c,d=new RegExp(/^[MXYZ]{1}[0-9]{7,8}[TRWAGMYFPDXBNJZSQVHLCKET]{1}$/gi),e="TRWAGMYFPDXBNJZSQVHLCKET",f=a.substr(a.length-1).toUpperCase();return a=a.toString().toUpperCase(),!(a.length>10||a.length<9||!d.test(a))&&(a=a.replace(/^[X]/,"0").replace(/^[Y]/,"1").replace(/^[Z]/,"2"),c=9===a.length?a.substr(0,8):a.substr(0,9),e.charAt(parseInt(c,10)%23)===f)},"Please specify a valid NIE number."),a.validator.addMethod("nifES",function(a,b){"use strict";return!!this.optional(b)||(a=a.toUpperCase(),!!a.match("((^[A-Z]{1}[0-9]{7}[A-Z0-9]{1}$|^[T]{1}[A-Z0-9]{8}$)|^[0-9]{8}[A-Z]{1}$)")&&(/^[0-9]{8}[A-Z]{1}$/.test(a)?"TRWAGMYFPDXBNJZSQVHLCKE".charAt(a.substring(8,0)%23)===a.charAt(8):!!/^[KLM]{1}/.test(a)&&a[8]==="TRWAGMYFPDXBNJZSQVHLCKE".charAt(a.substring(8,1)%23)))},"Please specify a valid NIF number."),a.validator.addMethod("nipPL",function(a){"use strict";if(a=a.replace(/[^0-9]/g,""),10!==a.length)return!1;for(var b=[6,5,7,2,3,4,5,6,7],c=0,d=0;d<9;d++)c+=b[d]*a[d];var e=c%11,f=10===e?0:e;return f===parseInt(a[9],10)},"Please specify a valid NIP number."),a.validator.addMethod("notEqualTo",function(b,c,d){return this.optional(c)||!a.validator.methods.equalTo.call(this,b,c,d)},"Please enter a different value, values must not be the same."),a.validator.addMethod("nowhitespace",function(a,b){return this.optional(b)||/^\S+$/i.test(a)},"No white space please"),a.validator.addMethod("pattern",function(a,b,c){return!!this.optional(b)||("string"==typeof c&&(c=new RegExp("^(?:"+c+")$")),c.test(a))},"Invalid format."),a.validator.addMethod("phoneNL",function(a,b){return this.optional(b)||/^((\+|00(\s|\s?\-\s?)?)31(\s|\s?\-\s?)?(\(0\)[\-\s]?)?|0)[1-9]((\s|\s?\-\s?)?[0-9]){8}$/.test(a)},"Please specify a valid phone number."),a.validator.addMethod("phonesUK",function(a,b){return a=a.replace(/\(|\)|\s+|-/g,""),this.optional(b)||a.length>9&&a.match(/^(?:(?:(?:00\s?|\+)44\s?|0)(?:1\d{8,9}|[23]\d{9}|7(?:[1345789]\d{8}|624\d{6})))$/)},"Please specify a valid uk phone number"),a.validator.addMethod("phoneUK",function(a,b){return a=a.replace(/\(|\)|\s+|-/g,""),this.optional(b)||a.length>9&&a.match(/^(?:(?:(?:00\s?|\+)44\s?)|(?:\(?0))(?:\d{2}\)?\s?\d{4}\s?\d{4}|\d{3}\)?\s?\d{3}\s?\d{3,4}|\d{4}\)?\s?(?:\d{5}|\d{3}\s?\d{3})|\d{5}\)?\s?\d{4,5})$/)},"Please specify a valid phone number"),a.validator.addMethod("phoneUS",function(a,b){return a=a.replace(/\s+/g,""),this.optional(b)||a.length>9&&a.match(/^(\+?1-?)?(\([2-9]([02-9]\d|1[02-9])\)|[2-9]([02-9]\d|1[02-9]))-?[2-9]([02-9]\d|1[02-9])-?\d{4}$/)},"Please specify a valid phone number"),a.validator.addMethod("postalcodeBR",function(a,b){return this.optional(b)||/^\d{2}.\d{3}-\d{3}?$|^\d{5}-?\d{3}?$/.test(a)},"Informe um CEP válido."),a.validator.addMethod("postalCodeCA",function(a,b){return this.optional(b)||/^[ABCEGHJKLMNPRSTVXY]\d[ABCEGHJKLMNPRSTVWXYZ] *\d[ABCEGHJKLMNPRSTVWXYZ]\d$/i.test(a)},"Please specify a valid postal code"),a.validator.addMethod("postalcodeIT",function(a,b){return this.optional(b)||/^\d{5}$/.test(a)},"Please specify a valid postal code"),a.validator.addMethod("postalcodeNL",function(a,b){return this.optional(b)||/^[1-9][0-9]{3}\s?[a-zA-Z]{2}$/.test(a)},"Please specify a valid postal code"),a.validator.addMethod("postcodeUK",function(a,b){return this.optional(b)||/^((([A-PR-UWYZ][0-9])|([A-PR-UWYZ][0-9][0-9])|([A-PR-UWYZ][A-HK-Y][0-9])|([A-PR-UWYZ][A-HK-Y][0-9][0-9])|([A-PR-UWYZ][0-9][A-HJKSTUW])|([A-PR-UWYZ][A-HK-Y][0-9][ABEHMNPRVWXY]))\s?([0-9][ABD-HJLNP-UW-Z]{2})|(GIR)\s?(0AA))$/i.test(a)},"Please specify a valid UK postcode"),a.validator.addMethod("require_from_group",function(b,c,d){var e=a(d[1],c.form),f=e.eq(0),g=f.data("valid_req_grp")?f.data("valid_req_grp"):a.extend({},this),h=e.filter(function(){return g.elementValue(this)}).length>=d[0];return f.data("valid_req_grp",g),a(c).data("being_validated")||(e.data("being_validated",!0),e.each(function(){g.element(this)}),e.data("being_validated",!1)),h},a.validator.format("Please fill at least {0} of these fields.")),a.validator.addMethod("skip_or_fill_minimum",function(b,c,d){var e=a(d[1],c.form),f=e.eq(0),g=f.data("valid_skip")?f.data("valid_skip"):a.extend({},this),h=e.filter(function(){return g.elementValue(this)}).length,i=0===h||h>=d[0];return f.data("valid_skip",g),a(c).data("being_validated")||(e.data("being_validated",!0),e.each(function(){g.element(this)}),e.data("being_validated",!1)),i},a.validator.format("Please either skip these fields or fill at least {0} of them.")),a.validator.addMethod("stateUS",function(a,b,c){var d,e="undefined"==typeof c,f=!e&&"undefined"!=typeof c.caseSensitive&&c.caseSensitive,g=!e&&"undefined"!=typeof c.includeTerritories&&c.includeTerritories,h=!e&&"undefined"!=typeof c.includeMilitary&&c.includeMilitary;return d=g||h?g&&h?"^(A[AEKLPRSZ]|C[AOT]|D[CE]|FL|G[AU]|HI|I[ADLN]|K[SY]|LA|M[ADEINOPST]|N[CDEHJMVY]|O[HKR]|P[AR]|RI|S[CD]|T[NX]|UT|V[AIT]|W[AIVY])$":g?"^(A[KLRSZ]|C[AOT]|D[CE]|FL|G[AU]|HI|I[ADLN]|K[SY]|LA|M[ADEINOPST]|N[CDEHJMVY]|O[HKR]|P[AR]|RI|S[CD]|T[NX]|UT|V[AIT]|W[AIVY])$":"^(A[AEKLPRZ]|C[AOT]|D[CE]|FL|GA|HI|I[ADLN]|K[SY]|LA|M[ADEINOST]|N[CDEHJMVY]|O[HKR]|PA|RI|S[CD]|T[NX]|UT|V[AT]|W[AIVY])$":"^(A[KLRZ]|C[AOT]|D[CE]|FL|GA|HI|I[ADLN]|K[SY]|LA|M[ADEINOST]|N[CDEHJMVY]|O[HKR]|PA|RI|S[CD]|T[NX]|UT|V[AT]|W[AIVY])$",d=f?new RegExp(d):new RegExp(d,"i"),this.optional(b)||d.test(a)},"Please specify a valid state"),a.validator.addMethod("strippedminlength",function(b,c,d){return a(b).text().length>=d},a.validator.format("Please enter at least {0} characters")),a.validator.addMethod("time",function(a,b){return this.optional(b)||/^([01]\d|2[0-3]|[0-9])(:[0-5]\d){1,2}$/.test(a)},"Please enter a valid time, between 00:00 and 23:59"),a.validator.addMethod("time12h",function(a,b){return this.optional(b)||/^((0?[1-9]|1[012])(:[0-5]\d){1,2}(\ ?[AP]M))$/i.test(a)},"Please enter a valid time in 12-hour am/pm format"),a.validator.addMethod("url2",function(a,b){return this.optional(b)||/^(https?|ftp):\/\/(((([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(%[\da-f]{2})|[!\$&'\(\)\*\+,;=]|:)*@)?(((\d|[1-9]\d|1\d\d|2[0-4]\d|25[0-5])\.(\d|[1-9]\d|1\d\d|2[0-4]\d|25[0-5])\.(\d|[1-9]\d|1\d\d|2[0-4]\d|25[0-5])\.(\d|[1-9]\d|1\d\d|2[0-4]\d|25[0-5]))|((([a-z]|\d|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(([a-z]|\d|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])*([a-z]|\d|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])))\.)*(([a-z]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(([a-z]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])*([a-z]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])))\.?)(:\d*)?)(\/((([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(%[\da-f]{2})|[!\$&'\(\)\*\+,;=]|:|@)+(\/(([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(%[\da-f]{2})|[!\$&'\(\)\*\+,;=]|:|@)*)*)?)?(\?((([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(%[\da-f]{2})|[!\$&'\(\)\*\+,;=]|:|@)|[\uE000-\uF8FF]|\/|\?)*)?(#((([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(%[\da-f]{2})|[!\$&'\(\)\*\+,;=]|:|@)|\/|\?)*)?$/i.test(a)},a.validator.messages.url),a.validator.addMethod("vinUS",function(a){if(17!==a.length)return!1;var b,c,d,e,f,g,h=["A","B","C","D","E","F","G","H","J","K","L","M","N","P","R","S","T","U","V","W","X","Y","Z"],i=[1,2,3,4,5,6,7,8,1,2,3,4,5,7,9,2,3,4,5,6,7,8,9],j=[8,7,6,5,4,3,2,10,0,9,8,7,6,5,4,3,2],k=0;for(b=0;b<17;b++){if(e=j[b],d=a.slice(b,b+1),8===b&&(g=d),isNaN(d)){for(c=0;c