Group TMR Temporary Key
Les GroupTMRTemporaryKey
sont un mécanisme permettant de rejoindre un groupe par un mécanisme de 2-man rule, comme pour le stockage des identités.
L'idée est de chiffrer la clé du groupe pour un certain Auth Factor (une adresse email, ou un numéro de téléphone), avec une certaine overEncryptionKey
qui sera stockée par vos serveurs (comme la twoManRuleKey
pour le stockage des identités).
Ensuite, pour rejoindre le groupe, le destinataire reçoit un challenge
par email ou SMS, valable 6h, et doit le répéter dans l'application pour prouver qu'il maitrise le Auth Factor, et peut accéder à la clé du groupe.
Cette fonctionnalité est particulièrement utile pour ajouter comme membre à un groupe un utilisateur qui n'est pas encore inscrit sur votre application, par exemple au moment de lui envoyer une invitation.
Création d'une GroupTMRTemporaryKey
Les membres d'un groupe ayant le statut d'administrateur peuvent créer une GroupTMRTemporaryKey
pour le groupe.
Pour créer une GroupTMRTemporaryKey
, il faut l'ID du groupe, et utiliser la méthode sdk.createGroupTMRTemporaryKey()
. Cette méthode prend comme arguments l'ID du groupe pour lequel créer la clé temporaire groupId
, ainsi qu'un objet d'options :
authFactor
, qui lui même contient le type de l'Auth Factor utilisé ('EM'
pour une adresse email,'SMS'
pour un numéro de téléphone), et la valeur de cet Auth Factor ;isAdmin
Un booléen définissant le statut administrateur de l'utilisateur lorsqu'il rejoindra le groupe ;rawOverEncryptionKey
, qui est la clé à utiliser pour protéger ceTmrAccess
, doit absolument être l'encodage en base64 d'un buffer cryptographiquement aléatoire de 64 octets ;- Optionnellement,
forceGroupUpdate
, Un booléen pour forcer la mise à jour du groupe connue localement avant de créer laGroupTMRTemporaryKey
, par défaut àfalse
TIP
Afin d'assurer la confidentialité end-to-end, la rawOverEncryptionKey
doit n'être accessible qu'à la personne qui crée la GroupTMRTemporaryKey
et au destinataire qui rejoindra le groupe.
Il est de la responsabilité de votre serveur de stocker ces rawOverEncryptionKey
et d'en limiter l'accès à l'utilisateur qui crée la GroupTMRTemporaryKey
et l'utilisateur invité.
Si plusieurs utilisateurs doivent ajouter des GroupTMRTemporaryKey
à destination du même Auth Factor, il convient de créer des rawOverEncryptionKey
s différentes pour chacun. Vous pouvez également créer une rawOverEncryptionKey
différente pour chaque ajout de GroupTMRTemporaryKey
, même si c'est le même utilisateur qui l'ajoute pour le même Auth Factor, si cela est plus simple pour vous.
TIP
L'option forceGroupUpdate
permet d'optimiser les requêtes réseau, en forçant la mise à jour du groupe avant d'essayer de créer une GroupTMRTemporaryKey
.
Si le groupe connu localement n'est pas à jour, la création échoura un première fois, et la fonction se relancera de manière récursive avec forceGroupUpdate
à true
.
La méthode sdk.createGroupTMRTemporaryKey()
rend un objet contenant l'ID de la GroupTMRTemporaryKey
créée. Cet ID n'est pas secret, et peut être transmis à votre serveur. Il peut servir à administrer la GroupTMRTemporaryKey
, ou encore à choisir quelle GroupTMRTemporaryKey
utiliser pour rejoindre un groupe.
Exemple d'utilisation :
// Chaque `rawOverEncryptionKey` doit nécessairement être un buffer de 64 octets aléatoires cryptographiquement sécurisé, encodé en base64.
const rawOverEncryptionKey = await sealdSdk.utils.generateB64EncodedSymKey()
// Création d'une `GroupTMRTemporaryKey`
const tmrAccess = await sealdSdk.createGroupTMRTemporaryKey(groupInfo.id, {
rawOverEncryptionKey,
authFactor: { type: 'EM', value: 'test@example.com' },
isAdmin: true
})
// Maintenant, vous pouvez envoyer le `tmrAccess.id` avec la `rawOverEncryptionKey` à vos serveurs pour les enregistrer.
SealdError* err = NULL;
char* groupId = "UUID"; // L'ID du groupe
char* authFactorType = "EM";
char* authFactorValue = "user@email.com";
int isAdmin = 0; // 1 for admin, 0 otherwise
int rawOverEncryptionKeyLen = 64;
unsigned char* rawOverEncryptionKeyBytes = randomBuffer(rawOverEncryptionKeyLen); // buffer de 64 octets aléatoires cryptographiquement sécurisé.
SealdGroupTMRTemporaryKey* gTMRCreated = NULL;
int errCode = SealdSdk_CreateGroupTMRTemporaryKey(sdk1, groupId, authFactorType, authFactorValue, isAdmin, rawOverEncryptionKeyBytes, rawOverEncryptionKeyLen, &gTMRCreated, &err);
NSError* error = nil;
NSString* groupId = @"UUID"; // L'ID du groupe
NSData* rawOverEncryptionKey = randomData(64); // buffer de 64 octets aléatoires cryptographiquement sécurisé.
SealdTmrAuthFactor* tmrAuthFactor = [[SealdTmrAuthFactor alloc] initWithValue:@"user@email.com" type:@"EM"];
SealdGroupTmrTemporaryKey* gTMRKey = [sdk createGroupTMRTemporaryKeyWithGroupId:groupId
authFactor:tmrAuthFactor
isAdmin:NO
rawOverEncryptionKey:rawOverEncryptionKey
error:&error];
let groupId = "UUID" // L'ID du groupe
let tmrAuthFactor = SealdTmrAuthFactor(value: "user@email.com", type: "EM")
let rawOverEncryptionKey = randomData(64) // buffer de 64 octets aléatoires cryptographiquement sécurisé.
let gTMRTKCreated = try await sdk.createGroupTMRTemporaryKeyAsync(
withGroupId: groupId,
authFactor: tmrAuthFactor,
isAdmin: false,
rawOverEncryptionKey: rawOverEncryptionKey)
val groupId = "UUID" // L'ID du groupe
val tmrAuthFactor = AuthFactor(AuthFactorType.EM, "user@email.com")
val rawOverEncryptionKey = randomData(64) // buffer de 64 octets aléatoires cryptographiquement sécurisé.
val gTMRCreated = sdk.createGroupTMRTemporaryKey(groupId, tmrAuthFactor, rawOverEncryptionKey, isAdmin = true)
String groupId = "UUID"; // L'ID du groupe
String authFactorType = "EM";
String authFactorValue = "user@email.com";
Uint8List rawOverEncryptionKey = randomData(64); // buffer de 64 octets aléatoires cryptographiquement sécurisé.
final SealdGroupTMRTemporaryKey gTMRTKCreated =
await sdk.createGroupTMRTemporaryKeyAsync(groupId, authFactorType,
authFactorValue, rawOverEncryptionKey);
Administration des GroupTMRTemporaryKey
Il existe trois fonctions pour administrer les GroupTMRTemporaryKey
:
La méthode
sdk.listGroupTMRTemporaryKeys()
permet de lister toutes lesGroupTMRTemporaryKey
existantes pour un groupe donné.La méthode
sdk.searchGroupTMRTemporaryKeys()
permet de lister toutes lesGroupTMRTemporaryKey
utilisable avec untmrJWT
donné. LetmrJWT
doit être le JWT associé à un Auth Factor. Il est possible de récupérer ce JWT avec la méthodessks2MR.getFactorToken()
TIP
Les fonctions listGroupTMRTemporaryKeys
et searchGroupTMRTemporaryKeys
, si l'option all
est mise à true
, retournent toutes les pages existante à partir de la page spécifiée par le paramètre page
.
- La méthode
sdk.deleteGroupTMRTemporaryKey()
permet de supprimer uneGroupTMRTemporaryKey
.
Convertir une GroupTMRTemporaryKey
pour rejoindre un groupe
Pour convertir une GroupTMRTemporaryKey
, il faut d'abord prouver que l'on contrôle le Auth Factor destinataire de celui-ci. Pour ceci, il faut récupérer un JWT depuis le serveur SSKS avec la méthode ssks2MR.getFactorToken()
. Cette méthode nécessite bien entendu d'être authentifié auprès de SSKS, c'est-à-dire soit d'avoir déjà un authenticatedSessionId
, soit d'utiliser le point d'API POST /tmr/back/challenge_send/
(avec force_auth
à true
) pour obtenir un challenge, et passer ce challenge lors de l'appel à ssks2MR.getFactorToken()
.
Une fois qu'on a ce token, il faut utiliser la méthode sdk.convertGroupTMRTemporaryKey()
. Cette méthode prend comme arguments :
groupId
, l'ID du groupe concerné ;temporaryKeyId
, l'ID de laGroupTMRTemporaryKey
concernée ;- la
rawOverEncryptionKey
utilisée ; - optionnellement, une option
deleteOnConvert
pour supprimer laGroupTMRTemporaryKey
après conversion.
Exemple d'utilisation simple :
// Récupération d'un tmrJWT
const getFactorTokenResponse = await sdk.ssks2MR.getFactorToken({ sessionId: ssksSessionId, authFactor, challenge })
await convertGroupTMRTemporaryKey(
groupId, // L'ID du groupe concerné
temporaryKeyId, // L'ID de la `GroupTMRTemporaryKey` concernée
getFactorTokenResponse.token, // Le token obtenu par l'appel de `ssks2MR.getFactorToken()`
rawOverEncryptionKey, // `rawOverEncryptionKey` transmise par votre serveur
{ deleteOnConvert: true }
)
SealdError* err = NULL;
char* groupId = "UUID"; // L'ID du groupe.
char* groupTMRKeyId = "UUID"; // L'ID de la `GroupTMRTemporaryKey` concernée.
char* authFactorType = "EM";
char* authFactorValue = "user@email.com";
int deleteOnConvert = 0; // 1 to delete after conversion, 0 otherwise
int rawOverEncryptionKeyLen = 64;
unsigned char* rawOverEncryptionKeyBytes = RETRIEVED_KEY // La `rawOverEncryptionKey` transmise par votre serveur.
// Récupération d'un tmrJWT
SealdSsksTMRPlugin* ssksPluginTmrAccesses; // Une instance initialisé de SealdSsksTMRPlugin
char* authenticationSessionId = "UUID"; // L'ID de la session d'authentification TMR créée par votre serveur.
char* ssksTMRChallenge = "aaaaaa"; // Le challenge envoyé au facteur d'authentification.
SealdSsksTMRPluginGetFactorTokenResponse* retrievedToken = NULL;
int errCode = SealdSsksTMRPlugin_GetFactorToken(ssksPluginTmrAccesses, authenticationSessionId, authFactorType, authFactorValue, ssksTMRChallenge, &retrievedToken, &err);
// Conversion de la clé temporaire TMR de groupe :
int errCode = SealdSdk_ConvertGroupTMRTemporaryKey(sdk2, groupId, groupTMRKeyId, retrievedToken->Token, rawOverEncryptionKeyBytes, rawOverEncryptionKeyLen, deleteOnConvert, &err);
NSError* error = nil;
NSString* groupId = @"UUID"; // L'ID du groupe.
NSString* groupTMRKeyId = @"UUID"; // L'ID de la `GroupTMRTemporaryKey` concernée.
NSData* rawOverEncryptionKey = RETRIEVED_KEY // La `rawOverEncryptionKey` transmise par votre serveur.
SealdTmrAuthFactor* tmrAuthFactor = [[SealdTmrAuthFactor alloc] initWithValue:@"user@email.com" type:@"EM"];
// Récupération d'un tmrJWT
NSString* authenticationSessionId = @"UUID"; // L'ID de la session d'authentification TMR créée par votre serveur.
NSString* ssksTMRChallenge = @"aaaaaa"; // Le challenge envoyé au facteur d'authentification.
SealdSsksGetFactorTokenResponse* tmrJWT = [ssksTMR getFactorToken:authenticationSessionId
authFactor:tmrAuthFactor
challenge:ssksTMRChallenge
error:&error];
// Conversion de la clé temporaire TMR de groupe :
[sdk2 convertGroupTMRTemporaryKeyWithGroupId:groupTMRId
temporaryKeyId:gTMRKey.keyId
tmrJWT:tmrJWT.token
rawOverEncryptionKey:rawOverEncryptionKey
deleteOnConvert:NO
error:&error];
let groupId = "UUID" // L'ID du groupe.
let groupTMRKeyId = "UUID" // L'ID de la `GroupTMRTemporaryKey` concernée.
let tmrAuthFactor = SealdTmrAuthFactor(value: "user@email.com", type: "EM")
let rawOverEncryptionKey = RETRIEVED_KEY // La `rawOverEncryptionKey` transmise par votre serveur.
// Récupération d'un tmrJWT
let authenticationSessionId = "UUID"// L'ID de la session d'authentification TMR créée par votre serveur.
let ssksTMRChallenge = "aaaaaa" // Le challenge envoyé au facteur d'authentification.
let tmrJWT = try await ssksTMR.getFactorTokenAsync(
sessionId: authenticationSessionId,
authFactor: tmrAuthFactor,
challenge: ssksTMRChallenge
)
// Conversion de la clé temporaire TMR de groupe :
try await sdk.convertGroupTMRTemporaryKeyAsync(
withGroupId: groupId,
temporaryKeyId: groupTMRKeyId,
tmrJWT: tmrJWT.token,
rawOverEncryptionKey: rawOverEncryptionKey,
deleteOnConvert: false)
val groupId = "UUID" // L'ID du groupe.
val groupTMRKeyId = "UUID" // L'ID de la `GroupTMRTemporaryKey` concernée.
val tmrAuthFactor = AuthFactor(AuthFactorType.EM, "user@email.com")
val rawOverEncryptionKey = RETRIEVED_KEY // La `rawOverEncryptionKey` transmise par votre serveur.
// Récupération d'un tmrJWT
val authenticationSessionId = "UUID" // L'ID de la session d'authentification TMR créée par votre serveur.
val ssksTMRChallenge = "aaaaaa" // Le challenge envoyé au facteur d'authentification.
val tmrJWT =
ssksPlugin.getFactorTokenAsync(
authenticationSessionId,
authFactor = tmrAuthFactor,
challenge = ssksTMRChallenge,
)
// Conversion de la clé temporaire TMR de groupe :
sdk.convertGroupTMRTemporaryKey(groupId, groupTMRKeyId, tmrJWT.token, rawOverEncryptionKey)
String groupId = "UUID"; // L'ID du groupe.
String groupTMRKeyId = "UUID"; // L'ID de la `GroupTMRTemporaryKey` concernée.
String authFactorType = "EM";
String authFactorValue = "user@email.com";
Uint8List rawOverEncryptionKey = RETRIEVED_KEY // La `rawOverEncryptionKey` transmise par votre serveur.
// Récupération d'un tmrJWT
String authenticationSessionId = "UUID"; // L'ID de la session d'authentification TMR créée par votre serveur.
String ssksTMRChallenge = "aaaaaa"; // Le challenge envoyé au facteur d'authentification.
SealdSsksTMRPluginGetFactorTokenResponse tmrJWT =
await ssksPlugin.getAuthFactorTokenAsync(
authenticationSessionId, authFactorType, authFactorValue,
challenge: ssksTMRChallenge);
// Conversion de la clé temporaire TMR de groupe :
await sdk2.convertGroupTMRTemporaryKeyAsync(
groupId, groupTMRKeyId, tmrJWT.token, rawOverEncryptionKey);