• R/O
  • SSH
  • HTTPS

akdf: Commit


Commit MetaInfo

Revision526 (tree)
Time2020-11-07 06:30:22
Authorderekwildstar

Log Message

KRK.Rtl.Win.WinCrypt.pas
¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯

A função CryptGenKey foi corrigida
A função CryptGetUserKey foi corrigida
A constante CERT_SIGN_HASH_CNG_ALG_PROP_ID foi adicionada

KRK.Rtl.Win.WinCrypt.Utilities.pas
¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯

Iniciada a correção da função XMLSign considerando que o algoritmo de assinatura não pode ser livremente escolhido
A alteração ainda não foi concluída
GetKeyContainerInfo agora é GetCertificateKeyContainerInfo
Criada a função GetCertificateSignatureAlgorithm
Criada a função GetKeyPair
Criada a função DeleteKeySet
Removidas referências parametrizadas a <SignatureMethod> nos templates
Outros ajustes que não sei como descrever
Contém erros!

Change Summary

Incremental Difference

--- trunk/rtp/src/Rtl/Win/KRK.Rtl.Win.WinCrypt.Utilities.pas (revision 525)
+++ trunk/rtp/src/Rtl/Win/KRK.Rtl.Win.WinCrypt.Utilities.pas (revision 526)
@@ -97,7 +97,7 @@
9797
9898 TSignatureFormat = (sfNotSet, sfEnveloped, sfEnveloping);
9999 TDigestAlgorithm = (daNotSet, daSHA1, daSHA224, daSHA256, daSHA384, daSHA512);
100- TSignatureAlgorithm = (saNotSet, saDSASHA1, saDSASHA256, saRSASHA1, saRSASHA224, saRSASHA256, saRSASHA384, saRSASHA512, saECDSASHA1, saECDSASHA224, saECDSASHA256, saECDSASHA384, saECDSASHA512);
100+ TSignatureAlgorithm = (saNotSet, saRSASHA1, saFromCertificate);
101101
102102 TWriteKeyInfo = (wkiKeyValue = KEYVALUE, wkiCertificates = CERTIFICATES, wkiPurge = PURGE);
103103 TWriteKeyInfos = set of TWriteKeyInfo;
@@ -132,6 +132,8 @@
132132 Encoding: String;
133133 end;
134134
135+ TKeyPairType = (kptNotSet, kptKeyExchange, kptSignature);
136+
135137 //: Seleciona um certificado de acordo com os parâmetros especificados.
136138 //: Use esta função para retornar um contexto de certificado (PCCERT_CONTEXT) ou
137139 //: mostrar uma tela que lista os certificados disponíveis, dependendo da
@@ -235,13 +237,27 @@
235237 // no url a seguir, principalmente a parte que fala das funções que usam
236238 // CRYPT_KEY_PROV_INFO talvez elas sejam um atalho
237239 // https://docs.microsoft.com/en-us/windows/win32/api/wincrypt/ns-wincrypt-crypt_key_prov_info
238-function GetKeyContainerInfo(ACertificateContext: PCCERT_CONTEXT; out ACryptKeyProvInfo: PCryptKeyProvInfo): Boolean;
240+function GetCertificateKeyContainerInfo(ACertificateContext: PCCERT_CONTEXT; out ACryptKeyProvInfo: PCryptKeyProvInfo): Boolean;
241+//: Obtém o nome do algoritmo de assinatura do certificado.
242+function GetCertificateSignatureAlgorithm(ACertificateContext: PCCERT_CONTEXT): String;
239243 //: Assina um arquivo qualquer usando o formato XML, tal como especificado em
240244 //: https://www.w3.org/TR/xmldsig-core2/. Esta função requer que a biblioteca
241245 //: MSXML5 esteja registrada
242246 function XMLSign(const AParams: TXMLSignParams): TXMLSignReturn;
247+// Isso parece não usar MSXML5!!!
248+// https://docs.microsoft.com/en-us/windows/win32/seccrypto/cryptography-functions#cryptxml-functions
243249 function XMLVerifySign(const AParams: TXMLVerifySignParams; out AReturn: TXMLVerifySignReturn): Boolean;
244250
251+// Leia no site abaixo um exemplo de como obter uma chave de sessão e gerar seu hash, talvez seja possível criar chaves (senhas?) aleatorias, algo do que eu fiz manualmente no DefinedCrypt pde ser feito de forma mais sofisticada aqui
252+// https://docs.microsoft.com/en-us/windows/win32/seccrypto/example-c-program-creating-and-hashing-a-session-key
253+
254+// Obtém o par de chaves a partir do contêiner de chaves no provedor do tipo
255+// indicado. Caso não haja o contêiner o achave especificada, o contêiner será
256+// criado e/ou a chave especificada e assim um handle para essa chave será
257+// retornado. Esse handle precisa ser destruído com CryptDestroyKey
258+function GetKeyPair(AKeyContainerName: String; AProviderName: String; AProviderType: Word; AKeyPairType: TKeyPairType; AKeyPairCreationFlags: DWORD; out AKeyPair: HCRYPTKEY): Boolean;
259+procedure DeleteKeySet(AKeyContainerName: String; AProviderName: String; AProviderType: Cardinal);
260+
245261 implementation
246262
247263 uses
@@ -257,7 +273,7 @@
257273 '<Signature xmlns="http://www.w3.org/2000/09/xmldsig#">'#13#10 +
258274 ' <SignedInfo>'#13#10 +
259275 ' <CanonicalizationMethod Algorithm="http://www.w3.org/TR/2001/REC-xml-c14n-20010315" />'#13#10 +
260- ' <SignatureMethod Algorithm="<:SIGNATUREALGORITHM:>" />'#13#10 + //http://www.w3.org/2000/09/xmldsig#rsa-sha1
276+ ' <SignatureMethod />'#13#10 +
261277 ' <Reference URI="<:URI:>">'#13#10 +
262278 ' <Transforms>'#13#10 +
263279 ' <Transform Algorithm="http://www.w3.org/2000/09/xmldsig#enveloped-signature" />'#13#10 +
@@ -275,7 +291,7 @@
275291 '<Signature xmlns="http://www.w3.org/2000/09/xmldsig#">'#13#10 +
276292 ' <SignedInfo>'#13#10 +
277293 ' <CanonicalizationMethod Algorithm="http://www.w3.org/TR/2001/REC-xml-c14n-20010315" />'#13#10 +
278- ' <SignatureMethod Algorithm="<:SIGNATUREALGORITHM:>" />'#13#10 + //http://www.w3.org/2000/09/xmldsig#rsa-sha1
294+ ' <SignatureMethod />'#13#10 +
279295 ' <Reference URI="#<:URI:>">'#13#10 +
280296 ' <DigestMethod Algorithm="<:DIGESTALGORITHM:>" />'#13#10 + //http://www.w3.org/2000/09/xmldsig#sha1
281297 ' <DigestValue />'#13#10 +
@@ -678,6 +694,13 @@
678694 // Obtém o provedor a partir do contexto do certificado usado para
679695 // assinar. O nome da função é estranho e não parece indicar que ela
680696 // serve pra isso, mas foi pra isso que eu a usei, e deu certo.
697+
698+ // The CryptAcquireCertificatePrivateKey function obtains the private
699+ // key for a certificate. This function is used to obtain access to a
700+ // user's private key when the user's certificate is available, but
701+ // the handle of the user's key container is not available. This
702+ // function can only be used by the owner of a private key and not by
703+ // any other user.
681704 if not CryptAcquireCertificatePrivateKey(CertificateContext
682705 ,0
683706 ,nil
@@ -709,7 +732,7 @@
709732 // Retorna a chave em format BLOB (Little-Endian)
710733 if not CryptGetUserKey(CryptProviderHandle
711734 ,KeySpec
712- ,KeysHandle) then
735+ ,@KeysHandle) then
713736 raise EAdvApi.Create(GetLastError,'CryptGetUserKey@GetSignature: Não foi possível obter o handle para as chaves do CSP')
714737 else
715738 try
@@ -1826,40 +1849,65 @@
18261849 }
18271850 *)
18281851
1829-function GetKeyContainerInfo(ACertificateContext: PCCERT_CONTEXT; out ACryptKeyProvInfo: PCryptKeyProvInfo): Boolean;
1852+function GetCertificateKeyContainerInfo(ACertificateContext: PCCERT_CONTEXT; out ACryptKeyProvInfo: PCryptKeyProvInfo): Boolean;
18301853 var
1831- CryptKeyProvInfoSize: DWORD;
1854+ InfoSize: DWORD;
18321855 begin
18331856 Result := False;
18341857 ACryptKeyProvInfo := nil;
1835- CryptKeyProvInfoSize := 0;
1858+ InfoSize := 0;
18361859
18371860 if CertGetCertificateContextProperty(ACertificateContext
18381861 ,CERT_KEY_PROV_INFO_PROP_ID
18391862 ,nil
1840- ,@CryptKeyProvInfoSize) then
1863+ ,@InfoSize) then
18411864 begin
1842- ACryptKeyProvInfo := AllocMem(CryptKeyProvInfoSize);
1865+ ACryptKeyProvInfo := AllocMem(InfoSize);
18431866
18441867 if CertGetCertificateContextProperty(ACertificateContext
18451868 ,CERT_KEY_PROV_INFO_PROP_ID
18461869 ,ACryptKeyProvInfo
1847- ,@CryptKeyProvInfoSize) then
1870+ ,@InfoSize) then
18481871 Result := True;
18491872 end;
18501873 end;
18511874
1875+function GetCertificateSignatureAlgorithm(ACertificateContext: PCCERT_CONTEXT): String;
1876+var
1877+ InfoData: PChar;
1878+ InfoSize: DWORD;
1879+begin
1880+ Result := '';
1881+
1882+ if CertGetCertificateContextProperty(ACertificateContext
1883+ ,CERT_SIGN_HASH_CNG_ALG_PROP_ID
1884+ ,nil
1885+ ,@InfoSize) then
1886+ begin
1887+ GetMem(InfoData,InfoSize);
1888+ try
1889+ if CertGetCertificateContextProperty(ACertificateContext
1890+ ,CERT_SIGN_HASH_CNG_ALG_PROP_ID
1891+ ,InfoData
1892+ ,@InfoSize) then
1893+ begin
1894+ Result := InfoData;
1895+ end;
1896+ finally
1897+ FreeMem(InfoData);
1898+ end;
1899+ end;
1900+
1901+end;
1902+
18521903 function XMLSign(const AParams: TXMLSignParams): TXMLSignReturn;
18531904 var
18541905 PreparedTemplate: String;
18551906 SignatureTemplate: IXMLDOMDocument3;
18561907 InputXML: IXMLDOMDocument3;
1857- CertificateContext: PCCERT_CONTEXT;
1858- KeyContainerInfo: PCryptKeyProvInfo;
1859- XMLDigitalSignature: IXMLDigitalSignature; // No futuro, olhe XMLDigitalSignatureEx
1860- XMLDSigKey: IXMLDSigKey;
18611908 ContentsData: PByte;
18621909 ContentsSize: DWORD;
1910+ CertificateContext: PCCERT_CONTEXT;
18631911 // - ///////////////////////////////////////////////////////////////////////////
18641912 procedure PrepareTemplate(aTemplate: String);
18651913 var
@@ -1903,25 +1951,6 @@
19031951 else
19041952 raise Exception.Create('O formato da assinatura não foi especificado');
19051953
1906- case Aparams.SignatureAlgorithm of
1907- saDSASHA1: Aux := 'http://www.w3.org/2000/09/xmldsig#dsa-sha1';
1908- saDSASHA256: Aux := 'http://www.w3.org/2009/xmldsig11#dsa-sha256';
1909- saRSASHA1: Aux := 'http://www.w3.org/2000/09/xmldsig#rsa-sha1';
1910- saRSASHA224: Aux := 'http://www.w3.org/2001/04/xmldsig-more#rsa-sha224';
1911- saRSASHA256: Aux := 'http://www.w3.org/2001/04/xmldsig-more#rsa-sha256';
1912- saRSASHA384: Aux := 'http://www.w3.org/2001/04/xmldsig-more#rsa-sha384';
1913- saRSASHA512: Aux := 'http://www.w3.org/2001/04/xmldsig-more#rsa-sha512';
1914- saECDSASHA1: Aux := 'http://www.w3.org/2001/04/xmldsig-more#ecdsa-sha1';
1915- saECDSASHA224: Aux := 'http://www.w3.org/2001/04/xmldsig-more#ecdsa-sha224';
1916- saECDSASHA256: Aux := 'http://www.w3.org/2001/04/xmldsig-more#ecdsa-sha256';
1917- saECDSASHA384: Aux := 'http://www.w3.org/2001/04/xmldsig-more#ecdsa-sha384';
1918- saECDSASHA512: Aux := 'http://www.w3.org/2001/04/xmldsig-more#ecdsa-sha512';
1919- else
1920- raise Exception.Create('Não foi selecionado o algorítmo de hash da assinatura');
1921- end;
1922-
1923- PreparedTemplate := StringReplace(PreparedTemplate,'<:SIGNATUREALGORITHM:>',Aux,[rfReplaceAll]);
1924-
19251954 case AParams.DigestAlgorithm of
19261955 daSHA1: Aux := 'http://www.w3.org/2000/09/xmldsig#sha1';
19271956 daSHA224: Aux := 'http://www.w3.org/2001/04/xmldsig-more#sha224';
@@ -1994,7 +2023,7 @@
19942023
19952024 if Assigned(KeyInfo) then
19962025 begin
1997- X509Data := KeyInfo.selectSingleNode('X509Data');
2026+ X509Data := KeyInfo.selectSingleNode('ds:X509Data');
19982027 // A partir deste ponto nós filhos de <KeyInfo> serão selecionados,
19992028 // criados, adicionados e/ou complementados. Ao criar um novo nó, por
20002029 // padrão, o seu namespace é "em branco". Como <KeyInfo> está dentro de
@@ -2015,7 +2044,7 @@
20152044 if not Assigned(X509Data) then
20162045 X509Data := KeyInfo.appendChild(AXMLDocument.createNode(NODE_ELEMENT,'X509Data',SIGNATURENS));
20172046
2018- X509Certificate := X509Data.selectSingleNode('X509Certificate');
2047+ X509Certificate := X509Data.selectSingleNode('ds:X509Certificate');
20192048
20202049 if not Assigned(X509Certificate) then
20212050 begin
@@ -2049,6 +2078,10 @@
20492078 end;
20502079 end;
20512080 // - ///////////////////////////////////////////////////////////////////////////
2081+var
2082+ XMLDigitalSignature: IXMLDigitalSignatureEx;
2083+ XMLDSigKey: IXMLDSigKeyEx;
2084+ KPI: PCryptKeyProvInfo;
20522085 begin
20532086 ZeroMemory(@Result,SizeOf(TXMLSignReturn));
20542087 // Variável que vai conter o XML final, com o template aplicado + o conteúdo a
@@ -2149,35 +2182,73 @@
21492182 // <Signature>, usa-se "ds:Signature"
21502183 InputXML.setProperty('SelectionNamespaces', 'xmlns:ds="http://www.w3.org/2000/09/xmldsig#"');
21512184 // Seleciona um certificado de acordo com as opções informadas
2152- if SelectCertificate(AParams.SelectCertificateParams,CertificateContext) and GetKeyContainerInfo(CertificateContext,KeyContainerInfo) then
2153- try
2154- XMLDigitalSignature := CoMXDigitalSignature50.Create;
2155- XMLDigitalSignature.signature := InputXML.selectSingleNode('//ds:Signature');
2156- // Abaixo, createKeyFromCSP vai usar informações obtidas a partir do
2157- // certificado informado a fim de criar as chaves necessárias para a
2158- // assinatura, entretanto, a geração das chaves não precisa ser baseada no
2159- // certificado. createKeyFromCSP precisa receber em seu primeiro parâmetro
2160- // um tipo de CSP que apenas pode ser um, de dois valores possíveis:
2161- // PROV_DSS_DH (13) ou PROV_RSA_FULL (1). O segundo parâmetro desta função
2162- // precisa receber o nome de um CSP do tipo indicado no primeiro
2163- // parâmetro. Já o terceiro parâmetro precisa receber o nome de um
2164- // contêiner de chaves. Esse nome precisa ser um nome válido dentro do CSP
2165- // informado. Para obter os nomes de contêineres de chaves de um CSP use a
2166- // função GetProviderKeyContainerNames
2167- XMLDSigKey := XMLDigitalSignature.createKeyFromCSP(KeyContainerInfo.dwProvType,KeyContainerInfo.pwszProvName,KeyContainerInfo.pwszContainerName,0);
2185+ if SelectCertificate(AParams.SelectCertificateParams,CertificateContext) then
2186+ begin
2187+ XMLDigitalSignature := IXMLDigitalSignatureEx(CoMXDigitalSignature50.Create);
2188+ XMLDigitalSignature.signature := InputXML.selectSingleNode('//ds:Signature');
2189+ // Leia isso: https://docs.microsoft.com/en-us/previous-versions/windows/desktop/ms754613(v=vs.85)
2190+ // Não precisa da linha abaixo quando se usa createKeyFromCertContext
21682191
2169- if Assigned(XMLDSigKey) then
2170- begin
2171- if Assigned(XMLDigitalSignature.sign(XMLDSigKey, WriteKeyInfos)) then
2172- ReturnAdjustedXML
2173- else
2174- raise Exception.Create('Não foi possível assinar');
2175- end
2192+ Usar a funcao abaixo para obter o handle do store do certificado.AParams
2193+ Aparentemente hcertstore é um store que só tem um certificado e não é o
2194+ certstore "real". use o handle do store onde o certificado está para ver se
2195+ vai precisar adicionar o certificado manualmente. A intenção é tentar
2196+ inserir todos os certificados existentes no store também, e
2197+
2198+ CertOpenStore()
2199+
2200+ XMLDigitalSignature.setStoreHandle(CertificateContext.hCertStore);
2201+
2202+// case AParams.SignatureAlgorithm of
2203+// saRSASHA1: ;
2204+// saFromCertificate: ;
2205+// else
2206+// raise Exception.Create('O algoritmo de assinatura não foi informado');
2207+// end;
2208+
2209+ // O algoritmo de assinatura depende do certificado, exclusivamente, quando
2210+ // se assina. O certificado tem uma propriedade chamada "Algoritmo de hash de
2211+ // assinatura", e é ele que será usado na hora de assinar no nó SignatureMethod, não importa qual o algoritmo selecionado
2212+ //IXMLDigitalSignatureEx(XMLDigitalSignature).createKeyFromCertContext(CertificateContext,XMLDSigKey);
2213+
2214+ // Ao usar a forma abaixo, o algoritmo de hash assinatura aparentemente pode ser diferente daquele informado no certificado
2215+ // createKeyFromCSP exige PROV_RSA_FULL ou PROV_DSS_DH
2216+ // O que é um conteiner de chaves? https://stackoverflow.com/questions/2528186/what-exactly-is-a-key-container
2217+ // https://docs.microsoft.com/pt-br/windows/win32/seccrypto/example-c-program-creating-a-key-container-and-generating-keys?redirectedfrom=MSDN
2218+ //var y: String := 'SafeSign Standard Cryptographic Service Provider';
2219+
2220+// Escolha o melhor tipo 1 e crie/selecione as chaves nele neste ponto do codigo
2221+// talvez seja bom criar as chaves e logo em seguida destruir?
2222+// Conteiners de chave do tipo 1 aqui só criam SHA-1 no algoritmo de assinatura
2223+// para usar o do certificado, o codigo é outro
2224+//
2225+// crie uma opção pra isso que será ou sha-1 (quando cria as chaves aqui)
2226+// ou de acordo com o certificado (pra pegar o que o certificado tiver
2227+// remova as opções de hash de chave então
2228+
2229+ //XMLDSigKey := IXMLDSigKeyEx(IXMLDigitalSignatureEx(XMLDigitalSignature).createKeyFromCSP(PROV_RSA_FULL,y,'Meu conteiner de chaves',0));
2230+
2231+ // Aqui podemos obter XMLDSigKey a partir do CSP do certificado
2232+ // KPI contém informações sobre o conteiner de chaves associado ao
2233+ // certificado. Este contêiner de chaves, contém chaves que foram emitidas
2234+ // pela entidade de certificação do certificado em questão, portanto XMLDSigKey vai se referir diretamente ao certificado utilizado
2235+ GetCertificateKeyContainerInfo(CertificateContext,KPI);
2236+ // createKeyFromCSP apenas trabalha com PROV_RSA_FULL e PROV_DSS_DH, ambos só trabalham com SHA-1, por isso o algoritmo da assinatura digital no xml final é SHA-1
2237+ XMLDSigKey := IXMLDSigKeyEx(IXMLDigitalSignatureEx(XMLDigitalSignature).createKeyFromCSP(KPI.dwProvType
2238+ ,KPI.pwszProvName
2239+ ,KPI.pwszContainerName
2240+ ,0));
2241+
2242+ if Assigned(XMLDSigKey) then
2243+ begin
2244+ if Assigned(XMLDigitalSignature.sign(XMLDSigKey, WriteKeyInfos)) then
2245+ ReturnAdjustedXML
21762246 else
2177- raise Exception.Create('Não foi possível criar a chave a partir do CSP');
2178- finally
2179- FreeMem(KeyContainerInfo);
2180- end;
2247+ raise Exception.Create('Não foi possível assinar');
2248+ end
2249+ else
2250+ raise Exception.Create('Não foi possível obter a chave a partir do certficado digital escolhido');
2251+ end;
21812252 end;
21822253
21832254 // O url abaixo tem um exemplo que valida a cadeia de certificados. Isso pode
@@ -2268,4 +2339,100 @@
22682339 end;
22692340 end;
22702341
2342+function GetKeyPair(AKeyContainerName: String; AProviderName: String; AProviderType: Word; AKeyPairType: TKeyPairType; AKeyPairCreationFlags: DWORD; out AKeyPair: HCRYPTKEY): Boolean;
2343+var
2344+ KeyContainerHandle: HCRYPTPROV;
2345+ KeySpec: DWORD;
2346+begin
2347+ Result := False;
2348+ KeyContainerHandle := 0;
2349+ AKeyPair := 0;
2350+
2351+ if Trim(AKeyContainerName) = '' then
2352+ raise Exception.Create('Favor informar o nome do contêiner de chaves');
2353+
2354+ if Trim(AProviderName) = '' then
2355+ raise Exception.Create('Favor informar o nome do provedor criptográfico (CSP)');
2356+
2357+ case AKeyPairType of
2358+ kptKeyExchange: KeySpec := AT_KEYEXCHANGE;
2359+ kptSignature: KeySpec := AT_SIGNATURE;
2360+ else
2361+ raise Exception.Create('O tipo de par de chaves não foi informado');
2362+ end;
2363+
2364+ // Na primeira execução, tenta adquirir o contexto para o contêiner de
2365+ // chaves especificado em AKeyContainerName, mas como este contêiner não
2366+ // existe, ele será criado, apenas se o erro tiver sido NTE_BAD_KEYSET ou
2367+ // NTE_KEYSET_NOT_DEF. Caso não seja possível criar o contêiner de chaves, uma
2368+ // exceção será levantada. Mais detalhes em https://docs.microsoft.com/en-us/windows/win32/api/wincrypt/nf-wincrypt-cryptacquirecontexta
2369+ if not CryptAcquireContext(@KeyContainerHandle
2370+ ,PChar(AKeyContainerName)
2371+ ,PChar(AProviderName)
2372+ ,AProviderType
2373+ ,0) then
2374+ begin
2375+ if (GetLastError = Cardinal(NTE_BAD_KEYSET)) or (GetLastError = Cardinal(NTE_KEYSET_NOT_DEF)) then
2376+ begin
2377+ if not CryptAcquireContext(@KeyContainerHandle
2378+ ,PChar(AKeyContainerName)
2379+ ,PChar(AProviderName)
2380+ ,AProviderType
2381+ ,CRYPT_NEWKEYSET) then
2382+ raise EWinCrypt.Create(GetLastError,'Não foi possível criar um novo contêiner de chaves usando os dados informados');
2383+ end
2384+ else
2385+ raise EWinCrypt.Create(GetLastError,'Falha ao obter o manipulador para o contêiner de chaves especificado');
2386+ end;
2387+
2388+ // Se o fluxo chegar aqui o contêiner de chaves foi selecionado/criado e seu
2389+ // contexto (handle) encontra-se em "KeyContainerHandle" }
2390+
2391+ if KeyContainerHandle > 0 then
2392+ try
2393+ // Na primeira execução, tenta obter um handle para um par de chaves a partir
2394+ // de KeyContainerHandle. Caso o contêiner esteja vazio, o erro será
2395+ // NTE_NO_KEY e um par de chaves para assinatura digital será criado e
2396+ // colocado no contêiner identificado por KeyContainerHandle e, finalmente, um
2397+ // handle será retornado em AKeyPair
2398+ if not CryptGetUserKey(KeyContainerHandle
2399+ ,KeySpec
2400+ ,@AKeyPair) then
2401+ begin
2402+ if GetLastError = Cardinal(NTE_NO_KEY) then
2403+ begin
2404+ if not CryptGenKey(KeyContainerHandle
2405+ ,KeySpec
2406+ ,AKeyPairCreationFlags
2407+ ,@AKeyPair) then
2408+ raise EWinCrypt.Create(GetLastError,'Não foi possível criar um novo par de chaves');
2409+ end
2410+ else
2411+ raise EWinCrypt.Create(GetLastError,'Falha ao obter o manipulador para o par de chaves');
2412+ end;
2413+
2414+ Result := True;
2415+ finally
2416+ CryptReleaseContext(KeyContainerHandle,0);
2417+ end;
2418+end;
2419+
2420+procedure DeleteKeySet(AKeyContainerName: String; AProviderName: String; AProviderType: Cardinal);
2421+var
2422+ KeyContainerHandle: HCRYPTPROV;
2423+begin
2424+ if Trim(AKeyContainerName) = '' then
2425+ raise Exception.Create('Favor informar o nome do contêiner de chaves');
2426+
2427+ if Trim(AProviderName) = '' then
2428+ raise Exception.Create('Favor informar o nome do provedor criptográfico (CSP)');
2429+
2430+ if not CryptAcquireContext(@KeyContainerHandle
2431+ ,PChar(AKeyContainerName)
2432+ ,PChar(AProviderName)
2433+ ,AProviderType
2434+ ,CRYPT_DELETEKEYSET) then
2435+ raise EWinCrypt.Create(GetLastError,'Não foi possível excluir o contêiner de chaves especificado');
2436+end;
2437+
22712438 end.
--- trunk/rtp/src/Rtl/Win/KRK.Rtl.Win.WinCrypt.pas (revision 525)
+++ trunk/rtp/src/Rtl/Win/KRK.Rtl.Win.WinCrypt.pas (revision 526)
@@ -1576,8 +1576,7 @@
15761576 function CryptReleaseContext(hProv: HCRYPTPROV; dwFlags: DWORD): BOOL; winapi;
15771577
15781578 {$EXTERNALSYM CryptGenKey}
1579-function CryptGenKey(hProv: HCRYPTPROV; Algid: ALG_ID; dwFlags: DWORD;
1580- var phKey: HCRYPTKEY): BOOL; winapi;
1579+function CryptGenKey(hProv: HCRYPTPROV; Algid: ALG_ID; dwFlags: DWORD; phKey: PHCRYPTKEY): BOOL; winapi;
15811580
15821581 {$EXTERNALSYM CryptDeriveKey}
15831582 function CryptDeriveKey(hProv: HCRYPTPROV; Algid: ALG_ID; hBaseData: HCRYPTHASH; dwFlags: DWORD; phKey: PHCRYPTKEY): BOOL; winapi;
@@ -1611,8 +1610,7 @@
16111610 pbBuffer: PBYTE): BOOL; winapi;
16121611
16131612 {$EXTERNALSYM CryptGetUserKey}
1614-function CryptGetUserKey(hProv: HCRYPTPROV; dwKeySpec: DWORD;
1615- out phUserKey: HCRYPTKEY): BOOL; winapi;
1613+function CryptGetUserKey(hProv: HCRYPTPROV; dwKeySpec: DWORD; phUserKey: PHCRYPTKEY): BOOL; winapi;
16161614
16171615 {$EXTERNALSYM CryptExportKey}
16181616 function CryptExportKey(hKey: HCRYPTKEY; hExpKey: HCRYPTKEY; dwBlobType: DWORD; dwFlags: DWORD; pbData: PBYTE; dwDataLen: PDWORD): BOOL; winapi;
@@ -10561,6 +10559,8 @@
1056110559 CERT_ROOT_PROGRAM_NAME_CONSTRAINTS_PROP_ID = 84;
1056210560 {$EXTERNALSYM CERT_FIRST_RESERVED_PROP_ID}
1056310561 CERT_FIRST_RESERVED_PROP_ID = 85;
10562+ {$EXTERNALSYM CERT_SIGN_HASH_CNG_ALG_PROP_ID}
10563+ CERT_SIGN_HASH_CNG_ALG_PROP_ID = 89;
1056410564
1056510565 {$EXTERNALSYM CERT_LAST_RESERVED_PROP_ID}
1056610566 CERT_LAST_RESERVED_PROP_ID = $00007FFF;
--- trunk/utl/TESTADOR/bin/CSP + ALG.txt (nonexistent)
+++ trunk/utl/TESTADOR/bin/CSP + ALG.txt (revision 526)
@@ -0,0 +1,247 @@
1+Id do Tipo Nome do provedor criptográfico (CSP) Implementação
2+---------- ---------------------------------------------------------------- ----------------------------------------
3+ 1 Microsoft Base Cryptographic Provider v1.0 SW
4+ 13 Microsoft Base DSS and Diffie-Hellman Cryptographic Provider SW
5+ 3 Microsoft Base DSS Cryptographic Provider SW
6+ 1 Microsoft Base Smart Card Crypto Provider HW+SW+MX+RM
7+ 18 Microsoft DH SChannel Cryptographic Provider SW
8+ 1 Microsoft Enhanced Cryptographic Provider v1.0 SW
9+ 13 Microsoft Enhanced DSS and Diffie-Hellman Cryptographic Provider SW
10+ 24 Microsoft Enhanced RSA and AES Cryptographic Provider SW
11+ 12 Microsoft RSA SChannel Cryptographic Provider SW
12+ 1 Microsoft Strong Cryptographic Provider SW
13+ 1 SafeSign Standard Cryptographic Service Provider HW+SW+MX+RM
14+ 24 SafeSign Standard RSA and AES Cryptographic Service Provider HW+SW+MX+RM
15+----------------------------------------------------------------------------------------------------------------------
16+HW = Hardware, SW = Software, MX = HW+SW, RM = Mídia Removível, UK = Desconhecido
17+
18+──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────
19+Microsoft Base Cryptographic Provider v1.0 (Tipo 1)
20+──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────
21+ID do algoritmo Nome Bits Tipo
22+--------------- --------------- ---- ---------
23+00006602h RC2 40 Encrypt
24+00006801h RC4 40 Encrypt
25+00006601h DES 56 Encrypt
26+00008004h SHA-1 160 Hash
27+00008001h MD2 128 Hash
28+00008002h MD4 128 Hash
29+00008003h MD5 128 Hash
30+00008008h SSL3 SHAMD5 288 Hash
31+00008005h MAC 0 Hash
32+00002400h RSA_SIGN 512 Signature
33+0000A400h RSA_KEYX 512 Exchange
34+00008009h HMAC 0 Hash
35+──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────
36+Microsoft Base DSS and Diffie-Hellman Cryptographic Provider (Tipo 13)
37+──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────
38+ID do algoritmo Nome Bits Tipo
39+--------------- --------------- ---- ---------
40+0000660Ch CYLINK MEK 40 Encrypt
41+00006602h RC2 40 Encrypt
42+00006801h RC4 40 Encrypt
43+00006601h DES 56 Encrypt
44+00008004h SHA-1 160 Hash
45+00008003h MD5 128 Hash
46+00002200h DSA_SIGN 1024 Signature
47+0000AA01h DH_KEYX 512 Exchange
48+0000AA02h DH_KEYX 512 Exchange
49+──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────
50+Microsoft Base DSS Cryptographic Provider (Tipo 3)
51+──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────
52+ID do algoritmo Nome Bits Tipo
53+--------------- --------------- ---- ---------
54+00008004h SHA-1 160 Hash
55+00008003h MD5 128 Hash
56+00002200h DSA_SIGN 1024 Signature
57+──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────
58+Microsoft Base Smart Card Crypto Provider (Tipo 1)
59+──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────
60+ID do algoritmo Nome Bits Tipo
61+--------------- --------------- ---- ---------
62+00006602h RC2 128 Encrypt
63+00006801h RC4 128 Encrypt
64+00006601h DES 56 Encrypt
65+00006609h 3DES TWO KEY 112 Encrypt
66+00006603h 3DES 168 Encrypt
67+00008004h SHA-1 160 Hash
68+0000800Ch SHA-256 256 Hash
69+0000800Dh SHA-384 384 Hash
70+0000800Eh SHA-512 512 Hash
71+00008001h MD2 128 Hash
72+00008002h MD4 128 Hash
73+00008003h MD5 128 Hash
74+00008008h SSL3 SHAMD5 288 Hash
75+00008005h MAC 0 Hash
76+00002400h RSA_SIGN 2048 Signature
77+0000A400h RSA_KEYX 2048 Exchange
78+00008009h HMAC 0 Hash
79+0000660Eh AES 128 128 Encrypt
80+0000660Fh AES 192 192 Encrypt
81+00006610h AES 256 256 Encrypt
82+──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────
83+Microsoft DH SChannel Cryptographic Provider (Tipo 18)
84+──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────
85+ID do algoritmo Nome Bits Tipo
86+--------------- --------------- ---- ---------
87+0000660Ch CYLINK MEK 40 Encrypt
88+00006602h RC2 40 Encrypt
89+00006801h RC4 40 Encrypt
90+00006601h DES 56 Encrypt
91+00006609h 3DES TWO KEY 112 Encrypt
92+00006603h 3DES 168 Encrypt
93+00008004h SHA-1 160 Hash
94+00008003h MD5 128 Hash
95+00002200h DSA_SIGN 1024 Signature
96+0000AA01h DH_KEYX 512 Exchange
97+0000AA02h DH_KEYX 512 Exchange
98+00004C01h SSL3 MASTER 384 Unknown
99+00004C06h TLS1 MASTER 384 Unknown
100+00004C02h SCH MASTER HASH 0 Unknown
101+00004C03h SCH MAC KEY 0 Unknown
102+00004C07h SCH ENC KEY 0 Unknown
103+──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────
104+Microsoft Enhanced Cryptographic Provider v1.0 (Tipo 1)
105+──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────
106+ID do algoritmo Nome Bits Tipo
107+--------------- --------------- ---- ---------
108+00006602h RC2 128 Encrypt
109+00006801h RC4 128 Encrypt
110+00006601h DES 56 Encrypt
111+00006609h 3DES TWO KEY 112 Encrypt
112+00006603h 3DES 168 Encrypt
113+00008004h SHA-1 160 Hash
114+00008001h MD2 128 Hash
115+00008002h MD4 128 Hash
116+00008003h MD5 128 Hash
117+00008008h SSL3 SHAMD5 288 Hash
118+00008005h MAC 0 Hash
119+00002400h RSA_SIGN 1024 Signature
120+0000A400h RSA_KEYX 1024 Exchange
121+00008009h HMAC 0 Hash
122+──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────
123+Microsoft Enhanced DSS and Diffie-Hellman Cryptographic Provider (Tipo 13)
124+──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────
125+ID do algoritmo Nome Bits Tipo
126+--------------- --------------- ---- ---------
127+0000660Ch CYLINK MEK 40 Encrypt
128+00006602h RC2 128 Encrypt
129+00006801h RC4 128 Encrypt
130+00006601h DES 56 Encrypt
131+00006609h 3DES TWO KEY 112 Encrypt
132+00006603h 3DES 168 Encrypt
133+00008004h SHA-1 160 Hash
134+00008003h MD5 128 Hash
135+00002200h DSA_SIGN 1024 Signature
136+0000AA01h DH_KEYX 1024 Exchange
137+0000AA02h DH_KEYX 1024 Exchange
138+──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────
139+Microsoft Enhanced RSA and AES Cryptographic Provider (Tipo 24)
140+──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────
141+ID do algoritmo Nome Bits Tipo
142+--------------- --------------- ---- ---------
143+00006602h RC2 128 Encrypt
144+00006801h RC4 128 Encrypt
145+00006601h DES 56 Encrypt
146+00006609h 3DES TWO KEY 112 Encrypt
147+00006603h 3DES 168 Encrypt
148+00008004h SHA-1 160 Hash
149+0000800Ch SHA-256 256 Hash
150+0000800Dh SHA-384 384 Hash
151+0000800Eh SHA-512 512 Hash
152+00008001h MD2 128 Hash
153+00008002h MD4 128 Hash
154+00008003h MD5 128 Hash
155+00008008h SSL3 SHAMD5 288 Hash
156+00008005h MAC 0 Hash
157+00002400h RSA_SIGN 1024 Signature
158+0000A400h RSA_KEYX 1024 Exchange
159+00008009h HMAC 0 Hash
160+0000660Eh AES 128 128 Encrypt
161+0000660Fh AES 192 192 Encrypt
162+00006610h AES 256 256 Encrypt
163+──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────
164+Microsoft RSA SChannel Cryptographic Provider (Tipo 12)
165+──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────
166+ID do algoritmo Nome Bits Tipo
167+--------------- --------------- ---- ---------
168+0000660Eh AES 128 128 Encrypt
169+00006610h AES 256 256 Encrypt
170+00006602h RC2 128 Encrypt
171+00006801h RC4 128 Encrypt
172+00006601h DES 56 Encrypt
173+00006609h 3DES TWO KEY 112 Encrypt
174+00006603h 3DES 168 Encrypt
175+00008004h SHA-1 160 Hash
176+00008003h MD5 128 Hash
177+00008008h SSL3 SHAMD5 288 Hash
178+00008005h MAC 0 Hash
179+0000A400h RSA_KEYX 1024 Exchange
180+00008009h HMAC 0 Hash
181+00004C05h SSL2 MASTER 40 Unknown
182+00004C01h SSL3 MASTER 384 Unknown
183+00004C06h TLS1 MASTER 384 Unknown
184+00004C02h SCH MASTER HASH 0 Unknown
185+00004C03h SCH MAC KEY 0 Unknown
186+00004C07h SCH ENC KEY 0 Unknown
187+──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────
188+Microsoft Strong Cryptographic Provider (Tipo 1)
189+──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────
190+ID do algoritmo Nome Bits Tipo
191+--------------- --------------- ---- ---------
192+00006602h RC2 128 Encrypt
193+00006801h RC4 128 Encrypt
194+00006601h DES 56 Encrypt
195+00006609h 3DES TWO KEY 112 Encrypt
196+00006603h 3DES 168 Encrypt
197+00008004h SHA-1 160 Hash
198+00008001h MD2 128 Hash
199+00008002h MD4 128 Hash
200+00008003h MD5 128 Hash
201+00008008h SSL3 SHAMD5 288 Hash
202+00008005h MAC 0 Hash
203+00002400h RSA_SIGN 1024 Signature
204+0000A400h RSA_KEYX 1024 Exchange
205+00008009h HMAC 0 Hash
206+──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────
207+SafeSign Standard Cryptographic Service Provider (Tipo 1)
208+──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────
209+ID do algoritmo Nome Bits Tipo
210+--------------- --------------- ---- ---------
211+00008004h SHA-1 160 Hash
212+00008002h MD4 128 Hash
213+00008003h MD5 128 Hash
214+00006602h RC2 128 Encrypt
215+00006801h RC4 128 Encrypt
216+00006601h DES 56 Encrypt
217+00006609h 3DES TWO KEY 112 Encrypt
218+00006603h 3DES 168 Encrypt
219+00008008h SSL3 SHAMD5 288 Hash
220+00008005h MAC 0 Hash
221+00002400h RSA_SIGN 1024 Signature
222+0000A400h RSA_KEYX 1024 Exchange
223+00008009h HMAC 0 Hash
224+0000800Ch SHA-256 256 Hash
225+0000800Dh SHA-384 384 Hash
226+0000800Eh SHA-512 512 Hash
227+──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────
228+SafeSign Standard RSA and AES Cryptographic Service Provider (Tipo 24)
229+──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────
230+ID do algoritmo Nome Bits Tipo
231+--------------- --------------- ---- ---------
232+00008004h SHA-1 160 Hash
233+00008002h MD4 128 Hash
234+00008003h MD5 128 Hash
235+00006602h RC2 128 Encrypt
236+00006801h RC4 128 Encrypt
237+00006601h DES 56 Encrypt
238+00006609h 3DES TWO KEY 112 Encrypt
239+00006603h 3DES 168 Encrypt
240+00008008h SSL3 SHAMD5 288 Hash
241+00008005h MAC 0 Hash
242+00002400h RSA_SIGN 1024 Signature
243+0000A400h RSA_KEYX 1024 Exchange
244+00008009h HMAC 0 Hash
245+0000800Ch SHA-256 256 Hash
246+0000800Dh SHA-384 384 Hash
247+0000800Eh SHA-512 512 Hash
\ No newline at end of file
--- trunk/utl/TESTADOR/src/UFRAMSelecionarCertificado.pas (revision 525)
+++ trunk/utl/TESTADOR/src/UFRAMSelecionarCertificado.pas (revision 526)
@@ -27,6 +27,7 @@
2727 EDITCertificatePassword: TEdit;
2828 Button1: TButton;
2929 procedure CBBXProviderTypesChange(Sender: TObject);
30+ procedure Button1Click(Sender: TObject);
3031 private
3132 function GetSelectCertificateParams: TSelectCertificateParams;
3233 { Private declarations }
@@ -71,7 +72,7 @@
7172 implementation
7273
7374 uses
74- KRK.Rtl.Win.WinCrypt, KRK.Rtl.Win.WinCrypt.Utilities;
75+ KRK.Rtl.Win.WinCrypt, KRK.Rtl.Win.WinCrypt.Utilities, UDAMOPrincipal;
7576
7677 {$R *.dfm}
7778
@@ -93,6 +94,12 @@
9394
9495 { TFRAMSelecionarCertificado }
9596
97+procedure TFRAMSelecionarCertificado.Button1Click(Sender: TObject);
98+begin
99+ if DAMOPrincipal.OPDICarregarArquivoPFX.Execute then
100+ EDITCertificateFile.Text := DAMOPrincipal.OPDICarregarArquivoPFX.FileName;
101+end;
102+
96103 procedure TFRAMSelecionarCertificado.CBBXProviderTypesChange(Sender: TObject);
97104 begin
98105 LoadCSPNames;
Show on old repository browser