2010-03-20 6 views
3

Quelle est la façon la plus simple que je peux cacher un identifiant sensible, tout en fournissant des moyens équivalents d'identification des données de l'extérieur?méthode la plus simple cacher des informations sensibles

Par exemple, permet de dire que j'ai une table de base de données avec des enregistrements et l'un d'eux est un champ d'identification sensible.

ID 
2A 
1S 
etc... 

alors je veux avoir un second enregistrement:

ID PublicID 
2A AXXX44328 
1S KKKZJSAAS 

de telle sorte que quand je me donne un publicId je peux toujours déterminer quel ID il se réfère à:

H(PublicID) = ID 

mais personne d'autre est capable de le faire.

Notez également, que je veux être en mesure de reproduire la chaîne dans au moins deux endroits différents. Donc, si j'ai deux serveurs/base de données, l'ID 2A doit correspondre à la chaîne AXX44328 sur chacun d'entre eux indépendamment.

Je soupçonne que c'est comme, le cryptage - avec jeter une clé publique?

+0

Gardez à l'esprit ... Si vos identifiants sensibles sont très courts, quelqu'un peut encore les deviner en interrogeant votre site Web/application à plusieurs reprises, sans même prendre la peine de regarder le PublicID. Vous devez vous assurer que votre demande d'entrée accepte UNIQUEMENT l'identificateur public de l'extérieur. –

Répondre

3

Si vos ID sont relativement courts (15 octets ou moins), je suggère de les chiffrer avec un chiffrement par bloc, à savoir le AES. L'AES utilise une clé secrète K, qui a une longueur de 128, 192 ou 256 bits (128 bits suffisent).Puisque AES traite un bloc de 16 octets exactement, vous devez remplir un peu votre ID. Le bourrage "habituel" (appelé "PKCS # 5") consiste à ajouter n octets (n> = 1), tous ayant la valeur n, de sorte que la longueur résultante soit appropriée (ici, vous veux une longueur de 16).

Ainsi, la transformation de ID (les données sensibles) dans S (la chaîne cryptée qui peut être présentée au public au sens large) est la suivante: S = AESencrypt_K (pad (ID)). L'opération inverse est: ID = UNPAD (AESdecrypt_K (S)). Si ID est de 16 octets ou plus, alors le cryptage utilisera plusieurs invocations de AES, et il y a des subtilités en ce qui concerne la façon dont ces invocations sont reliés entre eux. Le mot-clé est mode et la Enchaînement réponse habituelle est « CBC ».

La connaissance de la clé secrète K (même K) est nécessaire pour les deux opérations. Cela signifie que quiconque peut calculer S de ID peut également calculer ID de S, et vice versa.

Maintenant, si vous avez besoin d'entités pour pouvoir calculer S de ID sans leur donner le pouvoir de faire l'opération inverse, alors les choses sont plus complexes. vous ne devez pas en particulier, ont un processus déterministe: s'il y a un seul S qui peut être calculée à partir ID alors tout le monde peut essayer une recherche exhaustive sur les valeurs possibles de ID jusqu'à ce qu'une correspondance avec un donné S est trouvé. Donc, vous devez détendre le modèle, en ce qu'un donné ID peut donner un grand nombre de chaînes brouillées possibles S «, de sorte que tous ceux S » peut être reconverti en ID par quelqu'un qui a le "bonne" valeur secrète. C'est ce que vous obtiendriez du cryptage asymétrique. L'algorithme de chiffrement asymétrique habituel est RSA. Avec une clé RSA 1024 bits (une taille typique pour une sécurité appropriée), ID peut avoir une taille maximale de 117 octets, et S ' sera long de 128 octets (l'augmentation de la taille correspond aux données aléatoires injectées qui rend le processus non déterministe). Si 128 octets sont trop, vous pouvez obtenir des messages cryptés plus courts avec le cryptage El-Gamal sur les courbes elliptiques (jusqu'à environ 40 octets ou si, pour une mise à 20 octets ID), mais vous pouvez avoir un disque temps de trouver une implémentation existante.

+0

Vous ne voulez pas dire S = pad (AESencrypt_K (ID))?Parce que vous dites "vous devez remplir votre ID" – drozzy

+0

Non, vous remplissez l'ID _then_ que vous cryptez. Ce que vous suggérez est de tamponner le résultat du chiffrement, ce qui n'a pas de sens puisque le point de remplissage est d'obtenir quelque chose qui peut être chiffré, donc vous ne pouvez pas avoir de résultat de chiffrement avant d'avoir rembourré. –

+0

Non, ce que je veux dire est "S = pad (AESencrypt_K (ID))" est ce que vous avez écrit. Dans votre réponse. – drozzy

3

Il est suffisant pour générer une chaîne aléatoire, unique d'une sorte et le stocker dans la base de données que votre ID public. Indexez la table sur l'ID public et vous pouvez facilement récupérer l'ID réel (et les autres valeurs de ligne) en fonction de l'ID public. Comme la base de données est privée, personne ne peut déterminer l'ID en fonction de l'ID public.

Un moyen simple pour générer la chaîne aléatoire, unique est de prendre un hachage SHA-1 (par exemple) de la véritable identité + une valeur de sel, par exemple

my $public_id = sha1($salt . $id); 

La valeur $salt doit être une longue chaîne aléatoire qui est généré une fois, conservé sur le serveur et n'a jamais révélé publiquement. Il est très difficile (presque impossible) pour un attaquant de désosser l'ID réel de l'ID public par brute-forçant le hachage (qui peut être assez facile sans sel, si l'ID est court et numérique)

L'avantage de cette approche est que le même $ id sera toujours mappé sur le même $ public_id, tant que la valeur $ salt reste constante.


Si ce n'est pas une option, générer une clé aléatoire et chiffrer l'ID réel avec elle, et utiliser la version cryptée comme ID public. Vous pouvez ensuite déchiffrer cet identifiant plus tard pour récupérer l'identifiant réel.

+0

Oui, je sais que c'est une option, mais je veux être en mesure de reproduire la chaîne aléatoire à deux endroits différents. Donc si j'ai deux serveurs/base de données, l'ID 2A doit correspondre à la chaîne AXX44328 sur chacun d'entre eux de façon indépendante. – drozzy

+0

J'ai rajouté la section sur la prise d'un hachage sha1. Cela résout votre problème, à condition que les deux serveurs puissent accéder à la valeur $ salt. – rjh

+0

Désolé - mais SHA1 a une possibilité de collision, alors que je veux que ce soit 0. – drozzy

1

Vous n'avez pas spécifié de langage de programmation. Voici un exemple en PHP, semblable à ce que RJH a suggéré avec SHA1, mais utilise un algorithme de chiffrement symétrique approprié plutôt que SHA1, ce qui élimine la possibilité (même à distance) des collisions:

 

define('KEY', 'S4mPhZg3rQga'); 

function encrypt($text) 
{ 
    return base64_encode(mcrypt_encrypt(MCRYPT_RIJNDAEL_256, KEY, $text, MCRYPT_MODE_ECB, mcrypt_create_iv(mcrypt_get_iv_size(MCRYPT_RIJNDAEL_256, MCRYPT_MODE_ECB), MCRYPT_RAND))); 
} 

function decrypt($text) 
{ 
    return mcrypt_decrypt(MCRYPT_RIJNDAEL_256, KEY, base64_decode($text), MCRYPT_MODE_ECB, mcrypt_create_iv(mcrypt_get_iv_size(MCRYPT_RIJNDAEL_256, MCRYPT_MODE_ECB), MCRYPT_RAND)); 
} 

// example usage: 
$C = encrypt('1234'); 
echo("Public ID: $C\n"); 

$P = decrypt($C); 
echo("Private ID: $P\n"); 

La valeur de la clé doit être réglée une fois , avec la même valeur dans les deux serveurs, et ne devrait jamais être révélé. Vous utiliseriez encrypt() lors de l'affichage des données et decrypt() lors de l'acceptation de données provenant de l'extérieur. Il n'est pas nécessaire de stocker le PublicID, vous le calculez simplement à la volée.

+0

Hmm. J'allais le suggérer mais j'avais des doutes sur la sécurité des chiffrements par bloc qui étaient si petits. Ai-je tort? – rjh

+0

Cette clé doit donc faire partie du code source, par exemple, sur chaque serveur? – drozzy

+0

Avec AES vous avez toujours la possibilité de collisions, non? – drozzy

1

Puisque vous voulez être en mesure de recréer l'identifiant sur deux, déconnectés, bases de données, vous aurez besoin d'avoir une sorte de clé partagée.

C'est un endroit parfait pour un HMAC.Pour voler RFC-2104 par de Wikipédia:

Soit:
H (·) une fonction de hachage cryptographique
K une clé secrète rembourré à droite avec des zéros supplémentaires à la taille du bloc de la fonction de hachage
m est le message à authentifier
∥ représentent concaténation
⊕ désignent ou exclusif (XOR)
opad être le rembourrage extérieur (0x5c5c5c ... 5c5c, un bloc-longue constante hexadécimale)
ipa d le rembourrage intérieur (0x363636 ... 3636, un bloc-longue constante hexadécimale)

Puis HMAC (K, m) est mathématiquement défini par
HMAC (K, m) = H ((K ⊕ opad) ∥ H ((K ⊕ ipad) ∥ m)).

Mais, vous n'avez pas à implémenter vous-même! Utilisez la bibliothèque standard de votre langue de choix. Par exemple, en Python:

>>> import hmac 
>>> hmac.new(key='abc123secret make me long', msg='This is my unique key #1') 
<hmac.HMAC instance at 0xb77bdbac> 
>>> _.hexdigest() 
'c23a224afa917d13fbef58ee14884269' 

Vous avez maintenant un ID unique calculable. Pré-calcul en tant que clés primaires dans votre base de données. Recherche si nécessaire!


En tant que sidenote, faire pas hasch salé (Google: "don't hash secrets") et ne PAS utiliser une version cryptée de vos données. Le premier à cause des attaques de message-extension. Ce dernier parce que vous exposer inutilement les données d'une manière qui répond uniquement sur votre sécurité clé.

Je lierais avec plus de références, mais je suis un nouvel utilisateur. : - \

+0

L'article que vous référence indique en fait "Dans l'exemple de mot de passe, vous pouvez hacher un mot de passe tant que vous le salt correctement." Donc, si vous faites référence à ma réponse, je pense que mon utilisation d'un hash salé est correcte (elle est identique à l'exemple). OTOH, j'ai aussi vu PunBB et d'autres applications faire 'sha1 ($ sel. Sha1 ($ sel. $ Mot de passe))' qui semble être une approximation de HMAC. – rjh

+0

Un sel * ne fournit pas d'authenticité. Cela augmente seulement la complexité de calcul nécessaire pour générer un message correspondant au hachage. Et, re-hachage d'un hachage salé fournit un avantage supplémentaire négligeable, voire pas, (voir: http://stackoverflow.com/questions/348109/is-double-hashing-a-password-less-secure-than-just- hashing-it-once). Si le champ ID est sensible et - compte tenu des commentaires récents - vraisemblablement court. Par conséquent, forcer le hachage est un problème légitime. Dans ce cas, il devrait regarder bcrypt ou PBKDF-- et pas un sel. –

+0

Si le "sel" est utilisé pour s'assurer que l'identifiant provient de l'une des autres machines, alors c'est une question d'authenticité et cela nécessite un HMAC. Un sel, et même le double-hachage d'un sel, n'est jamais une approximation d'un HMAC. C'est une chose complètement différente. –

Questions connexes