Verschlüsselung im Client
Categories:
Neben der Möglichkeit, die zu überwachenden Daten im Klartext an omniac Business zu senden, bieten wir auch an, die Daten bereits normalisiert, verschlüsselt und gehasht zu empfangen. Letzteres ist auch der von uns empfohlene Weg, da so die persönlichen Attribute Ihrer Nutzer nie im Klartext Ihren Firmenkontext verlassen. Die Verarbeitungsschritte, die dafür notwendig sind, müssen identisch mit denen sein, die wir durchführen, bevor wir die Daten zum Durchsuchen unserer Datenleck-Datenbank verwenden. Im Folgenden wird dieses Vorgehen kurz erläutert.
Tenant abrufen
In Ihrem Tenant finden Sie alle notwendigen Informationen zur Normalisierung, Verschlüsselung und zum Hashing. Im Feld “available_attributes” finden Sie die Normalisierungsregeln, im Feld “hash_algorithm” die zu verwendende Hash-Funktion und im Feld “encryption_key” den Public Key, um die Daten zu verschlüsseln. Jeder dieser Schritte wird nun kurz erläutert.
Beispiel: E-Mail
Der Schritt der Normalisierung muss zu Beginn und vor jeder weiteren Verarbeitung durchgeführt werden. Wir betrachten nun das Beispiel der E-Mail (zu finden in den “available_attributes” des Tenants):
{
"key": "email",
"encrypted": true,
"split": false,
"normalize": [
"DeleteQuotationMarks",
"DeleteTrailingComma",
"UnicodeNormalization",
"Strip",
"Lowercase"
],
"mask": {
"task": "email",
"begin": 0,
"end": 0
}
},
Alle folgenden Schritte werden auf der normalisierten Version der E-Mail vorgenommen. Als Nächstes folgt das Hashing. Hierzu wird im Tenant der Algorithmus vorgegeben, der aktuell jedoch immer SHA-256 ist. Die Verschlüsselung ist nicht bei jedem Attribut benötigt (siehe boolean Feld encrypted). Wenn encrypted=true ist, wird der PKCS1 Algorithmus genutzt. Hier eine Beispielimplementierung in Go:
func EncryptWithPublicKey(pubKey string, data string) (string, error) {
publicKeyBytes, err := base64.StdEncoding.DecodeString(pubKey)
if err != nil {
return "", errors.New("failed to decode public key: " + err.Error())
}
rsaPublicKey, err := ParseRsaPublicKeyFromPemStr(string(publicKeyBytes))
if err != nil {
return "", errors.New("ParseRsaPublicKey: " + err.Error())
}
rng := rand.Reader
ciphertext, err := rsa.EncryptPKCS1v15(rng, rsaPublicKey, []byte(data))
if err != nil {
return "", errors.New("failed to encrypt data: " + err.Error())
}
// Encode the encrypted data to base64 for easy transmission or storage
return base64.StdEncoding.EncodeToString(ciphertext), nil
}
Das masking liegt in der Hand der Kunden und die übermittelten Werte stellen nur einen Vorschlag dar. Hier geht es darum, wie die Werte maskiert trotzdem gespeichert werden um eine ungefähre Zuordnung für den Nutzer zu ermöglichen. So kann zum Beispiel die mail “test@example.com” als “te*****@**ple.com” übergeben werden.
Beispiel: Name (split Attribut)
Ist der Parameter “split” in der AttributConfig gesetzt, erwartet omniac Business, dass nach der Normalisierung die Werte an Leerzeichen getrennt und die entstandenen Teile einzeln erneut Normalisiert und Gehashed werden. Verschlüsselt wird trotzdem der gesamte Wert. Abschließend werden die gehashten Werte als string mit Kommas verbunden an omniac Business übermittelt. Es folgt ein Beispiel:
{
"key": "name",
"encrypted": true,
"split": true,
"normalize": [
"DeleteQuotationMarks",
"DeleteTrailingComma",
"ReplaceSymbols",
"DeleteConsecutiveSpaces",
"UnicodeNormalization",
"Strip",
"Lowercase"
],
"mask": {
"task": "",
"begin": 0,
"end": 0
}
},
Sollte beispielsweise der Name gemonitored werden, sind folgende Schritte notwendig, da split=true ist. Name Beispiel: “Max Mustermann”
- Normaliserung des gesamten Strings (“max mustermann”)
- Verschlüsselung des normalisierten Strings (“Q2CWI6xZ6r2QsS/tJCARqzFWEXh+aeRuClgaX4AzMrNAXrgyQcfq6/lYsCGvSPVa1jTWF7zd4fmi2AMh3DbirRNpfCJNNZcW2mE1Iw0EhilpYen6nYAMPtxb5zHhsb2DfaKr0qOFal1zIjDM+KiAbLaiOF+wTajGmH/3Bt2rwvK30/qDta3u3oplKzLVNqaoWpqGqiv0cKx9ytday8YqxqbqNcGZf1ztZVUAxkS4M0UHsVHVnHDK6ADcZoz2scdJU9nwipb0C2dXGePlE/hBBttkzq6lR2vExfIbjTQ+QEhzQiUdvz9WeuckHLRG8jGhMnSpIUZ9Pt/w2H1qAoEN0A==”)
- Aufteilen des Strings an den Leerzeichen ([“max”, “mustermann”])
- Normalisierung der Teile ([“max”, “mustermann”])
- Hashing der Teile ([“9baf3a40312f39849f46dad1040f2f039f1cffa1238c41e9db675315cfad39b6”, “e32a370b7912ad78cc6a88fda605a5b3657e9c3b164cee669364aaf3f8cdbb36”])
- Zusammenführen der gehashten Teile als String getrennt mit Kommas (“9baf3a40312f39849f46dad1040f2f039f1cffa1238c41e9db675315cfad39b6,e32a370b7912ad78cc6a88fda605a5b3657e9c3b164cee669364aaf3f8cdbb36”)
Senden der Attribute
Während ein normaler PUT /v1/profiles/:profile_id/attributes call body so aussieht:
[
{
"type": {
"key": "name"
},
"value": "Max Mustermann",
},
{
"type": {
"key": "email"
},
"value": "test@example.com",
},
]
erwarten wir folgendes Format für im Client gehashte und verschlüsselte Werte:
[
{
"type": {
"key": "name"
},
"value": "M** ******mann",
"hashed": "9baf3a40312f39849f46dad1040f2f039f1cffa1238c41e9db675315cfad39b6,e32a370b7912ad78cc6a88fda605a5b3657e9c3b164cee669364aaf3f8cdbb36",
"encrypted": "Q2CWI6xZ6r2QsS/tJCARqzFWEXh+aeRuClgaX4AzMrNAXrgyQcfq6/lYsCGvSPVa1jTWF7zd4fmi2AMh3DbirRNpfCJNNZcW2mE1Iw0EhilpYen6nYAMPtxb5zHhsb2DfaKr0qOFal1zIjDM+KiAbLaiOF+wTajGmH/3Bt2rwvK30/qDta3u3oplKzLVNqaoWpqGqiv0cKx9ytday8YqxqbqNcGZf1ztZVUAxkS4M0UHsVHVnHDK6ADcZoz2scdJU9nwipb0C2dXGePlE/hBBttkzq6lR2vExfIbjTQ+QEhzQiUdvz9WeuckHLRG8jGhMnSpIUZ9Pt/w2H1qAoEN0A=="
},
{
"type": {
"key": "email"
},
"value": "te*****@**ple.com",
"hashed": "973dfe463ec85785f5f95af5ba3906eedb2d931c24e69824a89ea65dba4e813b",
"encrypted": "K/QKpKzdLLGRSayMrqPFqpBCN/vH6fDKWltqNqX1E0ZBLZQEya6rLqg8VTiomyC3hDnp3d+YFHYwXyFpCRjIXQ0uXA8Yz2fZWHnYdLVv5ua2gYAC9huCJmtM89wYBLINPq47gERwHUeiSzVxNk3D6XvwgvGQXd+N+y/A4XC+mhhe603CrC6lzY0N2e7QyQK5YBni9mfr0S+lMVN6CpGqBlnucKGaVXdPn9fBmwWvW3pkA4uoEhRQruD9fdIBFrOy388ctRtrmHFVlP5IWkwXxXas2CpLCarapgULJcO9pG6kG0RqE+NAiKgsZ2Jw3PA0ZLqjp0sIXH3xTzLPNZJ7xQ=="
},
]
Nun sind die Attribute, wie in der Version, in der omniac Business diese Schritte übernimmt, bei uns abgelegt und werden überwacht.