반응형
// 아래 예제는 "개인" 인증서 저장소에 설치된 모든 인증서를 찾아
// 인증서의 버전, 일련번호, 주체, 발급자, 유효 기간을 화면에 보여준다
// Wcrypt2는 http://stuff.irsoft.de/CryptoAPI2.zip 에서 다운받으면 된다
unit Unit1;
interface
uses
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
Dialogs, StdCtrls, Wcrypt2;
type
TForm1 = class(TForm)
Button1: TButton;
Memo1: TMemo;
procedure Button1Click(Sender: TObject);
private
{ Private declarations }
public
{ Public declarations }
end;
var
Form1: TForm1;
implementation
{$R *.dfm}
function GetLocalTime(a: TFileTime): String;
var
mtm: TSystemTime;
at: TFileTime;
ds,ts: ShortString;
begin
filetimetolocalfiletime(a,at);
filetimetosystemtime(at,mtm);
SetLength(ds, GetDateFormat(LOCALE_USER_DEFAULT, 0, @mtm, NIL, @ds[1], 255) - 1);
SetLength(ts, GetTimeFormat(LOCALE_USER_DEFAULT, time_noseconds, @mtm, NIL, @ts[1], 255) - 1);
Result := ds+' '+ts;
end;
procedure TForm1.Button1Click(Sender: TObject);
const
// 인증서 저장소=개인(MY)
StoreName = 'MY'; // MY, CA, ROOT 등 종류는 다양하다
// 발급 주체(Subject)의 Common Name(CN)
CN = 'www.howto.pe.kr';
// encoding 유형
MyEncType = PKCS_7_ASN_ENCODING or X509_ASN_ENCODING;
var
hCertStr: HCERTSTORE;
pCertCntx: PCCERT_CONTEXT;
pStoreName: PWideChar;
nameBLOB: CERT_NAME_BLOB;
nameString: PChar;
size: DWORD;
NotBefore, NotAfter: TFileTime;
serNum: PChar;
begin
Memo1.Clear;
// 모든 데이터는 null terminated Unicode 로 표현된다
// 아래의 일련의 명령어들은 아래의 한 문장으로 표현된다
// hCertStr := CertOpenSystemStore(0, 'MY');
GetMem(pStoreName, 2*Length(StoreName)+1);
StringToWideChar(StoreName, pStoreName, 2*Length(StoreName)+1);
try
hCertStr := CertOpenStore(CERT_STORE_PROV_SYSTEM,
0,
0,
CERT_STORE_READONLY_FLAG or CERT_SYSTEM_STORE_CURRENT_USER,
pStoreName);
finally
FreeMem(pStoreName, 2*Length(StoreName)+1);
end;
if hCertStr = nil then
begin
ShowMessage('"개인" 인증서 저장소를 열 수 없습니다');
Exit;
end;
try
nameString := StrAlloc(512);
pCertCntx := CertEnumCertificatesInStore(hCertStr, nil); // 첫번째 인증서
while pCertCntx <> nil do
begin
Memo1.Lines.Add('버전: '+IntToStr(pCertCntx^.pCertInfo^.dwVersion + 1)); // CERT_V3 = 2
serNum := PChar(pCertCntx^.pCertInfo^.SerialNumber.pbData);
Memo1.Lines.Add('일련번호: '+Format('%x%x', [pInt64(serNum+8)^, pInt64(serNum)^]));
nameBLOB := pCertCntx^.pCertInfo^.Subject;
size := CertNameToStr(MyEncType, @nameBlob, CERT_SIMPLE_NAME_STR, nameString, 512);
if size > 1 then
Memo1.Lines.Add('주체: '+nameString);
nameBLOB := pCertCntx^.pCertInfo^.Issuer;
size := CertNameToStr(MyEncType, @nameBlob, CERT_SIMPLE_NAME_STR, nameString, 512);
if size > 1 then
Memo1.Lines.Add('발급자: '+nameString);
NotBefore := pCertCntx^.pCertInfo^.notBefore;
NotAfter := pCertCntx^.pCertInfo^.notAfter;
Memo1.Lines.Add('유효 기간(시작): '+GetLocalTime(NotBefore));
Memo1.Lines.Add('유효 기간(끝): '+GetLocalTime(NotAfter));
Memo1.Lines.Add('');
pCertCntx := CertEnumCertificatesInStore(hCertStr, pCertCntx); // 다음 인증서
end;
finally
StrDispose(nameString);
CertFreeCertificateContext(pCertCntx);
CertCloseStore(hCertStr,0);
end;
end;
end.
반응형