2016-08-05 2 views
0

Je peux signer et vérifier les données en PHP utilisant OpenSSL:Impossible de vérifier la signature pyopenssl en C#

function generate_signature($privateKey, $data) { 

    $keyData = openssl_get_privatekey($privateKey); 

    openssl_sign($data, $signature, $keyData, OPENSSL_ALGO_SHA256); 
    openssl_free_key($keyData); 

    $sigText = base64_encode($signature); 
    return $sigText; 
} 

function verify_signature($pubKey, $sigText, $data) { 
    $signature = base64_decode($sigText);  

    $keyData = openssl_get_publickey($pubKey); 
    $ok = openssl_verify($data, $signature, $keyData, "sha256WithRSAEncryption"); 
    openssl_free_key($keyData); 

    return $ok; 
} 

$privateKey= file_get_contents("private.key"); 
$pubKey = file_get_contents("public.pem"); 

$data = "This is a test"; 
$sigText = generate_signature($privateKey, $data); 
$result = verify_signature($pubKey, $sigText, $data); 

Cela fonctionne très bien pour quelles que soient les valeurs des données essayer. $result est toujours vrai.

Cependant, lorsque je tente de vérifier la signature en C# en utilisant les API bouncycastle, il échoue toujours:

public static bool VerifySignature(string data, string signatureText) 
{ 
    // Using statements and error checking removed for brevity 

    var uri = new Uri("pack://application:,,,/Resources/public.pem"); 
    var resourceStream = Application.GetResourceStream(uri); 
    var reader = new StreamReader(resourceStream.Stream); 

    PemReader pemReader = new PemReader(reader); 
    RsaKeyParameters parameters = (RsaKeyParameters)pemReader.ReadObject(); 
    RSACryptoServiceProvider provider = (RSACryptoServiceProvider)RSACryptoServiceProvider.Create(); 

    RSAParameters rParams = new RSAParameters(); 
    rParams.Modulus = parameters.Modulus.ToByteArray(); 
    rParams.Exponent = parameters.Exponent.ToByteArray(); 

    provider.ImportParameters(rParams); 

    byte[] sigBytes = Convert.FromBase64String(signatureText); 
    byte[] dataBytes = Encoding.UTF8.GetBytes(data); 

    bool isValid = provider.VerifyData(dataBytes, CryptoConfig.MapNameToOID("SHA256"), sigBytes); 

    return isValid; 
} 

Peu importe ce que j'essaie, isValid est toujours faux. J'ai essayé d'utiliser SHA1 aux deux extrémités au lieu de SHA256, j'ai essayé différents encodages, j'ai essayé d'inverser plusieurs tableaux d'octets au cas où il y aurait des problèmes d'endian, mais peu importe ce que j'essaie, je ne peux pas vérifier le PHP Signature. Il me manque clairement quelque chose du côté C#, mais je ne sais pas quoi.

+1

Quand quelque chose ne va pas avec une signature il y a un truc que vous pouvez faire pour le débogage: une signature RSA est techniquement une valeur de hachage chiffrée par RSA. Vous pouvez simplement le décrypter en utilisant la clé publique que vous utilisez pour vérifier (et en utilisant aucun algo de remplissage). Puis enregistrez les données, extrayez le hachage et comparez-le avec ce que vous attendez. – Robert

+0

1) Avez-vous ajouté le certificat dans le magasin de certificats? 2) Selon cette documentation: https://msdn.microsoft.com/en-us/library/55yk5665(v=vs.110).aspx vous devez calculer le hachage: hash.ComputeHash –

+0

@LeonidasMenendez Je suis assez sûr Les certificats n'ont pas besoin d'être dans le fichier de clés pour les utiliser, c'est juste un endroit sûr pour les stocker. Vous devez toujours charger les octets de clé brute hors d'eux. – lfalin

Répondre

0

Eh bien, je ne suis toujours pas sûr de ce que RSACryptoServiceProvider a contre moi, mais je l'ai trouvé une autre méthode qui fonctionne parfaitement:

public static bool VerifySignature(string data, string signatureText) 
{ 
    // Using statements and error checking removed for brevity 
    var uri = new Uri("pack://application:,,,/Resources/public.pem"); 
    var resourceStream = Application.GetResourceStream(uri); 
    var reader = new StreamReader(resourceStream.Stream); 

    PemReader pemReader = new PemReader(reader); 
    RsaKeyParameters parameters = (RsaKeyParameters)pemReader.ReadObject(); 

    RsaDigestSigner signer = (RsaDigestSigner)SignerUtilities.GetSigner("SHA-256withRSA"); 
    signer.Init(false, parameters); 

    byte[] sigBytes = Convert.FromBase64String(signatureText); 
    byte[] dataBytes = Encoding.UTF8.GetBytes(data); 

    signer.BlockUpdate(dataBytes, 0, dataBytes.Length); 
    bool isValid = signer.VerifySignature(sigBytes); 

    return isValid; 
}