Comment sécuriser une image médicale DICOM ?

05/06/2018

Nous traitons dans cet article des moyens de sécurisation d'une image DICOM en conformité avec la législation en vigueur.

En imagerie médicale, les communications réseaux et les fichiers informatiques utilisent le standard DICOM.

Dans un précédent article, nous avons vu qu'une image médicale au format DICOM n'est pas sécurisée par défaut et peut être modifiée.

Pour y remédier, une solution consiste à bunkériser les réseaux informatiques (VPN, firewall, HTTPS, HADS,...) ou l'accès aux machines mais l'expérience montre que les images médicales ont une forte tendance à se volatiliser dans la nature (des CD, DVD et autres clés USB perdus, envoi par email ou par coursier, serveur/disque dur volés, ...).

Les solutions cumulables présentées dans cet article utilisent :

  • la signature électronique pour garantir l'authenticité de l'image c'est-à-dire son origine et qu'elle n'a pas été modifiée
  • le chiffrement pour garantir que seule la personne autorisée peut consulter l'image ou des informations sur l'identité du patient (nom, prénom, date de naissance du patient, du médecin, ...)
  • la pseudonymisation qui empêche d'identifier le patient sans avoir des informations supplémentaires

Ces solutions s'intègrent dans les champs DICOM de l'image pour que cette dernière reste compatible DICOM et voyage sans encombre dans les appareils d'imagerie médicale (stations, serveurs , ...)

Pour décrire plus clairement les opérations nous utiliserons dans cet article du pseudo-code.

Le code source fonctionnel en JavaScript et node.js peut être consulté ici.

La législation

Une image DICOM est une donnée de santé par nature puisqu'elle est susceptible de révéler des informations sur l’état de santé d'une personne.

Jusqu'à présent, excepté pour les données de santé stockées dans le cloud (HADS ou Hébergeur Agrée de Données de Santé), il était seulement recommandé de chiffrer les données de santé échangées afin de garantir le secret médical et il n'était pas obligatoire de désigner un responsable du traitement.

Le RGPD clarifie cette situation :

Le responsable du traitement choisit une des solutions (signature, chiffrement et pseudonymisation) ou décide de les cumuler en fonction des risques évalués. Il choisit également les champs DICOM à traiter susceptibles de compromettre l'identité du patient ou le secret médical.

Pseudonymiser une image DICOM

La solution classique pour se soustraire au RGPD est d'anonymiser l'image ce qui rend l'identification du patient irréversible mais empêche de stocker l'image dans un PACS.

La pseudonymisation quand à elle est réversible ce qui permet de retrouver l'image stockée dans un PACS.

Exemple :

Nom Nom pseudonymisé Nom anonymisé
Pierre 4FJdERui89 XXXXXXXX
Paul M15Zdqd0 XXXXXXXX
Pierre 4FJdERui89 XXXXXXXX

Le nom du patient est pseudonymisé à l'aide d'une fonction de hachage cryptographique comme HMAC qui nécessite une clé secrète uniquement connue par le responsable du traitement, et les autres informations sur l'identité du patient sont anonymisées en les remplaçant simplement par 'XXXXXXX'.

L'image sera archivée dans le PACS avec comme nom de patient le code d'authentification HMAC, elle pourra par la suite être retrouvée dans le PACS en recalculant le code HMAC à partir du nom du patient.

Pour afficher le code HMAC qui correspond au nom du patient et sa date naissance :

// l'utilisateur indique le nom du patient
patientName = readFromKeyboard()
// l'utilisateur indique la date de naissance du patient
patientBirthdate = readFromKeyboard()
// calculer l'empreinte HMAC de l'ensemble (Nom du patient et date de naissance) à l'aide de la clé secrète : "je suis le responsable du traitement"
hmac = HMAC([dicom.patientName, dicom.patientBirthdate], 'je suis le responsable du traitement')
// afficher à l'écran la clé HMAC
printToScreen(hmac)

Pour pseudonymiser une image DICOM :

// charger le fichier dicom en mémoire et le parser
dicom = readDicomFile('dicomfile.dcm') 
// calculer l'empreinte HMAC de l'ensemble (Nom du patient et date de naissance) à l'aide de la clé secrète : "je suis le responsable du traitement"
hmac = HMAC([dicom.patientName, dicom.patientBirthdate], 'je suis le responsable du traitement')
// remplacer le nom du patient par la clé HMAC
dicom.patientName = hmac
// anonymiser le nom du patient
dicom.patientBirthdate = 'XXXXXX'
// sauvegarder les modifications dans un nouveau fichier
writeDicomFile(dicom, 'newdicomfile.dcm')

Chiffrer une image DICOM

Le chiffrement permet de limiter la visualisation des informations d'une image aux seules personnes possédant la clé de déchiffrage.

Un algorithme de cryptographie asymétrique comme par exemple RSA peut être utilisé.

Le destinataire des images génère une paire de clés : une clé publique et une clé privée, ces deux clés sont liées.

Le destinataire communique uniquement sa clé publique aux personnes souhaitant lui communiquer de manière chiffrée des images, mais lui seul pourra les déchiffrer à l'aide de sa clé privée qu'il ne communique à personne.

Générer une paire de clés : une privée et une public

// générer une paire de clés privée / public
pairKeys = generatePublicPrivateKeys()
// envoyer par email la clé public aux personnes souhaitant me communiquer des images cryptées
sendByEmail(pairKeys.public, ['hospital1@mail.fr','clinique2@mail.fr'])
// conserver sur ma clé USB la clé privée pour décrypter des images
saveInFile(pairKeys.private, '/USB/myPrivateKey.txt')

Chiffrer l'image DICOM avec la clé public

// charger le fichier dicom en mémoire et le parser
dicom = readDicomFile('dicomfile.dcm') 
// chiffrer le nom du patient à l'aide de la clé public
dicom.patientName = crypt(dicom.patientName, publicKey)
// chiffrer la date de naissance du patient à l'aide de la clé public
dicom.patientBirthdate = crypt(dicom.patientBirthDate, publicKey)
// sauvegarder la version chiffrée dans un nouveau fichier
writeDicomFile(dicom, 'cryptedDicomFile.dcm')

Déchiffrer l'image DICOM avec la clé privée

// charger le fichier DICOM en mémoire et le parser
dicom = readDicomFile('cryptedDicomFile.dcm')
// déchiffrer le nom du patient à l'aide de la clé privée
dicom.patientName = decrypt(dicom.patientName, privateKey)
// déchiffrer la date de naissance du patient à l'aide de la clé privée
dicom.patientBirthdate = decrypt(dicom.patientBirthdate, privateKey)
// sauvegarder la version déchiffrée dans un nouveau fichier
writeDicomFile(dicom, 'decryptedDicomFile.dcm')

Signer une image DICOM

La signature d'image permet de garantir l'origine de l'image et qu'elle n'a pas été modifiée.

Une empreinte unique de l'image DICOM est calculée à l'aide par exemple de SHA-2.

La source de l'image génère une paire de clés : une clé privée et une clé public.

La source utilise sa clé privée pour chiffrer l'empreinte de l'image DICOM et l'enregistrer dans un champ de l'image, la source communique uniquement aux destinataires sa clé public.

Les destinataires utilisent la clé public pour déchiffrer l'empreinte et comparent cette dernière avec celle recalculée.

Calculer la signature électronique

// charger le fichier DICOM en mémoire et le parser
dicom = readDicomFile('dicomFile.dcm')
// calculer l'empreinte de l'ensemble (nom du patient, date de naissance et les pixels)
sha = SHA256([dicom.patientName, dicom.patientBirthdate, dicom.pixels])
// chiffrer avec la clé privée
shaCrypted = crypt(sha, privateKey)
// insérer la signature dans un champ DICOM
dicom.signature = shaCrypted
// sauvegarder l'image DICOM signée dans un nouveau fichier
writeDicomFile(dicom, 'signedDicomFile.dcm')

Vérifier la signature

// charger le fichier DICOM signé en mémoire et le parser
dicom = readDicomFile('signedDicomFile.dcm')
// déchiffrer l'empreinte de l'image DICOM avec la clé public
shaDecrypted = decrypt(dicom.signature, publicKey)
// recalculer l'empreinte de l'ensemble (nom du patient, date de naissance et les pixels)
shaOriginal = SHA256([dicom.patientName, dicom.patientBirthdate, dicom.pixels])
// comparer les deux signatures
if (shaOriginal == shaDecrypted) {
    printToScreen("Image OK !")	// l'image n'a pas été modifiée
} else {
    printToScreen("Image Corrupted !") //l'image a été modifiée
}

Clés certifiées par une autorité indépendante

Pour garantir la propriété d'une paire de clés privé / public, il n'y a pas d'autres choix que de faire appel à une autorité indépendante qui associera la paire à une personne physique ou morale (une entreprise).

Elle garantira également l'unicité de cette paire de clés.

Conclusion

Étant donné la quantité de données engendrées par l'imagerie médicale, toute technique de sécurité mise en place nécessite une analyse approfondie puisqu'elle aura naturellement des répercussions sur les performances de transfert, de stockage, de consultation, ...

Sections: Articles
Auteurs: Emmanuel ROECKER, Rym BOUCHAGOUR
Formations, Conseil & Développement e-Santé

Formations qui pourraient vous intéresser

Restez informé avec notre newsletter