는 다음과 같은 XMLDSig 프로 문서 SignedInfo에 가정을위한 RSA-SHA1 서명을 생성하기 위해 Windows 암호화 API를 사용하는 방법 :XMLDSIG
<SignedInfo xmlns="http://www.w3.org/2000/09/xmldsig#">
<CanonicalizationMethod Algorithm="http://www.w3.org/TR/2001/REC-xml-c14n-20010315"></CanonicalizationMethod>
<SignatureMethod Algorithm="http://www.w3.org/2000/09/xmldsig#rsa-sha1"></SignatureMethod>
<Reference URI="#object">
<DigestMethod Algorithm="http://www.w3.org/2000/09/xmldsig#sha1"></DigestMethod>
<DigestValue>OPnpF/ZNLDxJ/I+1F3iHhlmSwgo=</DigestValue>
</Reference>
</SignedInfo>
위의 SignedInfo에 노드의 SHA1이
5a c8 ef ab 04 5a 9a 46 fe 00 1a c5 8c 25 36 46 ff 88 dc 6a
가 발생하는 것입니다 Windows CryptoAPI의 SignatureValue에서 다음을 실행합니다.
var hProv: HCRYPTPROV;
hHash: HCRYPTHASH;
hKey: HCRYPTKEY;
s: string;
B, bSign: TBytes;
bPrefix, bPubKeyModulus, bExp: TBytes;
iFFLen, iPos, iSize, iHashSize: Cardinal;
PubKey: TRsaPubKey;
begin
s := '<SignedInfo xmlns="http://www.w3.org/2000/09/xmldsig#">' + #$0A +
' <CanonicalizationMethod Algorithm="http://www.w3.org/TR/2001/REC-xml-c14n-20010315"></CanonicalizationMethod>' + #$0A +
' <SignatureMethod Algorithm="http://www.w3.org/2000/09/xmldsig#rsa-sha1"></SignatureMethod>' + #$0A +
' <Reference URI="#object">' + #$0A +
' <DigestMethod Algorithm="http://www.w3.org/2000/09/xmldsig#sha1"></DigestMethod>' + #$0A +
' <DigestValue>OPnpF/ZNLDxJ/I+1F3iHhlmSwgo=</DigestValue>' + #$0A +
' </Reference>' + #$0A +
'</SignedInfo>';
B := TEncoding.ANSI.GetBytes(s);
{get context for crypt default provider}
Win32Check(CryptAcquireContext(hProv, nil, nil, PROV_RSA_FULL, CRYPT_VERIFYCONTEXT));
try
Win32Check(CryptGenKey(hProv, AT_SIGNATURE, RSA1024BIT_KEY or CRYPT_EXPORTABLE or ALG_SID_RSA_PKCS, hKey));
{create hash-object (SHA algorithm)}
Win32Check(CryptCreateHash(hProv, CALG_SHA1, 0, 0, hHash));
Win32Check(CryptHashData(hHash, @B[0], Length(B), 0));
// Obtain hash size
iSize := SizeOf(iSize);
SetLength(B, iSize);
Win32Check(CryptGetHashParam(hHash, HP_HASHSIZE, @B[0], iSize, 0));
Move(B[0], iSize, iSize);
// obtain hash value
SetLength(B, iSize);
Win32Check(CryptGetHashParam(hHash, HP_HASHVAL, @B[0], iSize, 0));
Print('Hex: ' + ToHex(B));
Print('Base64: ' + ToBase64(B));
// Signature of Hash
Win32Check(CryptSignHash(hHash, AT_SIGNATURE, nil, 0, nil, iSize));
SetLength(bSign, iSize);
Win32Check(CryptSignHash(hHash, AT_SIGNATURE, nil, 0, @bSign[0], iSize));
Print;
Print('Signature: ');
Print(ToBase64(Reverse(bSign)));
// Public key
Win32Check(CryptExportKey(hKey, 0, PUBLICKEYBLOB, 0, nil, iSize));
SetLength(B, iSize);
Win32Check(CryptExportKey(hKey, 0, PUBLICKEYBLOB, 0, @B[0], iSize));
Print;
Print('Public Key: ');
Print(ToHexASCII(B));
Move(B[SizeOf(TPublicKeyStruc)], PubKey, SizeOf(PubKey));
// Public key: Get Modulus
SetLength(bPubKeyModulus, PubKey.bitlen div 8);
Move(B[SizeOf(TPublicKeyStruc) + SizeOf(TRsaPubKey)], bPubKeyModulus[0], Length(bPubKeyModulus));
Print;
Print('Modulus: ');
Print(ToHex(bPubKeyModulus));
Print;
Print(ToBase64(bPubKeyModulus));
// Public key: Get Exponent
Print;
Print('Exponent: ');
Print(IntToStr(PubKey.pubexp));
SetLength(bExp, SizeOf(PubKey.pubexp));
Move(PubKey.pubexp, bExp[0], Length(bExp));
while bExp[Length(bExp) - 1] = 0 do
SetLength(bExp, Length(bExp) - 1);
Print('Base64: ' + ToBase64(bExp));
Print;
if CryptVerifySignature(hHash, @bSign[0], Length(bSign), hKey, nil, 0) then
Print('signature verified')
else
RaiseLastOSError;
Win32Check(CryptDestroyKey(hKey));
{destroy hash-object}
Win32Check(CryptDestroyHash(hHash));
finally
{release the context for crypt default provider}
Win32Check(CryptReleaseContext(hProv, 0));
end;
end;
서명을 생성하고 인증 할 수 있습니다. n CryptoAPI XMLDSig 사양에 따라 수행 중인지 확실하지 않습니다. http://www.aleksey.com/xmlsec/xmldsig-verifier.html
나는 다음과 같은 XMLDSig 프로 문서의 계수와 SignatureValue를 교체하고 온라인 검증과 확인 :
<?xml version="1.0" encoding="UTF-8"?>
<Signature xmlns="http://www.w3.org/2000/09/xmldsig#">
<SignedInfo xmlns="http://www.w3.org/2000/09/xmldsig#">
<CanonicalizationMethod Algorithm="http://www.w3.org/TR/2001/REC-xml-c14n-20010315"></CanonicalizationMethod>
<SignatureMethod Algorithm="http://www.w3.org/2000/09/xmldsig#rsa-sha1"></SignatureMethod>
<Reference URI="#object">
<DigestMethod Algorithm="http://www.w3.org/2000/09/xmldsig#sha1"></DigestMethod>
<DigestValue>OPnpF/ZNLDxJ/I+1F3iHhlmSwgo=</DigestValue>
</Reference>
</SignedInfo>
<SignatureValue>nihUFQg4mDhLgecvhIcKb9Gz8VRTOlw+adiZOBBXgK4JodEe5aFfCqm8WcRIT8GLLXSk8PsUP4//SsKqUBQkpotcAqQAhtz2v9kCWdoUDnAOtFZkd/CnsZ1sge0ndha40wWDV+nOWyJxkYgicvB8POYtSmldLLepPGMz+J7/Uws=</SignatureValue>
<KeyInfo>
<KeyValue>
<RSAKeyValue><Modulus>4IlzOY3Y9fXoh3Y5f06wBbtTg94Pt6vcfcd1KQ0FLm0S36aGJtTSb6pYKfyX7PqCUQ8wgL6xUJ5GRPEsu9gyz8ZobwfZsGCsvu40CWoT9fcFBZPfXro1Vtlh/xl/yYHm+Gzqh0Bw76xtLHSfLfpVOrmZdwKmSFKMTvNXOFd0V18=</Modulus><Exponent>AQAB</Exponent></RSAKeyValue>
</KeyValue>
</KeyInfo>
<Object xmlns="http://www.w3.org/2000/09/xmldsig#" Id="object">some text
with spaces and CR-LF.</Object>
</Signature>
내가 바로 그 일을하고있는 경우
더 확인하기 위해, 나는 온라인 검증을 시도
그리고 분명히 실패합니다.
나는 서명 값을 정확하게 생성하지 못했다고 생각합니다.