Https iOS

Bonsoir a tous ,

Je suis nouveau sur ce forum.

J'ai commencé a programmer en objective c (iOS ) .

J'ai plusieurs questions .

En fait , je dois établir une connexion en https sur un serveur.

J'utilise du json rpc , je ne sais pas si le json et https sont liés .

Ensuite , je dois envoyé un certificat , mais je ne sais pas sous quel format. J'ai un certificat en crt, un autre en jks. Je ne sais pas du tout quel format utiliser.

Enfin , comment envoyer ce fichier , quelles méthodes utilisées .


Je vous remercie d'avance !

Je vous serai très reconnaissant.

Réponses

  • CéroceCéroce Membre, Modérateur

    Je suis nouveau sur ce forum.

    Un petit message dans la rubrique Présentation des membres serait bienvenue, afin que nous puissions connaà®tre ton expérience.

    En fait , je dois établir une connexion en https sur un serveur.
    J'utilise du json rpc , je ne sais pas si le json et https sont liés .

    Non, ça n'a rien à  voir. Le JSON, c'est le format dans lequel on communique les données.

    HTTPS permet de chiffrer les échanges entre le serveur et le client.

    Ensuite , je dois envoyé un certificat , mais je ne sais pas sous quel format. J'ai un certificat en crt, un autre en jks. Je ne sais pas du tout quel format utiliser.
    Enfin , comment envoyer ce fichier , quelles méthodes utilisées .

    Mon expérience avec HTTPS sous iOS, c'est qu'on n'a rien à  faire de particulier, tout est géré par Foundation.
    Notamment, l'appli n'a pas besoin de récupérer de clef publique, c'est fait de façon transparente pour nous.

    Jette un oe“il aux classes NSURLConnection (ou NSURLSession sous iOS 7).
    Il existe aussi un bibliothèque open-source, AFNetworking, qui aide beaucoup.
  • Je te remercie pour ta réponse Céroce ! Je travaille dessu depuis 3 jours . Je vais regarder à  cela. 


    Donc , pour finir, je dois meme pas envoyer un certificate ou quoi que ce soit ? Si oui, de quel type ? 


    Je te remercie encore .


    Bonne journée.


  • Personne pour m'aider ? 


    Pour info , j'ai un truc de ce genre : 


     


     NSURLRequest *theRequest=[NSURLRequest requestWithURL:[NSURL URLWithString:@"https://10.xx.xx.xx"]


                                                  cachePolicy:NSURLRequestUseProtocolCachePolicy


                                              timeoutInterval:60.0];


        NSURLConnection *a = [[NSURLConnection alloc]initWithRequest:theRequest delegate:self];


        [a start];


     


    Pour ma méthode connexion :


     


     NSLog(@Authentication challenge);


        


        // Load Certificate


        NSString *thePath = [[NSBundle mainBundle] pathForResource:@server ofType:@crt];


        NSData * p12data = [NSData dataWithContentsOfFile:thePath];


        CFDataRef inP12data = (CFDataRef)CFBridgingRetain(p12data);


        


        SecIdentityRef myIdentity;


        SecTrustRef myTrust;


        extractIdentityAndTrust(inP12data, &myIdentity, &myTrust);


        


        SecCertificateRef myCertificate= NULL;;


        extractIdentityAndTrust(myIdentity, &myCertificate,&myTrust);


        const void *certs[] = { myCertificate };


        CFArrayRef certsArray = CFArrayCreate(NULL, certs, 1, NULL);


        


        NSURLCredential *credential = [NSURLCredential credentialWithIdentity:myIdentity certificates:(__bridge NSArray*)certsArray persistence:NSURLCredentialPersistencePermanent];


        


        [[challenge sender] useCredential:credential forAuthenticationChallenge:challenge];


     


    OSStatus extractIdentityAndTrust(CFDataRef inP12data, SecIdentityRef *identity, SecTrustRef *trust)


     {NSData *pkcs12data = [[NSData alloc] initWithContentsOfFile:[[NSBundle mainBundle] pathForResource:@server ofType:@crt]];


     CFDataRef inPKCS12Data = (__bridge CFDataRef)pkcs12data;


     


     CFStringRef password = CFSTR("motDePasse");


     const void *keys[] = { kSecImportExportPassphrase };


     const void *values[] = { password };


     CFDictionaryRef options = CFDictionaryCreate(NULL, keys, values, 1, NULL, NULL);


     


     CFArrayRef items = CFArrayCreate(NULL, 0, 0, NULL);


     


     OSStatus securityError = SecPKCS12Import(inPKCS12Data, options, &items);


     CFRelease(options);


     CFRelease(password);


     


     if(securityError == errSecSuccess)


     NSLog(@Success opening p12 certificate.);


     


        


        if (options) {


            CFRelease(options);


        }


        


        return securityError;


    }


     


     


     


    Voila. J'ai une erreur je ne sais pas ou . L'appli plante en plein milieu. 


     


    Mais je ne sais pas du tout si je suis dans le bon, pour mon autorisation en https .


    J'ai vu la librairie AFNetworking. Je ne sais pas du tout comment l'intégrer dans mon projet, ou reprendre quelles classes .


     


    Voilà , j'espère que je suis complet. 


  • CéroceCéroce Membre, Modérateur

    1) Merci d'utiliser la balise 'code'.

    2) Avec NSURLConnection, tu envoies une requête synchrone, ça bloque le thread principal, celui qui gère l'interface utilisateur. iOS tue ton application, parce qu'on n'a pas le droit de bloquer le thread principal plus d'une seconde ou deux. (Si tu en as besoin par la suite, NSURLConnection sait envoyer des requêtes asynchrones).

    3) Comme dit précédemment, pour faire du https, on n'a rien à  gérer. Donc, arrête de te prendre la tête avec les certificats. Tu lances les requêtes, et ça se débrouille tout seul.

    4) AFNetworking s'installe facilement via Cocoapods. La page github indique où trouver la doc.


  • Merci de ta réponse encore une foi  . 


     


    Avec mon code : 



    NSURLRequest *theRequest=[NSURLRequest requestWithURL:[NSURL URLWithString:@https://10.xx.xx.xx]cachePolicy:NSURLRequestUseProtocolCachePolicy timeoutInterval:60.0];
        NSURLConnection *a = [[NSURLConnection alloc]initWithRequest:theRequest delegate:self];
        [a start];

     j'ai une erreur du genre : 



    NSURLConnection/CFURLConnection HTTP load failed (kCFStreamErrorDomainSSL, -9843)

    As - tu un example à  me montrer pour les NSURLConnection ? 


    Je te remercie encore de ton aide . 


  • CéroceCéroce Membre, Modérateur
    Déjà , pour voir comment ça fonctionne sans HTTPS:

    NSURL *url = [NSURL URLWithString:@http://www.monsite.com/image.jpg];
    NSURLRequest *request = [NSURLRequest requestWithURL:url];
    [NSURLConnection sendAsynchronousRequest:request queue:[NSOperationQueue mainQueue] completionHandler:^(NSURLResponse *response, NSData *data, NSError *connectionError) {
    if(data)
    self.image = [UIImage imageWithData:data];
    else
    NSLog(@%s error: %@", __PRETTY_FUNCTION__, connectionError);
    }];
    Tu as une erreur SSL; c'est peut-être un problème de certificat pour communiquer en HTTPS.
    La plupart du temps, il n'y a rien à  faire de spécial, mais tu devras peut-être jouer avec NSURLCredentials dans ton cas précis.
    Assure-toi auparavant qu'on peut se connecter sur le site en HTTPS avec un navigateur web.
  • AliGatorAliGator Membre, Modérateur
    mars 2014 modifié #8
    Il n'est nécessaire de mettre du code pour gérer l'envoi du certificat sur les connexions sécurisées que si tu veux faire du SSL Two-Way (c'est à  dire s'il n'y a pas que le serveur qui est sécurisé et signe pour certifier de son identité, mais si le serveur attend aussi que le client (ton appi iOS en l'occurrence) renvoie un certificat (propre à  l'application) pour certifier qui elle est et qu'elle a le droit d'accéder au serveur.

    En pratique c'est un cas d'usage très rare (la plupart des serveurs qu'on interroge qui sont en HTTPS ils le sont juste pour te certifier que c'est bien eux derrière et pas un usurpateur ou un site qui tente de faire du phishing, genre, ils demandent pas de certification dans l'autre sens).
    En général on a juste du SSL One-Way, et du coup le serveur ne nous demande pas de lui renvoyer un certificat pour identifier l'appli, donc tu n'as rien à  écrire dans la méthode de challenge.

    En gros, dans du SSL One-Way, le gendarme (ton appli iOS) demande les papiers d'identité à  l'automobiliste (le serveur) qui doit prouver son identité, et ça c'est géré par iOS, par contre il est rare que le serveur (l'automobiliste) demande ses papiers au gendarme (l'appli iOS) pour qu'il/elle prouve son identité. Ca arrive (dans ce cas c'est du SSL Two-Way) que le serveur demande à  l'appli de s'identifier à  son tour, mais c'est loin d'être le cas d'usage le plus répandu, en général seul l'automobiliste a à  montrer ses papiers au gendarme et pas dans l'autre sens.


    Bref, à  mon avis tu as du SSL One-Way, comme dans 99% des cas, mais si tu es dans les 1% des cas où tu as du Two-Way ça pourrait expliquer ton erreur. Autre cas où tu peux avoir l'erreur c'est si le serveur que tu appelles est en HTTPS, mais que son certificat n'est plus valide (sa carte d'identité / son passeport a expiré, si tu veux)
  • Merci encore de vos réponses (Céroce et AliGator). 


     


    Premièrement, mon serveur est accessible en HTTPS://xx.xx.xx.xx(j'ai même accès par le safari de mon device).


    Maintenant, de la à  dire si c'est one-way ou two-way, je n'en sais strictement rien.


    Ensuite, si j'ai bien compris, j'aurai juste besoin de que le serveur me dise "OK tu peux te connecter en https ". 


    Peux tu me diriger si c'est c'est du one-way ou two-way. 


    Pour info, j'arrive à  récupérer des objects JSON en HTTP (récupérer une clé de session etc ). 


    Enfin, mon certificat est valable jusqu'en 2024. 


     


    Je vous remercie de votre aide . 

  • AliGatorAliGator Membre, Modérateur
    Quand tu dis "mon certificat" tu parles duquel ? De celui que tu as installé sur le serveur, car c'est toi qui administres le serveur ? Ou d'un certificat que tu es sensé insérer dans ton appli iPhone et que ceux qui gèrent le serveur t'ont demandé de générer ? Ou quoi ?

    Si tu peux te connecter en https depuis ton navigateur, et que le certificat utilisé sur le serveur est valable et n'est pas self-signed mais bien signé par une autorité de certification (VeriSign, StartSSL, ...) alors je confirme tu n'as rien à  faire dans ton code.

    Si le certificat est auto-signé (et non pas certifié par une autorité de certification) par contre je ne suis pas sûr, mais je pense que par mesure de sécurité iOS te refuse la connexion. Dans ce cas soit tu utilises à  la place sur ton serveur un vrai certificat signé (tu peux en obtenir un gratuitement de classe 1 sur startssl.com, ce qui suffit pour signer un nom de domaine), soit si tu veux garder ton self-signed certificate alors oui tu auras peut-être une ou 2 lignes de code pour dire à  ton appli "même si le gars il me présente une carte d'identité mais qui n'est pas tamponnée par l'état, et donc que toi tu restes sceptique et par mesure de sécurité tu ne le crois pas et refuse, moi je te dis tant pis je considère que son certificat est valide quand même". Dans ce cas les lignes de code en question ne consistera en aucun cas à  "demander à  l'iPhone d'envoyer un certificat au serveur" ou de manipuler des fichiers de certificat côté iPhone, mais de juste lui dire "YES" quand il demande s'il faut truster.
    Car encore une fois, ce n'est pas le serveur qui demande à  l'iPhone de certifier son identité en envoyant un certificat, mais l'iPhone qui demande au serveur de prouver son identité (en envoyant un certificat à  l'iPhone... qui va vérifier que ce certificat retourné par le serveur est authentique et pas juste signé par le fils du voisin)
  • Encore merci de ta réponse Aligator.

    Alors , mon crt est bien celui qui est installé sur mon serveur (je te confirme cela demain) , ce n'est pas moi qui administre le serveur .

    Ensuite , justement , je sais pas si c'est lequel que je dois installer sur mon iphone .

    Lorsque vous dites , tu n'as rien a gérer , concrètement qu'est ce qu'il faut faire car lorsque j'essaie mon URL avec https , j'ai l'erreur mentionné plus haut .

    Peut être créer un autre certificat ou quoi ?


    Merci encore de ton aide .
  • AliGatorAliGator Membre, Modérateur
    Si le crt que tu as c'est celui du serveur laisse le sur le serveur il a rien à  faire chez toi (comment et pourquoi t'es allé le récupérer d'ailleurs ?). T'as pas du tout à  l'installer sur l'iPhone ou quoi si c'est le certificat du serveur c'est sur le serveur c'est tout.


    Pour l'erreur que tu as faudrait afficher + de détails, faire un NSLog sur la NSError, rechercher la signification du code d'erreur.
  • Bonjour , 


     


    voilà  en fait , mon code ressemble à  ceci : 


     


     



     URL = [NSString stringWithFormat:@https:;//%@:%@/web/session/get_session_info",serveur,port];
            NSURL * serviceURL = [NSURL URLWithString:URL];
            JSONRPCService * service = [JSONRPCService serviceWithURL:serviceURL version:JSONRPCVersion_2_0];
            
            NSMutableDictionary *dict = [[NSMutableDictionary alloc] init];
            NSString *req =[self generate_json_request:dict];
            
            [[service callMethodWithNameAndNamedParams:req, nil]
             completion:^(JSONRPCMethodCall * methodCall,NSDictionary *result,NSError * error)
             {
                NSLog(@%@",error);
             }];

     Mon nslog ne s'affiche même pas. Mon url me permet de récupérer une session ID . 


    Et l'erreur que j'ai dans le log est : 



     NSURLConnection/CFURLConnection HTTP load failed (kCFStreamErrorDomainSSL, -9813)

    J'espère que je suis assez précis. 


     


    Une dernière chose, j'ai aussi des fichiers formats .P12, .CSR , .KEY. 


    Peut être ca sera plus claire ? 


     

  • AliGatorAliGator Membre, Modérateur
    Suffit de faire une petite recherche Google pour voir que ce code d'erreur kCFStreamErrorDomainSSL -9813 correspond à  l'erreur "Certificate chain not verified" autrement dit ton serveur utilise un certificat SSL auto-signé et pas validé par une autorité de certification. Autrement dit comme expliqué déjà  plus haut c'est comme s'il te présentait une carte d'identité non tamponnée par l'état ou la mairie ou autre.


    Du coup tu as plusieurs choix :

    - soit tu lui fais confiance même s'il te présente pourtant des papiers d'identité dont tu ne pu pas vérifier l'authenticité

    - soit tu te portes garant pour le serveur, en embarquant dans ton application le tampon ayant servi à  tamponner le certificat du serveur, autrement dit tu agis en tant qu'autorité de certification pour le certificat du serveur (qui n'a pas été tamponné par une autorité de certification reconnue et officielle mais à  bien été tamponné par qqun, même si ce qqun n'est pas une autorité officielle " et tu vas dire à  ton app que tu te portes garant pour / fais confiance à  cette autorité malgré tout

    - soit, et honnêtement c'est la solution la plus propre en terme de sécurité si tu as moyen de faire la demande à  ceux qui gèrent le serveur, tu leur demandes de mettre un vrai certificat SSL digne de ce nom sur leur serveur, un certificat signé par une vraie autorité de certification. On peut obtenir des certificats SSL de classe 1 sur startssl.com, c'est totalement gratuit et amplement suffisant pour de l'identification de nom de domaine d'un site " je l'ai fait en seulement quelques minutes pas plus tard que lundi dernier d'ailleurs sur un serveur à  moi
  • Merci encore une foi Aligator pour ta réponse. 


     


    Pour l'instant, c'est que des testes, donc à  mon avis pour le certificat , faudrait encore attendre ^^.


    Mais je comprends qu'en terme de propreté , c'est la meilleur solution . 


     


    Comment je m'y prends pour : 


    -Soit faire confiance même si il me présente ses papiers ?


    -Soit me porter garant , et donc embarquer le tampon dans mon app ? 


  • AliGatorAliGator Membre, Modérateur
    Les certificats ça marche par chaà®ne de confiance :
    - Un certificat est signé par un certificat parent
    - Ce certificat parent est lui-même signé par un certificat parent
    - Etc, etc, jusqu'à  ce que le parent soit un "Root Certificate", qui sera une "Autorité de Certification" ("CA" ou Certificate Authority en anglais) reconnue

    D'ailleurs si tu vas sur le site avec Safari depuis ton iPhone, tu vas sans doute avoir au minimum une alerte disant "l'autorité de ce site n'est pas certifiée, continuer quand même" avec les boutons comme "Se fier", etc... cela correspond bien au fait que le certificat n'est pas signé avec une autorité reconnue et que Safari te demande si tu veux quand même lui faire confiance malgré tout


    Le plus simple dans ton cas, surtout si c'est du test pour l'instant, c'est d'installer le certificat de l'autorité de certification parente (celle ayant signé le certificat du serveur) directement sur ton iPhone (dans la keychain de l'iPhone quoi), au moins le temps de tester.
    Bien sûr, cela ne fonctionnera alors que sur les iPhones ayant installé le certificat de la CA. Ca ne marchera pas si tu distribues l'appli sur d'autres iPhones sauf évidemment s'ils installent eux-même également le même certificat dans les réglages de leur iPhone.

    Cela t'évitera d'embarquer le certificat dans le bundle de l'app et d'avoir ensuite à  mettre du code pour dire à  ton app quoi faire.

    Dans ton cas, vu que c'est certainement un certificat auto-signé, comme son nom l'indique ça veut dire que le certificat parent qui a servi à  signer/tamponner le certificat du serveur, c'est le certificat du serveur lui-même (il s'est signé avec lui-même, comme si tu avais tamponné ta carte d'identité avec ton propre tampon). Donc dans ce cas c'est lui-même le certificat du serveur.
    Par exemple tu t'envoies le ".cer" par mail et tu ouvres le mail avec ton iPhone et tap sur la pièce-jointe, et l'iPhone va te proposer d'installer le certificat dans la Keychain de ton iPhone ce qui fait que tout iOS reconnaà®tra ce certificat.


    Si par contre tu avais à  faire fonctionner ton application à  long terme avec ce serveur et que ledit serveur ne comptais pas passer à  un certificat signé avec une autorité digne de ce nom (comme startssl ou VeriSign ou autre), genre diffuser ton appli sur le store, faudra évidemment embarquer le certificat ou faire autrement, mais là  si c'est juste pour tester sur qques iPhones autant installer le certif dans la keychain de ton iPhone et basta.
  • Oui Aligator, effectivement c'est bien un auto-signé, car dans n'importe quelle navigateur (que ce soit sur le pc ou autres),


    il me demande de "continuer" etc...


     


    Maintenant, pour l'histoire de l'installation du certificat avec le mail je l'ai déjà  fait. 


    Mais j'ai installé le .crt , et je l'ai bien sur mon téléphone dans Général->Profils . Mais est - ce le crt que je dois installé ? Où alors,


    il doit être au format "cer" ou autre chose, et la je demande à  celui qui administre le serveur le bon fichier. 


     


    Enfin, oui pour l'instant c'est que des tests, pas de publication sur l'Appstore ... 


     


    Encore merci de ton aide Aligator, je sens que je me rapproche du but ! 


  • Bonjour,


     


    Oui apparemment c'est la même chose entre .crt et .cer.  Fait une petite recherche sur Internet :)


     


    sinon, si tu utilise AFNetworking, il me semble que tu peux dire à  ton application iOS de valider toutes les connexions https même si le certificats est auto-signé, invalide,... ( à  mettre à  YES juste en mode test).


     


    Sinon pour mettre tout ça en mode production, le mieux c'est de corrigé ton problème au niveaux du serveur et de ne pas utiliser un certificat auto-signé. 


  • Bonjour Samir, 


    merci de ta réponse . 


     


    Je n'utilise pas AFNetworking (je ne sais pas comment l'utiliser ...) . 


    Mais j'ai vu une méthode : 



    -(BOOL)connection:(NSURLConnection *)connection canAuthenticateAgainstProtectionSpace:(NSURLProtectionSpace *)protectionSpace{
        return YES;
    }

    Je ne sais pas si c'est de ca que tu parle ? 

  • mirail67mirail67 Membre
    mars 2014 modifié #20

    Voila , j'ai installé mon certificat sur mon device, mais cela fonctionne toujours pas . 


    En fait, je ne sais pas par quelle moyen puis je dire à  mon device "Oui, fais confiance à  ce serveur " . 


    Voici mon screenshot : 


     IMG_1045.PNG


    (j'espère que vous voyez mon image )


  • NasatyaNasatya Membre
    mars 2014 modifié #21

    Alors non on ne voit pas ton images... Mais pour ta question y a un thread sur la question sur stackoverflow


    http://stackoverflow.com/questions/933331/how-to-use-nsurlconnection-to-connect-with-ssl-for-an-untrusted-cert/2033823#2033823


    Il y a une méthode privé de NSURLRequest ( setAllowsAnyHTTPSCertificate: forHost: ) J'ai bien dit privé donc utilisable seulement et uniquement pour les tests en attendant d'avoir le certificat définitif. De toute façon Apple rejettera ton application si tu la poste en utilisant cette méthode.


  • Ah désolé, je ne sais pas comment mettre une image . 


    Nasatya, cela ne fonctionne pas chez moi cette solution. Toujours l'erreur 



    SURLConnection/CFURLConnection HTTP load failed (kCFStreamErrorDomainSSL, -9813)

    :s

  • Bonjour,


     


    Si tu regarde le détail de ton erreur ici : http://www.opensource.apple.com/source/libsecurity_ssl/libsecurity_ssl-36800/lib/SecureTransport.h


     


    -9813,    /* cert chain not verified by root */


     


    Donc c'est bien un certificat auto-signé. ( relais les messages de @Aligator pour mieux comprendre).


    Après c'est un peu bizarre que ça ne marche pas après que t'as installé le certificat sur ton iPhone !!


     


    Sinon tu peux faire autrement pour géré un certificats auto-signé ( y a des bout de code sur internet), même si il me semble que c'est vraiment déconseillé.


     


    Plus de lecture ici : https://developer.apple.com/library/ios/technotes/tn2232/_index.html

  • Oui, grâce à  @Aligator, j'ai su que c'était un certificat auto-signé , donc cette méthode ne fonctionne pas chez moi. 


    Je vais faire un tour sur ton lien . 


     


    Merci à  toi samir 


  • Salut à  tous , 


     


    personne peut me lancer sur le bon chemin ? Je commence à  désespérer , je fais des recherches depuis plus de deux semaine  :'(


    Mais par contre, je suis de plus en plus proche  ::)

  • CéroceCéroce Membre, Modérateur


    personne peut me lancer sur le bon chemin ?




    On te l'a déjà  indiqué: arrête de t'ennuyer avec le certificat auto-signé. Créez un certificat signé par une autorité de certif et installez-le sur votre foutu serveur. De toute façon, il faudra le faire.

Connectez-vous ou Inscrivez-vous pour répondre.