(Réglé) Keychain, ajouter une key

Ben77650Ben77650 Membre
juillet 2014 modifié dans API UIKit #1

Bonjour à  tous,


 


Dans le cadre de mon application je doit utiliser une keychain pour stocker 3 informations: un couple d'identifiants et un tableau (de favoris)


 


Seul souci c'est que j'arrive à  court de key, en effet kSecValueData est utilisé pour mon username et kSecValueRef pour mon mot de passe. Le tableau n'a donc aucune clé propre à  lui, et je peut pas lui mettre kSecValueData sous peine de doublon.


 


J'avais donc essayé (un peu à  l'arrache certes) de créer une nouvelle clé avec le nom kValueData, seul souci c'est qu'il ne me la reconnais pas comme CFTypeRef.


 


Bon je ne vous parle même pas de la difficulté pour modifier ce fichier, puisque j'ai toujours droit à  ce genre de message, et que donc j'ai du passer par la console.



“SecItem.h” is locked for editing and you may not be able to save your changes. Do you want to unlock it?


 


“SecItem.h” is currently locked because you do not own the parent folder and have no write permission for it.


 




The file “SecItem.h” could not be unlocked.


 


Could not add write permission to the parent folder because you do not own it. Try modifying the permissions of the folder in the Finder or Terminal.


 



 


 


Comment puis je faire s'il vous plait pour me créer une nouvelle clé dans laquelle je lui stockerais mon tableau ?


 


Merci d'avance à  ceux qui m'aideront


Mots clés:

Réponses

  • CéroceCéroce Membre, Modérateur
    Personnellement, devant la difficulté à  utiliser les API du Keychain, je me suis rabattu sur FXKeychain:

    https://github.com/nicklockwood/FXKeychain

    Je ne pensais pas que c'était difficile (enregistrer un login et un mot de passe, ça doit être du gâteau), mais après deux heures perdues, j'ai admis ma défaite !
  • Ben77650Ben77650 Membre
    juillet 2014 modifié #3

    Effectivement ça a pas l'air archi compliqué d'enregistrer des id de connexion et d'aller les récupérer derrière


     


    Tout se fait aussi bêtement que ça



    KeychainItemWrapper *keychainItem = [[KeychainItemWrapper alloc] initWithIdentifier:@AppName accessGroup:nil];

    [keychainItem setObject:_email.text forKey:(__bridge id)(kSecValueData)];
    [keychainItem setObject:[self md5:_password.text] forKey:(__bridge id)(kSecAttrAccount)];
                        
    NSString *adEmail = [keychainItem objectForKey:(__bridge id)(kSecValueData)];
    NSString *pwd = [keychainItem objectForKey:(__bridge id)(kSecAttrAccount)];

    Après quand il s'agit d'enregistrer une 3e donnée qui est du même type que la 1ère ça doit pouvoir se faire aussi, sans avoir à  utiliser autre chose, enfin je pense


     


    On m'a soufflé ça:


     


    @ben77650 In a normal situation, kSecAttrAccount holds the username (not encrypted) and kSecValueData holds the password (encrypted). If you need to store more than one you can set a custom identifier per keychain item.

     


    Seulement j'arrive pas / je ne sais pas comment déclarer un identifiant personnalisé pour un objet de type Keychain d'où ma question ici


  • Ben77650Ben77650 Membre
    juillet 2014 modifié #4

    Voila ce que j'ai modifié dans mon fichier SecItem.h si ça peut vous aider à  comprendre



    extern CFTypeRef kSecValueData
        __OSX_AVAILABLE_STARTING(__MAC_10_6, __IPHONE_2_0);
    extern CFTypeRef kSecValueRef
        __OSX_AVAILABLE_STARTING(__MAC_10_6, __IPHONE_2_0);
    extern CFTypeRef kSecValuePersistentRef
        __OSX_AVAILABLE_STARTING(__MAC_10_6, __IPHONE_2_0);

    extern CFTypeRef kValueData
        __OSX_AVAILABLE_STARTING(__MAC_10_6, __IPHONE_2_0);


    extern CFTypeRef kSecAttrAccessible
        __OSX_AVAILABLE_STARTING(__MAC_10_9, __IPHONE_4_0);
    extern CFTypeRef kSecAttrAccessGroup
        __OSX_AVAILABLE_STARTING(__MAC_10_9, __IPHONE_3_0);
    extern CFTypeRef kSecAttrSynchronizable
        __OSX_AVAILABLE_STARTING(__MAC_10_9, __IPHONE_7_0);
    extern CFTypeRef kSecAttrSynchronizableAny
        __OSX_AVAILABLE_STARTING(__MAC_10_9, __IPHONE_7_0);
    extern CFTypeRef kSecAttrCreationDate
        __OSX_AVAILABLE_STARTING(__MAC_10_6, __IPHONE_2_0);
    extern CFTypeRef kSecAttrModificationDate
        __OSX_AVAILABLE_STARTING(__MAC_10_6, __IPHONE_2_0);
    extern CFTypeRef kSecAttrDescription
        __OSX_AVAILABLE_STARTING(__MAC_10_6, __IPHONE_2_0);
    extern CFTypeRef kSecAttrComment
        __OSX_AVAILABLE_STARTING(__MAC_10_6, __IPHONE_2_0);
    extern CFTypeRef kSecAttrCreator
        __OSX_AVAILABLE_STARTING(__MAC_10_6, __IPHONE_2_0);
    extern CFTypeRef kSecAttrType
        __OSX_AVAILABLE_STARTING(__MAC_10_6, __IPHONE_2_0);
    extern CFTypeRef kSecAttrLabel
        __OSX_AVAILABLE_STARTING(__MAC_10_6, __IPHONE_2_0);
    extern CFTypeRef kSecAttrIsInvisible
        __OSX_AVAILABLE_STARTING(__MAC_10_6, __IPHONE_2_0);
    extern CFTypeRef kSecAttrIsNegative
        __OSX_AVAILABLE_STARTING(__MAC_10_6, __IPHONE_2_0);
    extern CFTypeRef kSecAttrAccount
        __OSX_AVAILABLE_STARTING(__MAC_10_6, __IPHONE_2_0);

    extern CFTypeRef kValueData
        __OSX_AVAILABLE_STARTING(__MAC_10_6, __IPHONE_2_0);

    extern CFTypeRef kSecAttrService
        __OSX_AVAILABLE_STARTING(__MAC_10_6, __IPHONE_2_0);
    extern CFTypeRef kSecAttrGeneric
        __OSX_AVAILABLE_STARTING(__MAC_10_6, __IPHONE_2_0);
    extern CFTypeRef kSecAttrSecurityDomain
        __OSX_AVAILABLE_STARTING(__MAC_10_6, __IPHONE_2_0);
    extern CFTypeRef kSecAttrServer
        __OSX_AVAILABLE_STARTING(__MAC_10_6, __IPHONE_2_0);
    extern CFTypeRef kSecAttrProtocol
        __OSX_AVAILABLE_STARTING(__MAC_10_6, __IPHONE_2_0);
    extern CFTypeRef kSecAttrAuthenticationType
        __OSX_AVAILABLE_STARTING(__MAC_10_6, __IPHONE_2_0);
    extern CFTypeRef kSecAttrPort
        __OSX_AVAILABLE_STARTING(__MAC_10_6, __IPHONE_2_0);
    extern CFTypeRef kSecAttrPath
        __OSX_AVAILABLE_STARTING(__MAC_10_6, __IPHONE_2_0);
    extern CFTypeRef kSecAttrSubject
        __OSX_AVAILABLE_STARTING(__MAC_10_6, __IPHONE_2_0);
    extern CFTypeRef kSecAttrIssuer
        __OSX_AVAILABLE_STARTING(__MAC_10_6, __IPHONE_2_0);
    extern CFTypeRef kSecAttrSerialNumber
        __OSX_AVAILABLE_STARTING(__MAC_10_6, __IPHONE_2_0);
    extern CFTypeRef kSecAttrSubjectKeyID
        __OSX_AVAILABLE_STARTING(__MAC_10_6, __IPHONE_2_0);
    extern CFTypeRef kSecAttrPublicKeyHash
        __OSX_AVAILABLE_STARTING(__MAC_10_6, __IPHONE_2_0);
    extern CFTypeRef kSecAttrCertificateType
        __OSX_AVAILABLE_STARTING(__MAC_10_6, __IPHONE_2_0);
    extern CFTypeRef kSecAttrCertificateEncoding
        __OSX_AVAILABLE_STARTING(__MAC_10_6, __IPHONE_2_0);
    extern CFTypeRef kSecAttrKeyClass
        __OSX_AVAILABLE_STARTING(__MAC_10_6, __IPHONE_2_0);
    extern CFTypeRef kSecAttrApplicationLabel
        __OSX_AVAILABLE_STARTING(__MAC_10_6, __IPHONE_2_0);
    extern CFTypeRef kSecAttrIsPermanent
        __OSX_AVAILABLE_STARTING(__MAC_10_6, __IPHONE_2_0);
    extern CFTypeRef kSecAttrApplicationTag
        __OSX_AVAILABLE_STARTING(__MAC_10_6, __IPHONE_2_0);
    extern CFTypeRef kSecAttrKeyType
        __OSX_AVAILABLE_STARTING(__MAC_10_6, __IPHONE_2_0);
    extern CFTypeRef kSecAttrKeySizeInBits
        __OSX_AVAILABLE_STARTING(__MAC_10_6, __IPHONE_2_0);
    extern CFTypeRef kSecAttrEffectiveKeySize
        __OSX_AVAILABLE_STARTING(__MAC_10_6, __IPHONE_2_0);
    extern CFTypeRef kSecAttrCanEncrypt
        __OSX_AVAILABLE_STARTING(__MAC_10_6, __IPHONE_2_0);
    extern CFTypeRef kSecAttrCanDecrypt
        __OSX_AVAILABLE_STARTING(__MAC_10_6, __IPHONE_2_0);
    extern CFTypeRef kSecAttrCanDerive
        __OSX_AVAILABLE_STARTING(__MAC_10_6, __IPHONE_2_0);
    extern CFTypeRef kSecAttrCanSign
        __OSX_AVAILABLE_STARTING(__MAC_10_6, __IPHONE_2_0);
    extern CFTypeRef kSecAttrCanVerify
        __OSX_AVAILABLE_STARTING(__MAC_10_6, __IPHONE_2_0);
    extern CFTypeRef kSecAttrCanWrap
        __OSX_AVAILABLE_STARTING(__MAC_10_6, __IPHONE_2_0);
    extern CFTypeRef kSecAttrCanUnwrap
        __OSX_AVAILABLE_STARTING(__MAC_10_6, __IPHONE_2_0);

    Seulement quand je fais ça:



    [keychainItem setObject:jsonString forKey:(__bridge id)kValueData];

    Il me dit ça:


    Use of undeclared identifier 'kValueData'; did you mean 'kSecValueData'?

    Une idée peut être s'il vous plait ?


  • AliGatorAliGator Membre, Modérateur
    Nan mais pourquoi vouloir modifier un header système comme SecItem.h ? Modifier un header système, ça te choque pas ? Et avoir les warnings qui te disent en plus que c'est verrouillé ça ne t'a pas mis la puce à  l'oreille comme quoi c'était une mauvaise idée ?
  • zoczoc Membre
    juillet 2014 modifié #6

    Je rejoint Ali. De plus rajouter une référence "extern" vers un "objet" CTypeRef ne va pas rajouter l'objet réel dans la librairie du système, donc zéro chance que cela marche.


     


    Sinon, quel est l'intérêt de stocker des données non sensibles (favoris) dans le trousseau alors qu'il y a d'autres choses bien plus adaptées et souples pour cela (NSUserDefaults) ?


  • Ben77650Ben77650 Membre
    juillet 2014 modifié #7

    Bah on m'avais conseillé les Keychain plutôt que le NSUserDefaults...


     


    Ali bah comment je fais pour faire ça alors si c'est pas comme ça ?


     


     If you need to store more than one you can set a custom identifier per keychain item.

  • Pour les mots de passe et identifiants on considere que ce soin des données sensible ça doit aller dans le Keychain


    Pour le reste ça reste à  voir mais le plus souvent ça peut aller dans le userDefault.


  • Ben77650Ben77650 Membre
    juillet 2014 modifié #9

    En fait j'ai besoin de stocker un tableau de tableau c'est possible ça avec le NSUserDefaults ?


     


    Je peut ajouter/retirer à  souhait une "cellule" du tableau qu'il y a dans mon UserDefaults ?


     


    J'ai besoin d'ajouter des annonces (sous forme de tableau) dans ce tableau et de le garder en mémoire c'est faisable ?


  • Oui c'est faisable si c'est la question après si tu as besoin de faire ça peut être qu'il y a d'autre façon de faire que de sauvegarder des arrays. Parce que ni le keychain ni le NSUserDefault ne sont prévu pour ça.


  • Ben77650Ben77650 Membre
    juillet 2014 modifié #11

    Tu préconise quoi comme solution ?


     


    Mon boss veut pas ajouter une colonne a la BDD ou ne veut pas un nouveau WebService  (qui fasse une récupération des éléments par id)  ;)


  • tout dépend de la quantité d'infos à  stocker, si c'est important -> core data, sinon tu peux sérialiser un NSArray, et le garder dans un fichier que tu peux écrire dans le "Docs directory", pour le manipuler il faut le lire en mémoire (mais il faut vraiment qu'il soit très gros pour que la taille soit un problème)

  • il y a plein d'exemples sur le net comme ceci:


     


    @implementation NSArray(Plist)

    -(BOOL)writeToPlistFile:(NSString*)filename{
    NSData * data = [NSKeyedArchiver archivedDataWithRootObject:self];
    NSArray * paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
    NSString * documentsDirectory = [paths objectAtIndex:0];
    NSString * path = [documentsDirectory stringByAppendingPathComponent:filename];
    BOOL didWriteSuccessfull = [data writeToFile:path atomically:YES];
    return didWriteSuccessfull;
    }

    +(NSArray*)readFromPlistFile:(NSString*)filename{
    NSArray * paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
    NSString * documentsDirectory = [paths objectAtIndex:0];
    NSString * path = [documentsDirectory stringByAppendingPathComponent:filename];
    NSData * data = [NSData dataWithContentsOfFile:path];
    return [NSKeyedUnarchiver unarchiveObjectWithData:data];
    }


    je n'ai pas vérifié mais cela me semble correct...

  • Mon tableau est constitué de 16 objets, 14 NSString, 1 BOOL et 1 NSArray.


     


    CoreData pas sur que ça soit une bonne idée, vu que ça implique une BDD avec tout ce qui en découle derrière.


     


    La sérialisation peut effectivement être un moyen intéressant, j'avoue ne pas y avoir pensé, merci de m'avoir soufflé ça.


     


    Par contre je vois pas de quoi tu parles quand tu évoques le docs directory.


     


    Si vous avez d'autres idées je suis preneur ;)

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