2009-11-24 6 views
1

Je voudrais réécrire cette fonction de signature numérique php en code Delphi.Convertir cette signature numérique PHP en Delphi

function SaySig() { 

    $privKeyFilePath = "c:\temp\myrsakey.pem"; 

    $data = "sign this string"; 
    $fp = fopen($privKeyFilePath, "r"); 
    $priv_key = fread($fp, 8192); 
    fclose($fp); 
    $privatekeyid = openssl_get_privatekey($priv_key); 
    openssl_sign($data, $signature, $privatekeyid, OPENSSL_ALGO_SHA1); 
    openssl_free_key($privatekeyid); 
    $sig = base64_encode($signature); 
    echo "<br>"; 
    echo "Signature:".$sig."<br><br>"; 
    } 

Je ne me soucie pas quel composant est utilisé (lockbox, DelphiOpenSSL, Chilkat Crypte ActiveX, etc.). J'ai essayé tout cela sans succès; ce qui me fait penser que je fais quelque chose de fondamentalement faux.

Ma clé a été générée en tant que tel:

openssl req -x509 -nodes -days 365 -newkey rsa: 1024 -sha1 -subj «/C = US/ST = CA/L = Mountain View/CN = www.mycompany.com » -keyout myrsakey.pem c -out: \ temp \ myrsacert.pem

le contenu de la clé (ne vous inquiétez pas - je vais générer un nouveau):

----- COMMENCER LA CLÉ PRIVÉE RSA ----- MIICXgIBAAKBgQ CqsR7s4X74LfTiLv1PP6Yn0SBpGBtbzkBSQ95E2b9Haa3Qtf0a KjDJpZLMwXC/IrSP7K2Gxbl2cZotT19GVgw6PcYPTBBWX2gJoVrnQZP8uPdlGAgS plODP55R9f4F0KzIpE6d + dpTGfJ1wysFqYN8fxtlu8K7YO/Mh8tNzN5VOQIDAQAB AoGBAIvCvRyeQlU5Y + JzMSvbZNQDUrNabsRL67SwJ2VemVUCvbQ/3v62fv4M2VdY KFYIN6oE08yfRw0pVWE2NT + lIxqSQx7 + qv84Y7duqT7155wpCFj + a/6pYyNTFNFi 5wiTnN13eyHNgKxZm7QcMH67T/noTgz0LoT5p54ynmfNcjyBAkEA3DCEQ6Dm2xYH Nhk3 + 7sNEVklN20zNqyYvrCunNLAiLioF1jDApdfcT8YtVd29L7tH1ZdJYG5DXJ8 Bs7eKLGekQJBAMZzy0Q7LZHdWQxSRi7wy0eq6SqZMqi0pb9VPuXjWG1y + rtRr1vV vyMaGz4rcE7mkbq/nkn + AQXc30GOj3GE8CkCQQCMDVwDfBN6pL8/fLjsJ + S + 9RnD 8HRTwWKCX/UgkLif/fwEpZOcUVYGvSBlL9XdBJfkh9VFZwaidABJgEk0Tw3RAkBd 6pjMnpDvUeh9e0Y5mr0pGookHcIqsuspxEby9od3rI1a LsslU9 + T1hwEbPxGarmW vj0MAUgspR2G4deiqn4ZAkEAnWxV7NhtVPLs5Y2ZYeHz7ipdcSL4/keLW4PwKerF 7LJj4s7/6ZqnHA6Z0yhCcziflYQArWt1ViLMIYZ8grr5Kg == ----- END RSA PRIVATE KEY -----

Et la sortie semble en tant que tel:

jcIIsr145dTwDrT8g4jb2HZ5FP5UL6/9mK7hF6hC2lCZGlM0W4QqFqytghWaU0w3Z6JkMVUlxxWtQ2R + vWQVB0F3htAtbVZkiA67x0zor + zmpClBIazmfVJlng4sG1R7CCUZ0gGhdm4JMc08VsWU25utudcG6inpl whQiZgefW0 =

Il semblerait que je demande à quelqu'un de «faire mon travail». Mais j'ai été battant à ce sujet pendant un certain temps sans succès. Merci.

Quelqu'un a demandé que je poste un peu de mon code. Voici quelques-unes des choses que j'ai essayé ..

function TMainWeb.sign(mstring: String): string; 
var 
    mPrivateKey: TLbRSAKey; 
    LbRSASSA1: TLbRSASSA; 
begin 
    LbRSASSA1:= TLbRSASSA.create(nil); 
    LbRSASSA1.PrivateKey.LoadFromFile('C:\temp\myrsakey.der'); 
    LbRSASSA1.HashMethod := TRSAHashMethod(hmSHA1); 
    LbRSASSA1.SignString(mString); 
    result := LbRSASSA1.Signature.IntStr; 
end; 

function TMainWeb.sign1(mstring: String): string; 
var 
    LbDSA1: TLbDSA; 
    mPrivateKey: TLbRSAKey; 
begin 
    mPrivateKey := TLbRSAKey.Create(aks1024); 
    mPrivateKey.LoadFromFile('C:\temp\myrsakey.der'); 
    LbDSA1 := TLbDSA.create(application); 
    lbDSA1.PrivateKey.Assign(mPrivateKey); 
    LbDSA1.SignString(mString); 
end; 

function TMainWeb.Sign2(mString: String): string; 
var 
    signer: TMessageSigner; 
begin 
    signer := TMessageSigner.Create; 
    signer.LoadPrivateKey('C:\temp\myrsakey.pem'); 
    signer.PlainMessage := mString; 
    signer.MIMESign; 
    result := signer.SignedMessage; 
end; 
+0

Où est votre code Delphi? –

+0

J'ai essayé tellement de choses que je ne savais pas quoi inclure. J'ai ajouté quelques extraits de mon code; Aucun de qui a travaillé. –

+0

Je ne suis pas réellement un programmeur Delphi, je supposais juste que personne ne répondrait à moins que vous ayez posté une tentative :) –

Répondre

3

Essayez ceci.
Je ne prétends pas que c'est un code parfait (!) Mais il compile :-)   et donne le même résultat que vous avez cité. Utilise l'API OpenSSL de M Ferrante que vous mentionnez ci-dessus. Beaucoup de choses que vous ne feriez normalement qu'une seule fois au démarrage - comme charger une clé privée, InitSSL, etc. J'utilise le JCL Jedi pour les bases64 - c'est plus simple.Aussi certains d'entre eux semblent un peu bizarres (utilise TBytes où PChar ferait etc etc) comme je l'ai écrit à l'origine en utilisant mes en-têtes API Delphi 2010 mais j'ai réalisé que vous utilisiez D2007 et TEncoding n'était pas disponible et quelques mods étaient nécessaire.
(SignStringToBase64 est l'appel principal, à droite au bas de la liste)

uses libeay32, jclmime; 

const 
    LIBEAY_DLL_NAME = 'libeay32.dll'; 

// These aren't defined in the original libeay32.pas file 
procedure EVP_MD_CTX_init(ctx: PEVP_MD_CTX); cdecl; external LIBEAY_DLL_NAME; 
function EVP_MD_CTX_cleanup(ctx: PEVP_MD_CTX): integer; cdecl; external LIBEAY_DLL_NAME; 

procedure InitSSL; 
begin 
    OpenSSL_add_all_algorithms; 
    OpenSSL_add_all_ciphers; 
    OpenSSL_add_all_digests; 
    ERR_load_crypto_strings; 
    // Seed the pseudo-random number generator 
    // This should be something a little more "random"! 
    RAND_load_file('c:\windows\paint.exe', 512); 
end; 

procedure FinalizeSSL; 
begin 
    EVP_cleanup; 
end; 

function GetSSLErrorMessage: string; 
const 
    BUFF_SIZE = 128; // OpenSSL docs state should be >= 120 bytes 
var 
    err: TBytes; 
begin 
    SetLength(err, BUFF_SIZE); 
    ERR_error_string(ERR_get_error, @err[0]); 
    result := string(err); 
end; 

function RSALoadPrivateKey(const AFileName, APassPhrase: string): PRSA; 
var 
    bp: pBIO; 
    fn, pp: PAnsiChar; 
    pk: PRSA; 
begin 
    fn := PAnsiChar(AnsiString(AFileName)); 
    pp := PAnsiChar(AnsiString(APassPhrase)); 
    bp := BIO_new(BIO_s_file()); 
    BIO_read_filename(bp, fn); 
    pk := nil; 
    result := PEM_read_bio_RSAPrivateKey(bp, pk, nil, pp); 
    if result = nil then 
    raise Exception.Create('Private key failure.' + GetSSLErrorMessage); 
end; 

function LoadPrivateKey(const AFileName, APass: string): PEVP_PKEY; 
var 
    rkey: PRSA; 
begin 
    rkey := RSALoadPrivateKey(AFileName, APass); 
    result := EVP_PKEY_new; 
    EVP_PKEY_assign(result, EVP_PKEY_RSA, rkey); 
end; 

procedure CleanUpKey(AKey: PEVP_PKEY); 
begin 
    if (AKey <> nil) then 
    begin 
    EVP_PKEY_free(AKey); 
    // The OpenSSL docs state that the related rsa key will also 
    // be freed when the parent key is freed 
    end; 
end; 

function EVPSign(ASource: TBytes; const APrivateKey: PEVP_PKEY): TBytes; 
var 
    keysize: integer; 
    ks: cardinal; 
    ctx: EVP_MD_CTX; 
begin 
    keysize := EVP_PKEY_size(APrivateKey); 
    SetLength(result, keysize); 

    EVP_MD_CTX_init(@ctx); 
    try 
    EVP_SignInit(@ctx, EVP_sha1); 
    EVP_SignUpdate(@ctx, @ASource[0], Length(ASource)); 
    EVP_SignFinal(@ctx, @result[0], ks, APrivateKey); 
    SetLength(result, ks); 
    finally 
    EVP_MD_CTX_cleanup(@ctx); 
    end; 
end; 

function Base64EncodeBytes(Input: TBytes): string; 
var 
    b64: TBytes; 
begin 
    SetLength(b64, jclMime.MimeEncodedSizeNoCRLF(Length(Input))); 
    jclMime.MimeEncodeNoCRLF(Input[0], Length(Input), b64[0]); 
    result := string(b64); 
end; 

function SignStringToBase64(const AText: string): string; 
var 
    key: PEVP_PKEY; 
    src, enc: TBytes; 
begin 
    InitSSL; 
    try 
    key := LoadPrivateKey('c:\temp\priv-key.pem', ''); 
    try 
     SetLength(src, Length(AText)); 
     CopyMemory(@src[0], @AText, Length(AText));   
     enc := EVPSign(src, key); 
     result := Base64EncodeBytes(enc); 
    finally 
     CleanUpKey(key); 
    end; 
    finally 
    FinalizeSSL; 
    end; 
end; 
+0

Merci beaucoup. Essayer de l'implémenter maintenant mais avoir du mal à installer/compiler Jedi (l'ai obtenu sur http://sourceforge.net/projects/jvcl/files/). jclmime.pas nécessite jcl.inc, ce qui nécessite jcld11.inc, qui ne peut être trouvé. Je vais continuer à creuser. –

+0

Exécutez simplement install.bat à la racine de l'installation du JCL - il est remarquablement sophistiqué. jcld11.inc est créé automatiquement avec une charge de contenu spécifique à la version. (Ou utilisez votre propre bibliothèque Base64 préférée) – shunty

+0

En fait, posez-la un peu et revenez dessus. Vous avez la source de http://sourceforge.net/projects/jcl/files/ et il compile. –

Questions connexes