パスの\をエスケープするのが手間なので C#でいうとこの @"c:\temp\file.txt" に該当する機能ってなんだろうと調べてみたら
生文字列リテラルという名称のものがあるのね。
R"(c:\temp\file.txt)"
かっこで、かこうまでがセット。
SHA256を調べてみたらひとまず、OPENSSLインストールして・・・
のように、何かインストールしてといった話から始まるわけですが、
諸事情によりインストールを避けたいというのとWindows限定でしか使わないということから以下のコードにたどり着いた。
#include <stdio.h>
#include <windows.h>
#include <wincrypt.h>
int SHA256(BYTE* data, DWORD dataSize, BYTE* hash, DWORD* hashSize) {
int result = 0;
HCRYPTPROV hProv = 0;
HCRYPTHASH hHash = 0;
if (!CryptAcquireContext(&hProv, NULL, NULL, PROV_RSA_AES, CRYPT_VERIFYCONTEXT)){ goto LAST; }
if (!CryptCreateHash(hProv, CALG_SHA_256, 0, 0, &hHash)) { goto LAST; }
if (!CryptHashData(hHash, data, dataSize, 0)) { goto LAST; }
if (!CryptGetHashParam(hHash, HP_HASHVAL, hash, hashSize, 0)) { goto LAST; }
result = 1;
LAST:
if (hHash) { CryptDestroyHash(hHash); }
if (hProv) { CryptReleaseContext(hProv, 0); }
return result;
}
int main() {
const char* str = "Hello SHA256";
BYTE hash[32] = { 0 };
DWORD hashSize = sizeof(hash);
if (SHA256((BYTE*)str, strlen(str), hash, &hashSize)) {
for (DWORD i = 0; i < hashSize; i++) {
printf("%02x", hash[i]);
}
printf("\n");
}
return 0;
}
ただし、CryptHashData 関数 は、非推奨とのこと。
大事な この API は非推奨です。 新規および既存のソフトウェアでは 、暗号化次世代 API の 使用を開始する必要があります。Microsoft は、今後のリリースでこの API を削除する可能性があります。 CryptHashData 関数 (wincrypt.h)
70725d0f78cb0967c0e5171f733619712d239e28f2d279e4b3c3ed97f7456fa3
そんなわけで、書き換えるとこんな感じらしい。
#include <stdio.h>
#include <windows.h>
#include <bcrypt.h>
#include <ntstatus.h>
#include <vector>
#include <string.h>
#pragma comment(lib, "bcrypt.lib")
std::vector<BYTE> SHA256(const BYTE* data, DWORD dataSize)
{
BCRYPT_ALG_HANDLE hAlg = NULL;
BCRYPT_HASH_HANDLE hHash = NULL;
std::vector<BYTE> hash;
DWORD hashSize = 0, cbData = 0;
NTSTATUS status = STATUS_UNSUCCESSFUL;
do {
// アルゴリズムプロバイダーを開く
status = BCryptOpenAlgorithmProvider(&hAlg, BCRYPT_SHA256_ALGORITHM, NULL, 0);
if (!BCRYPT_SUCCESS(status)) break;
// ハッシュオブジェクトのサイズを取得
status = BCryptGetProperty(hAlg, BCRYPT_OBJECT_LENGTH, (PBYTE)&cbData, sizeof(DWORD), &hashSize, 0);
if (!BCRYPT_SUCCESS(status)) break;
// ハッシュオブジェクトを作成
std::vector<BYTE> hashObject(cbData);
status = BCryptCreateHash(hAlg, &hHash, hashObject.data(), (ULONG)hashObject.size(), NULL, 0, 0);
if (!BCRYPT_SUCCESS(status)) break;
// データをハッシュ化
status = BCryptHashData(hHash, (PBYTE)data, dataSize, 0);
if (!BCRYPT_SUCCESS(status)) break;
// ハッシュサイズを取得
status = BCryptGetProperty(hAlg, BCRYPT_HASH_LENGTH, (PBYTE)&hashSize, sizeof(DWORD), &cbData, 0);
if (!BCRYPT_SUCCESS(status)) break;
// 最終的なハッシュ値を取得
hash.resize(hashSize);
status = BCryptFinishHash(hHash, hash.data(), hashSize, 0);
if (!BCRYPT_SUCCESS(status)) hash.clear();
} while (false);
if (hHash) BCryptDestroyHash(hHash);
if (hAlg) BCryptCloseAlgorithmProvider(hAlg, 0);
return hash;
}
int main() {
const char* str = "Hello SHA256";
DWORD dataSize = strlen(str); // 正しい入力データサイズを使用
std::vector<BYTE> hash = SHA256((BYTE*)str, dataSize);
for (BYTE b : hash) {
printf("%02x", b);
}
printf("\n");
return 0;
}
gotoで最後にまとめて解放するコードにしていたら、初期化(std::vector
70725d0f78cb0967c0e5171f733619712d239e28f2d279e4b3c3ed97f7456fa3
該当のクラスデフォルトの説明あり
各説明とデフォルト値ですね
builder.Services.Configure<IdentityOptions>(options =>
{
// ロックアウトの設定
options.Lockout.DefaultLockoutTimeSpan = TimeSpan.FromMinutes(5); // ロックアウトの期間
options.Lockout.MaxFailedAccessAttempts = 5; // ロックアウトになる前の最大失敗試行回数
options.Lockout.AllowedForNewUsers = true; // 新しいユーザーに対してロックアウトを許可するかどうか
});
AllowedForNewUsersは、アカウント作ったあとの初回ログインでロックアウトを許容するかどうかという設定とのこと
作ったばかりなので間違える可能性を考慮してということだろうか。。
ただ、上記設定を利用するかどうかは、Loginする際のメソッドに渡す引数できまる
具体的には、以下のようにコントローラーのLoginのメソッドのところで、 PasswordSignInAsyncメソッドに渡すlockoutFailureがtrueだと
MaxFailedAccessAttemptsの回数に応じてロックアウトされる
using Microsoft.AspNetCore.Identity;
using Microsoft.AspNetCore.Mvc;
using SampleWeb.Models;
namespace SampleWeb.Controllers
{
public class AccountController : Controller
{
private readonly SignInManager<IdentityUser> _signInManager;
public AccountController(SignInManager<IdentityUser> signInManager)
{
_signInManager = signInManager;
}
public IActionResult Login()
{
return View();
}
[HttpPost]
public async Task<IActionResult> Login(LoginModel model)
{
if (ModelState.IsValid)
{
var result = await _signInManager.PasswordSignInAsync(model.Email, model.Password, model.RememberMe, lockoutOnFailure: true);
if (result.Succeeded)
{
return RedirectToAction("Index", "Home");
}
else
{
ModelState.AddModelError(string.Empty, "Invalid login attempt.");
}
}
return View(model);
}
}
}