8
votes

Avoir du mal à décrypter dans C # quelque chose crypté sur iPhone en utilisant RSA

J'ai passé deux jours sur ce jusqu'à présent et passé au peigne fin toutes les sources à ma disposition, c'est donc le dernier recours.

J'ai un certificat X509 dont la clé publique que j'ai stocké dans le trousseau de l'iPhone (simulateur uniquement À ce point). Du côté ASP.NET, j'ai le certificat dans le magasin de cert avec une clé privée. Quand je crypter une chaîne sur l'iPhone et décryptées sur le serveur, je reçois un CryptographicException code> « mauvaises données. » J'ai essayé Array.Reverse code> suggéré dans la section RSACryptoServiceProvider code> sur un longshot, mais il n'a pas aidé. p>

J'ai comparé la base de 64 chaînes sur les deux côtés et ils sont égaux . Je l'ai comparé les tableaux d'octets brutes après décodage et ils sont trop égaux. Si je crypter sur le serveur en utilisant la clé publique, le tableau d'octets est différent de la version de l'iPhone et déchiffre facilement en utilisant la clé privée. La chaîne de texte brut brut est de 115 caractères il est donc dans la limite de 256 octets de ma clé 2048 bits p>

Voici la méthode de cryptage iPhone (à peu près mot pour mot de la échantillon CryptoExercise application 's wrapSymmetricKey code>): p>

private string Decrypt(string cipherText)
{
    if (clientCert == null)
    {
        // Get certificate
        var store = new X509Store(StoreName.My, StoreLocation.LocalMachine);
        store.Open(OpenFlags.ReadOnly);
        foreach (var certificate in store.Certificates)
        {
            if (certificate.GetNameInfo(X509NameType.SimpleName, false) == CERT)
            {
                clientCert = certificate;
                break;
            }
        }
    }

    using (var rsa = (RSACryptoServiceProvider)clientCert.PrivateKey)
    {
        try
        {
            var encryptedBytes = Convert.FromBase64String(cipherText);
            var decryptedBytes = rsa.Decrypt(encryptedBytes, false);
            var plaintext = Encoding.UTF8.GetString(decryptedBytes);
            return plaintext;
        }
        catch (CryptographicException e)
        {
            throw(new ApplicationException("Unable to decrypt payload.", e));
        }
    }
}


0 commentaires

4 Réponses :


-2
votes

Je crois que vous avez répondu à la question vous-même. Le problème se situe très certainement dans l'endansnité.

C'est une façon possible d'écrire des méthodes de conversion à double sens: xxx

Cela pourrait être une bonne ressource pour vous (Autre que Wikipedia): http://betterexplaine.com/articles / compréhension-big-et-petit-endian-byte-ordre /


3 commentaires

C'est génial d'entendre et merci pour la réponse! Pardonne mon ignorance, mais comment puis-je utiliser exactement ces méthodes de conversion? Je suppose qu'ils sont pour sur l'iPhone alors où voudrais-je le brancher dans ma méthode?


Il s'avère que l'endansion entre les plates-formes est une relique des jours PowerPC. Mac OS X, en étant basé sur l'architecture X86, est petit-Endian - identique à Windows. L'iPhone, sur l'architecture du bras, est également petit-Endian autant que je puisse déterminer des recherches.


Endentianness ne serait pas un problème ici, de toute façon. Toutes vos opérations impliquent des octets bruts et non des numéros multi-octets.




3
votes

Eh bien ... La première étape (comme vous le dites que vous avez fait) consiste à chiffrer les mêmes messages avec les mêmes vecteurs d'initialisation utilisant à la fois l'iPhone et la mise en œuvre C #. Vous devriez obtenir la même sortie. Vous avez dit que vous ne l'avez pas fait, alors il y a un problème.

Cela signifie soit:

  • L'implémentation de l'iPhone de RSA est incorrecte.
  • La mise en œuvre .NET de RSA est incorrecte.
  • Les fichiers clés sont différents (ou sont interprétés différemment).

    Je suggérerais que les deux premiers sont peu probables, mais ils sont à distance possibles.

    Vous indiquez: "Dossier de poche installé dans différentes cordes de Cert Store et Server-Crypted String" ... Cela ne prouve rien: tout ce qui prouve est celui donné d'un ensemble de nombres aléatoires particulier que vous pouvez chiffrer / déchiffrer avec succès sur une plate-forme. Vous ne garantissez pas que les deux plates-formes voient le même ensemble de nombres aléatoires.

    Donc, je vous suggère de le sortir jusqu'au niveau le plus bas possible ici. Inspectez les entrées directes (Array d'octet) et les sorties du cryptage sur les deux plates-formes. Si, avec les mêmes entrées (binaires), vous n'obtenez pas la même sortie, vous avez un problème de plate-forme. Je pense que cela est peu probable, alors je suppose que vous constaterez que les IVS sont interprétés différemment.


5 commentaires

Merci pour votre réponse! Je peux trouver nulle part dans les bibliothèques .NET ou cacao où vous pouvez définir un IV pour le cryptage RSA ou le décryptage. Je pensais IV uniquement appliqué uniquement aux algorithmes symétriques. Je ne voudrais pas non plus penser que 1 ou 2 sont possibles, mais je ne peux pas non plus comprendre que la clé publique d'un certificat X509 serait interprétée différemment sur les deux plates-formes. Mais j'ai pris le cert du téléphone et je l'ai plongé sur le serveur et il y avait un succès là-bas, donc je ne sais pas quoi penser. Je vais regarder dans les détails de la clé publique de chaque plate-forme pour vous assurer qu'ils sont les mêmes,


Mais je suis sûr que je ne devrais pas être surpris que la même clé publique pourrait générer une sortie différente pour la même entrée sur des passes différentes. C'est le but du remplissage de PKCS n ° 1, quelque chose qu'un ingénieur Apple a confirmé: lists.apple.com/archives/apple-cdsa/2009/jul/msg00032.html


Désolé - quand j'ai dit que l'IV, j'avais peut-être une mauvaise utilisation de la terminologie - il est tard ici :) Je voulais dire fondamentalement la clé de cryptage: les données que vous obtenez de la méthode exportParameters dans .NET ou le contenu de votre paramètre "Key" sur l'iPhone. Je pense que cela mériterait de s'assurer qu'ils sont les mêmes (à l'exclusion de la partie privée bien sûr).


Je vous donne le crédit de réponse parce que vous avez exhorté un nouveau départ.


Mes deux cents ici: Les IV sont utilisés dans des chiffres à blocs, pas nécessairement des algorithmes symétriques.



1
votes

Ceci est ma première réponse sur Stackoverflow, alors pardonnez-moi si je le fais mal!

Je ne peux pas vous donner une réponse complète, mais j'avais des problèmes très similaires lorsque j'ai essayé d'intégrer avec PHP - il semble que que le format des fichiers de certificat d'Apple est un peu différent de celui des autres logiciels qui s'attend (y compris OpenSSL). P>

Voici comment je déchiffrer une signature cryptée dans PHP - J'extrise réellement le module et la PK du public transmis clé manuellement et utilisez cela pour les substances RSA, plutôt que d'essayer d'importer la clé: p> xxx pré>

l'objectif-c qui génère cette clé publique est la suivante: p>

NSData * data = [[SecKeyWrapper sharedWrapper] getPublicKeyBits];
[req addValue:[data base64Encoding] forHTTPHeaderField: @"X-Public-Key"];
data = [[SecKeyWrapper sharedWrapper] getSignatureBytes:[signatureData dataUsingEncoding:NSUTF8StringEncoding]];
[req addValue:[data base64Encoding] forHTTPHeaderField: @"X-Signature"];


1 commentaires

Comme l'a suggéré Jon Grant, je vais inspecter les bits de clé publique eux-mêmes, mais le fait est que l'iPhone lit un certificat X509 groupé avec l'application (non générée sur le téléphone lui-même) et je trouve incroyable que le téléphone lit la clé publique dans différemment. Je vais régler cela en vérifiant les octets, mais je vais être terriblement surpris si c'est le cas.