Lazarus または Delphi に関する質問です。Windows で信頼されたルート証明機関の証明書にプログラムでアクセスする方法はありますか。Windows に「mmc.exe」という GUI ベースのツールがあることは知っていますが、Object Pascal 構文を使用して証明書ファイル (.crt、.cer、.pem など) にアクセスする必要があります。誰でもそれで私を助けることができますか?
3 に答える
EldoS の SecureBlackBox を使用すると、ほぼすべてのことができます。 http://www.eldos.com/sbb/
このソフトウェアはそれを簡単にします。簡単ではない。
代わりに、ActiveX タイプ ライブラリとして簡単にインポートできるCAPICOMがありますが、単純な古い Windows Cryptography APIもあります。
例として、これは私の非常に古いテスト プロジェクトです (最近は試していません)。JEDIで利用できる関連する API 翻訳を含むWinCrypt
またはユニットが必要になります。JwaWinCrypt
program lstore;
{$APPTYPE CONSOLE}
uses
Windows,
SysUtils,
WinCrypt;
var
StoreName: array[0..255] of Char;
hStore: HCERTSTORE;
CertContext: PCertContext;
CertPropId: DWORD;
Data: array[0..511] of Char;
DataLen: DWORD;
i: Integer;
procedure DisplayCertContext(Cert: PCertContext);
var
CertName: array[0..255] of Char;
begin
if CertGetNameString(CertContext, CERT_NAME_EMAIL_TYPE, 0, nil,
CertName, 256) = 0 then
RaiseLastWin32Error;
Writeln('Subject CERT_NAME_EMAIL_TYPE: ', CertName);
if CertGetNameString(CertContext, CERT_NAME_SIMPLE_DISPLAY_TYPE, 0, nil,
CertName, 256) = 0 then
RaiseLastWin32Error;
Writeln('Subject CERT_NAME_SIMPLE_DISPLAY_TYPE: ', CertName);
if CertGetNameString(CertContext, CERT_NAME_FRIENDLY_DISPLAY_TYPE, 0, nil,
CertName, 256) = 0 then
RaiseLastWin32Error;
Writeln('Subject CERT_NAME_FRIENDLY_DISPLAY_TYPE: ', CertName);
if CertGetNameString(CertContext, CERT_NAME_EMAIL_TYPE, CERT_NAME_ISSUER_FLAG, nil,
CertName, 256) = 0 then
RaiseLastWin32Error;
Writeln('Issuer CERT_NAME_EMAIL_TYPE: ', CertName);
if CertGetNameString(CertContext, CERT_NAME_SIMPLE_DISPLAY_TYPE, CERT_NAME_ISSUER_FLAG, nil,
CertName, 256) = 0 then
RaiseLastWin32Error;
Writeln('Issuer CERT_NAME_SIMPLE_DISPLAY_TYPE: ', CertName);
if CertGetNameString(CertContext, CERT_NAME_FRIENDLY_DISPLAY_TYPE, CERT_NAME_ISSUER_FLAG, nil,
CertName, 256) = 0 then
RaiseLastWin32Error;
Writeln('Issuer CERT_NAME_FRIENDLY_DISPLAY_TYPE: ', CertName);
end;
begin
try
Write('Enter name of store to be listed: ');
Readln(StoreName);
hStore := CertOpenSystemStore(0, StoreName);
if hStore = nil then
RaiseLastWin32Error;
try
CertContext := CertEnumCertificatesInStore(hStore, nil);
while CertContext <> nil do
begin
DisplayCertContext(CertContext);
CertPropId := CertEnumCertificateContextProperties(CertContext, 0);
while CertPropId <> 0 do
begin
DataLen := 512;
// Writeln(Format('CertPropId: %d', [CertPropId]));
case CertPropId of
CERT_KEY_PROV_HANDLE_PROP_ID:
begin
CertGetCertificateContextProperty(CertContext, CertPropId,
@Data[0], DataLen);
Writeln(Format('KEY_PROV_HANDLE: $%.8x', [PDWORD(@Data[0])^]));
end;
CERT_KEY_PROV_INFO_PROP_ID:
begin
CertGetCertificateContextProperty(CertContext, CertPropId,
@Data[0], DataLen);
with PCryptKeyProvInfo(@Data[0])^ do
begin
Writeln(Format('pwszContainerName = %s', [pwszContainerName]));
Writeln(Format('pwszProvName = %s', [pwszProvName]));
Writeln(Format('dwFlags = %d', [dwFlags]));
Writeln(Format('cProvParams = %d', [cProvParams]));
//Writeln(Format('rgProvParam', [rgProvParam]));
Writeln(Format('dwKeySpec = %d', [dwKeySpec]));
end;
Writeln(Format('KEY_PROV_INFO: %d', [@Data[0]]));
end;
CERT_FRIENDLY_NAME_PROP_ID:
begin
CertGetCertificateContextProperty(CertContext, CertPropId,
@Data[0], DataLen);
Writeln(Format('FRIENDLY_NAME: %s', [PChar(@Data[0])]));
end;
CERT_KEY_IDENTIFIER_PROP_ID:
begin
CertGetCertificateContextProperty(CertContext, CertPropId,
@Data[0], DataLen);
Write('KEY_IDENTIFIER: ');
for i := 1 to DataLen do
Write(Format('%.2x ', [PBYTE(@Data[i - 1])^]));
Writeln;
end;
CERT_SHA1_HASH_PROP_ID:
begin
CertGetCertificateContextProperty(CertContext, CertPropId,
@Data[0], DataLen);
Write('SHA1_HASH: ');
for i := 1 to DataLen do
Write(Format('%.2x ', [PBYTE(@Data[i - 1])^]));
Writeln;
end;
CERT_MD5_HASH_PROP_ID:
begin
CertGetCertificateContextProperty(CertContext, CertPropId,
@Data[0], DataLen);
Write('MD5_HASH: ');
for i := 1 to DataLen do
Write(Format('%.2x ', [PBYTE(@Data[i - 1])^]));
Writeln;
end;
else
end;
CertPropId := CertEnumCertificateContextProperties(CertContext,
CertPropId);
end;
CertContext := CertEnumCertificatesInStore(hStore, CertContext);
end;
// if GetLastError <> CRYPT_E_NOT_FOUND then
// RaiseLastWin32Error;
finally
CertCloseStore(hStore, 0);
end;
except
on E: Exception do
begin
ExitCode := 1;
Writeln(Format('[%s] %s', [E.ClassName, E.Message]));
end;
end;
end.
Eldos SecureBlackBoxをお勧めしますが、無料の代替手段があります。
OpenSSL ライブラリを使用することもできます。Indy OpenSSL ヘッダーは不完全であるため、完全な OpenSSL ポートが必要です。また、含まれていないため、認証局からの公開証明書のデータベースをコンパイルする必要があります。
OpenSSL では、Windows 証明書ストアに直接アクセスできません。Windows または Firefox から証明書をエクスポートしてインポートできます。
Eldos SecureBlackBox は、プログラムのコード署名署名を検証する方法を含む、Windows 証明書ストアへのアクセスを提供します。
OpenSSL バイナリを Windows 製品に含めることができます。OpenSSL は既にインストールされており、Mac OS で使用できます。そのため、OpenSSL は FireMonkey または Lazarus で使用できます。
OpenSSL は十分に文書化されており、オンラインで多くの例を見つけることができますが、ほとんどが C または C++ で書かれています。私はそれで必要なものをすべて実装できて幸運でした。PEM ファイルを読み書きするための多くの関数があります。
SecureBlackBox にはまだ FireMonkey バージョンがありませんが、来年にはあると言っています (フォーラムによると)。fpc (フリー パスカル) バージョンがあります。