Schutz vertraulicher Daten durch Verschlüsselung auf Feldebene - Amazon CloudFront

Schutz vertraulicher Daten durch Verschlüsselung auf Feldebene

Mit Amazon CloudFront können Sie sichere End-to-End-Verbindungen zu Ursprungs-Servern mithilfe von HTTPS erzwingen. Die Verschlüsselung auf Feldebene fügt zusammen mit HTTPS eine zusätzliche Sicherheitsebene hinzu, mit der Sie bestimmte Daten während der gesamten Systemverarbeitung so schützen können, dass nur bestimmte Anwendungen sie sehen können.

Die Verschlüsselung auf Feldebene ermöglicht es Ihren Benutzern, vertrauliche Informationen in sicherer Weise auf Ihre Webserver hochzuladen. Die vertraulichen Informationen, die von Ihren Benutzern bereitgestellt werden, werden am Rand, in der Nähe des Benutzers, verschlüsselt und bleiben über den gesamten Anwendungs-Stack hinweg verschlüsselt. Diese Verschlüsselung stellt sicher, dass nur Anwendungen, die die Daten benötigen - und über die Anmeldeinformationen zum Entschlüsseln verfügen - dies tun können.

Um eine Verschlüsselung auf Feldebene zu verwenden, geben Sie bei der Konfiguration Ihrer CloudFront-Verteilungen den Satz der Felder in POST-Anforderungen an, die verschlüsselt werden sollen, so wie den öffentlichen Schlüssel, mit dem dies geschehen soll. Sie können bis zu 10 Datenfelder in einer Anfrage verschlüsseln. (Sie können nicht alle Daten in einer Anfrage mit Verschlüsselung auf Feldebene verschlüsseln; Sie müssen einzelne Felder angeben, die verschlüsselt werden sollen.)

Wenn die HTTPS-Anfrage mit Verschlüsselung auf Feldebene an den Ursprung weitergeleitet und durch Ihre Ursprungsanwendung bzw. Ihr Ursprungssubsystem geleitet wird, sind die vertraulichen Daten immer noch verschlüsselt, wodurch das Risiko einer Datenschutzverletzung oder eines versehentlichen Datenverlustes der vertraulichen Daten verringert wird. Komponenten, die aus geschäftlichen Gründen Zugriff auf die sensiblen Daten benötigen, wie z. B. ein Zahlungssystem für eine Kreditnummer, können mit dem entsprechenden privaten Schlüssel entschlüsseln und auf die Daten zugreifen.

Anmerkung

Beachten Sie, dass der Ursprung für die Verschlüsselung auf Feldebene die Chunked-Codierung unterstützen muss.


				Verschlüsselung auf Feldebene in CloudFront

Die CloudFront-Verschlüsselung auf Feldebene verwendet eine asymmetrische Verschlüsselung (auch Public-Key-Verschlüsselung). Sie stellen CloudFront einen öffentlichen Schlüssel zur Verfügung, und alle festgelegten, sensiblen Daten werden automatisch verschlüsselt. Der an CloudFront übergebene Schlüssel kann nicht verwendet werden, um die verschlüsselten Werte zu entschlüsseln. Dies ist nur mit Ihrem privaten Schlüssel möglich.


				Verschlüsseln Sie nur sensiblen Daten

Überblick über die Verschlüsselung auf Feldebene

Die folgenden Schritte geben einen Überblick über die Einrichtung der Verschlüsselung auf Feldebene. Spezifische Schritte finden Sie unter Verschlüsselung auf Feldebene einrichten.

  1. Holen Sie sich ein Schlüsselpaar aus öffentlichem und privatem Schlüssel. Sie müssen den öffentlichen Schlüssel abrufen und hinzufügen, bevor Sie mit der Einrichtung der Verschlüsselung auf Feldebene in CloudFront beginnen.

  2. Erstellen Sie ein Verschlüsselungsprofil auf Feldebene. Verschlüsselungsprofile auf Feldebene, die Sie in CloudFront erstellen, definieren die Felder, die verschlüsselt werden sollen.

  3. Erstellen Sie eine Verschlüsselungskonfiguration auf Feldebene. Eine Konfiguration spezifiziert die zu verwendenden Profile, basierend auf dem Inhaltstyp der Anfrage oder einem Abfrageargument, um bestimmte Datenfelder zu verschlüsseln. Sie können auch die Verhaltensoptionen für die Anforderungsweiterleitung auswählen, die Sie für verschiedene Szenarien benötigen. Sie können beispielsweise das Verhalten festlegen, wenn der durch das Abfrageargument in einer Anforderungs-URL angegebene Profilname in CloudFront nicht vorhanden ist.

  4. Verknüpfen zu einem Cache-Verhalten. Verknüpfen Sie die Konfiguration mit einem Cache-Verhalten für eine Verteilung, um anzugeben, wann CloudFront Daten verschlüsseln soll.

Verschlüsselung auf Feldebene einrichten

Führen Sie die folgenden Schritte aus, um mit der Verschlüsselung auf Feldebene zu beginnen. Weitere Informationen zu Kontingenten (früher als Limits bezeichnet) für die Verschlüsselung auf Feldebene finden Sie unter Kontingente.

Schritt 1: Erstellen eines RSA-Schlüsselpaars

Um zu beginnen, müssen Sie ein RSA-Schlüsselpaar erstellen, das einen öffentlichen Schlüssel und einen privaten Schlüssel enthält. Der öffentliche Schlüssel ermöglicht CloudFront die Verschlüsselung von Daten, und der private Schlüssel ermöglicht Komponenten am Ursprung, die verschlüsselten Felder zu entschlüsseln. Sie können OpenSSL oder ein anderes Tool verwenden, um ein Schlüsselpaar zu erstellen. Die Schlüsselgröße muss 2048 Bit betragen.

Wenn Sie beispielsweise OpenSSL verwenden, können Sie mithilfe des folgenden Befehls ein Schlüsselpaar mit einer Länge von 2048 Bits erstellen und in der Datei private_key.pem speichern:

openssl genrsa -out private_key.pem 2048

Die erstellte Datei enthält den öffentlichen und den privaten Schlüssel. Um den öffentlichen Schlüssel aus dieser Datei zu extrahieren, führen Sie den folgenden Befehl aus:

openssl rsa -pubout -in private_key.pem -out public_key.pem

Die Datei mit dem öffentlichen Schlüssel (public_key.pem) enthält den codierten Schlüsselwert, den Sie im folgenden Schritt einfügen.

Schritt 2: Hinzufügen des öffentlichen Schlüssels zu CloudFront

Nachdem Sie Ihr RSA-Schlüsselpaar erhalten haben, fügen Sie Ihren öffentlichen Schlüssel zu CloudFront hinzu.

So fügen Sie CloudFront (Konsole) Ihren öffentlichen Schlüssel hinzu
  1. Melden Sie sich bei der AWS Management Console an und öffnen Sie die CloudFront-Konsole unter https://console.aws.amazon.com/cloudfront/v3/home.

  2. Wählen Sie im Navigationsbereich Public key aus.

  3. Wählen Sie Add public key (Öffentlichen Schlüssel hinzufügen) aus.

  4. Geben Sie unter Key name einen eindeutigen Namen für den Schlüssel ein. Der Name darf keine Leerzeichen enthalten und darf nur alphanumerische Zeichen, Unterstriche (_) und Bindestriche (-) enthalten. Die maximale Anzahl der Zeichen beträgt 128.

  5. Fügen Sie unter Key value (Schlüsselwert) den codierten Schlüsselwert für den öffentlichen Schlüssel ein, einschließlich der Zeilen -----BEGIN PUBLIC KEY----- und -----END PUBLIC KEY-----.

  6. In Comment fügen Sie einen optionalen Kommentar hinzu. Beispielsweise können Sie das Ablaufdatum für den öffentlichen Schlüssel angeben.

  7. Wählen Sie Add (Hinzufügen) aus.

Sie können weitere Schlüssel für die Verwendung mit CloudFront hinzufügen, indem Sie die Schritte der Prozedur wiederholen.

Schritt 3: Erstellen eines Profils für die Verschlüsselung auf Feldebene

Nachdem Sie mindestens einen öffentlichen Schlüssel zu CloudFront hinzugefügt haben, erstellen Sie ein Profil, das CloudFront mitteilt, welche Felder verschlüsselt werden sollen.

So erstellen Sie ein Profil für die Verschlüsselung auf Feldebene (Konsole)
  1. Wählen Sie im Navigationsbereich die Option Field-level encryption aus.

  2. Wählen Sie Create profile (Profil erstellen) aus.

  3. Füllen Sie die folgenden Felder aus:

    Profilname

    Geben Sie einen eindeutigen Namen für das Profil ein. Der Name darf keine Leerzeichen enthalten und darf nur alphanumerische Zeichen, Unterstriche (_) und Bindestriche (-) enthalten. Die maximale Anzahl der Zeichen beträgt 128.

    Public key name

    Wählen Sie in der Dropdown-Liste den Namen eines öffentlichen Schlüssels, den Sie in Schritt 2 zu CloudFront hinzugefügt haben. CloudFront verwendet den Schlüssel, um die Felder, die Sie in diesem Profil angeben, zu verschlüsseln.

    Provider name

    Geben Sie einen Satz ein, um den Schlüssel zu identifizieren (z. B. den Anbieter, bei dem Sie das Schlüsselpaar erhalten haben). Diese Informationen werden zusammen mit dem privaten Schlüssel benötigt, wenn Anwendungen Datenfelder entschlüsseln. Der Name des Anbieters darf keine Leerzeichen enthalten und darf nur alphanumerische Zeichen, Doppelpunkte (:), Unterstriche (_) und Bindestriche (-) enthalten. Die maximale Anzahl der Zeichen beträgt 128.

    Feldnamensmuster für die Zuordnung

    Geben Sie die Namen der Datenfelder oder Muster ein, die Datenfeldnamen in der Anforderung identifizieren, die Sie mit CloudFront verschlüsseln möchten. Wählen Sie die Option +, um alle Felder hinzuzufügen, die Sie mit diesem Schlüssel verschlüsseln möchten.

    Für das Feldnamensmuster können Sie den gesamten Namen des Datenfeldes eingeben, wie z. B. DateOfBirth, oder nur den ersten Teil des Namens mit einem Platzhalterzeichen (*), wie z.B. CreditCard*. Das Feldnamensmuster darf neben dem optionalen Platzhalterzeichen (*) nur aus alphanumerischen Zeichen, eckigen Klammern ([ und ]), Punkten (.), Unterstrichen (_) und Bindestrichen (-) bestehen.

    Stellen Sie sicher, dass Sie keine überschneidenden Zeichen für unterschiedliche Feldnamensmuster verwenden. Wenn Sie beispielsweise ein Feldnamensmuster von ABC* haben, können Sie kein weiteres Feldnamensmuster hinzufügen, das AB* ist. Dazu kommt, dass bei Feldnamen zwischen Groß- und Kleinschreibung unterschieden wird und die maximale Anzahl der Zeichen 128 beträgt.

    Kommentar

    (Optional) Geben Sie einen Kommentar zu diesem Profil ein. Die maximale Anzahl der Zeichen beträgt 128.

  4. Nachdem Sie die Felder ausgefüllt haben, wählen Sie Create profile (Profil erstellen) aus.

  5. Wenn Sie weitere Profile hinzufügen möchten, wählen Sie Add profile aus.

Schritt 4: Erstellen einer Konfiguration

Nachdem Sie ein oder mehrere Verschlüsselungsprofile auf Feldebene erstellt haben, erstellen Sie eine Konfiguration, die den Inhaltstyp der Anforderung festlegt. In ihr enthalten sind die zu verschlüsselnden Daten, das für die Verschlüsselung zu verwendende Profil sowie andere Optionen, die definieren, wie CloudFront die Verschlüsselung handhaben soll.

Wenn beispielsweise CloudFront die Daten nicht verschlüsseln kann, können Sie in den folgenden Szenarien angeben, ob CloudFront eine Anforderung blockieren oder an Ihren Ursprung weiterleiten soll:

  • Wenn sich ein Anforderungsinhaltstyp nicht in einer Konfiguration befindet – Wenn Sie einen Inhaltstyp einer Konfiguration nicht hinzugefügt haben, können Sie angeben, ob CloudFront die Anforderung mit diesem Inhaltstyp an den Ursprung weiterleiten soll, ohne Datenfelder zu verschlüsseln, oder ob es die Anforderung blockieren und einen Fehler zurückgeben soll.

    Anmerkung

    Wenn Sie einer Konfiguration einen Inhaltstyp hinzufügen, aber kein Profil für diesen Typ angegeben haben, leitet CloudFront Anforderungen mit diesem Inhaltstyp immer an den Ursprung weiter.

  • Wenn der in einem Anforderungsargument bereitgestellte Profilname nicht bekannt ist – Wenn Sie das fle-profile-Abfrageargument mit einem Profilnamen angeben, der für Ihre Verteilung nicht existiert, können Sie festlegen, ob CloudFront die Anforderung an den Ursprung senden soll, ohne Datenfelder zu verschlüsseln, oder ob es die Anforderung blockieren und einen Fehler zurückgeben soll.

In einer Konfiguration können Sie auch angeben, ob die Bereitstellung eines Profils als Abfrageargument in einer URL ein Profil überschreibt, das Sie dem Inhaltstyp für diese Abfrage zugeordnet haben. Standardmäßig verwendet CloudFront das Profil, das Sie einem Inhaltstyp zugeordnet haben (wenn Sie eines angeben). Auf diese Weise können Sie ein Profil haben, das standardmäßig verwendet wird, aber für bestimmte Anforderungen entscheiden, dass Sie ein anderes Profil erzwingen möchten.

So können Sie z. B. (in Ihrer Konfiguration) SampleProfile als das zu verwendende Abfrageargumentprofil festlegen. Dann könnten Sie die URL https://d1234.cloudfront.net?fle-profile=SampleProfile anstelle von https://d1234.cloudfront.net verwenden, um CloudFront für diese Anforderung SampleProfile statt dem für den Inhaltstyp der Anforderung eingerichteten Profil verwenden zu lassen.

Sie können bis zu 10 Konfigurationen für ein einzelnes Konto erstellen und dann eine der Konfigurationen dem Cache-Verhalten einer beliebigen Verteilung für das Konto zuordnen.

So erstellen Sie eine Konfiguration für die Verschlüsselung auf Feldebene (Konsole)
  1. Wählen Sie auf der Seite Verschlüsselung auf Feldebene die Option Create configuration (Konfiguration erstellen) aus.

    Hinweis: Wenn Sie nicht mindestens ein Profil erstellt haben, wird die Option zum Erstellen einer Konfiguration nicht angezeigt.

  2. Füllen Sie die folgenden Felder aus, um das zu verwendende Profil anzugeben. (Einige Felder können nicht geändert werden.)

    Inhaltstyp (kann nicht geändert werden)

    Der Inhaltstyp ist auf application/x-www-form-urlencoded festgelegt und nicht änderbar.

    Default profile ID (optional)

    Wählen Sie in der Dropdown-Liste das Profil aus, das Sie dem Inhaltstyp im Feld Content type zuordnen möchten.

    Content-Format (kann nicht geändert werden)

    Das Content-Format ist auf URLencoded festgelegt und nicht änderbar.

  3. Wenn Sie das Standardverhalten von CloudFront für die folgenden Optionen ändern möchten, aktivieren Sie das entsprechende Kontrollkästchen.

    Weiterleiten der Anfrage an den Ursprung, wenn der Inhaltstyp der Anfrage nicht konfiguriert ist.

    Aktivieren Sie das Kontrollkästchen, wenn Sie zulassen möchten, dass die Anfrage an Ihren Ursprung geht, wenn Sie kein Profil für den Inhaltstyp der Anfrage angegeben haben.

    Überschreiben des Profils für einen Inhaltstyp mit einem bereitgestellten Abfrageargument

    Aktivieren Sie das Kontrollkästchen, wenn Sie zulassen möchten, dass ein in einem Abfrageargument angegebenes Profil das Profil überschreibt, das Sie für einen Inhaltstyp angegeben haben.

  4. Wenn Sie das Kontrollkästchen aktivieren, damit ein Abfrageargument das Standardprofil überschreiben kann, müssen Sie die folgenden zusätzlichen Felder für die Konfiguration ausfüllen. Sie können bis zu fünf dieser Abfrageargumentzuordnungen für die Verwendung mit Abfragen erstellen.

    Query argument

    Geben Sie den Wert ein, den Sie für URLs für das fle-profile-Abfrageargument einbeziehen möchten. Dieser Wert signalisiert CloudFront, dass die mit diesem Abfrageargument verknüpfte Profil-ID (die Sie im nächsten Feld angeben), für die Verschlüsselung auf Feldebene für diese Abfrage verwendet werden soll.

    Die maximale Anzahl der Zeichen beträgt 128. Der Wert darf keine Leerzeichen enthalten und darf nur alphanumerische Zeichen oder die folgenden Zeichen enthalten: Bindestrich (-), Punkt (.), Unterstrich (_), Stern (*), Pluszeichen (+), Prozent (%).

    Profile ID

    Wählen Sie in der Dropdown-Liste das Profil aus, das Sie mit dem Wert verknüpfen möchten, den Sie für Query argument eingegeben haben.

    Weiterleiten der Anfrage an den Ursprung, wenn das in einem Abfrageargument angegebene Profil nicht existiert.

    Aktivieren Sie das Kontrollkästchen, wenn Sie zulassen möchten, dass die Anforderung zu Ihrem Ursprung weitergeleitet wird, wenn das in einem Abfrageargument angegebene Profil nicht in CloudFront definiert ist.

Schritt 5: Hinzufügen einer Konfiguration zu einem Cache-Verhalten

Um eine Verschlüsselung auf Feldebene zu verwenden, verknüpfen Sie eine Konfiguration mit einem Cache-Verhalten für eine Verteilung, indem Sie die Konfigurations-ID als Wert für Ihre Verteilung hinzufügen.

Wichtig

Um eine Verschlüsselungskonfiguration auf Feldebene mit einem Cacheverhalten zu verknüpfen, muss die Verteilung so konfiguriert sein, dass sie immer HTTPS verwendet und HTTP POST- und PUT-Anforderungen von Viewern akzeptiert. D.h., eine der folgenden Bedingungen muss erfüllt sein:

  • Die Viewer Protocol Policy (Viewer-Protokollrichtlinie) des Cacheverhaltens muss Redirect HTTP to HTTPS (HTTP zu HTTPS umleiten) oder HTTPS only (Nur HTTPS) sein. (In AWS CloudFormation oder der CloudFront-API muss ViewerProtocolPolicy auf redirect-to-https oder https-only festgelegt sein.)

  • Die Allowed HTTP Methods (Erlaubte HTTP-Methoden) des Cache-Verhaltens müssen auf GET, HEAD, OPTIONS, PUT, POST, PATCH, DELETE gesetzt sein. (In AWS CloudFormation oder der CloudFront-API muss AllowedMethods auf GET, HEAD, OPTIONS, PUT, POST, PATCH, DELETE festgelegt werden. Diese können in beliebiger Reihenfolge angegeben werden.)

  • Die Origin Protocol Policy (Ursprungsprotokollrichtlinie) der Ursprungseinstellungen muss auf Match Viewer (Übereinstimmung mit Viewer) oder HTTPS Only (Nur HTTPS) festgelegt sein. (In AWS CloudFormation oder der CloudFront-API muss OriginProtocolPolicy auf match-viewer oder https-only festgelegt sein.)

Weitere Informationen finden Sie unter Werte, die Sie beim Erstellen oder Aktualisieren einer Verteilung angeben.

Entschlüsselung von Datenfeldern an Ihrem Ursprung

CloudFront verschlüsselt Datenfelder mit dem AWS Encryption SDK. Die Daten bleiben während des gesamten Anwendungs-Stacks verschlüsselt und können nur von Anwendungen abgerufen werden, die über die Anmeldeinformationen verfügen, um sie zu entschlüsseln.

Nach der Verschlüsselung wird der Verschlüsselungstext base64-kodiert. Wenn Ihre Anwendungen den Text am Ursprung entschlüsseln, müssen sie zuerst den Verschlüsselungstext entschlüsseln und dann das AWS Encryption SDK verwenden, um die Daten zu entschlüsseln.

Das folgende Codebeispiel veranschaulicht, wie Anwendungen Daten an Ihrem Ursprung entschlüsseln können. Beachten Sie Folgendes:

  • Um das Beispiel zu vereinfachen, lädt dieses Beispiel öffentliche und private Schlüssel (im DER-Format) aus Dateien im Arbeitsverzeichnis. In der Praxis würden Sie den privaten Schlüssel an einem sicheren Offline-Platz, wie z. B. einem Offline-Hardware-Sicherheitsmodul, aufbewahren und den öffentlichen Schlüssel an Ihr Entwicklungsteam verteilen.

  • CloudFront verwendet spezifische Informationen, während die Daten verschlüsselt werden. Die gleichen Parameter sollten am Ursprung verwendet werden, um sie zu entschlüsseln. Die Parameter, die CloudFront bei der Initialisierung des MasterKeys verwendet, beinhalten Folgendes:

    • PROVIDER_NAME: Sie haben diesen Wert beim Anlegen eines Verschlüsselungsprofils auf Feldebene angegeben. Verwenden Sie hier denselben Wert.

    • KEY_NAME: Sie haben einen Namen für Ihren öffentlichen Schlüssel erstellt, als Sie ihn in CloudFront hochgeladen haben, und dann den Schlüsselnamen im Profil angegeben. Verwenden Sie hier denselben Wert.

    • ALGORITHMUS: CloudFront verwendet RSA/ECB/OAEPWithSHA-256AndMGF1Padding als Algorithmus für die Verschlüsselung. Zum Entschlüsseln der Daten müssen Sie daher den gleichen Algorithmus verwenden.

  • Wenn Sie das folgende Beispielprogramm mit dem Verschlüsselungstext als Eingabe ausführen, werden die entschlüsselten Daten in Ihrer Konsole ausgegeben. Weitere Informationen finden Sie im Java-Beispielcode im AWS Encryption SDK.

Beispiel-Code

import java.nio.file.Files; import java.nio.file.Paths; import java.security.KeyFactory; import java.security.PrivateKey; import java.security.PublicKey; import java.security.spec.PKCS8EncodedKeySpec; import java.security.spec.X509EncodedKeySpec; import org.apache.commons.codec.binary.Base64; import com.amazonaws.encryptionsdk.AwsCrypto; import com.amazonaws.encryptionsdk.CryptoResult; import com.amazonaws.encryptionsdk.jce.JceMasterKey; /** * Sample example of decrypting data that has been encrypted by CloudFront field-level encryption. */ public class DecryptExample { private static final String PRIVATE_KEY_FILENAME = "private_key.der"; private static final String PUBLIC_KEY_FILENAME = "public_key.der"; private static PublicKey publicKey; private static PrivateKey privateKey; // CloudFront uses the following values to encrypt data, and your origin must use same values to decrypt it. // In your own code, for PROVIDER_NAME, use the provider name that you specified when you created your field-level // encryption profile. This sample uses 'DEMO' for the value. private static final String PROVIDER_NAME = "DEMO"; // In your own code, use the key name that you specified when you added your public key to CloudFront. This sample // uses 'DEMOKEY' for the key name. private static final String KEY_NAME = "DEMOKEY"; // CloudFront uses this algorithm when encrypting data. private static final String ALGORITHM = "RSA/ECB/OAEPWithSHA-256AndMGF1Padding"; public static void main(final String[] args) throws Exception { final String dataToDecrypt = args[0]; // This sample uses files to get public and private keys. // In practice, you should distribute the public key and save the private key in secure storage. populateKeyPair(); System.out.println(decrypt(debase64(dataToDecrypt))); } private static String decrypt(final byte[] bytesToDecrypt) throws Exception { // You can decrypt the stream only by using the private key. // 1. Instantiate the SDK final AwsCrypto crypto = new AwsCrypto(); // 2. Instantiate a JCE master key final JceMasterKey masterKey = JceMasterKey.getInstance( publicKey, privateKey, PROVIDER_NAME, KEY_NAME, ALGORITHM); // 3. Decrypt the data final CryptoResult <byte[], ? > result = crypto.decryptData(masterKey, bytesToDecrypt); return new String(result.getResult()); } // Function to decode base64 cipher text. private static byte[] debase64(final String value) { return Base64.decodeBase64(value.getBytes()); } private static void populateKeyPair() throws Exception { final byte[] PublicKeyBytes = Files.readAllBytes(Paths.get(PUBLIC_KEY_FILENAME)); final byte[] privateKeyBytes = Files.readAllBytes(Paths.get(PRIVATE_KEY_FILENAME)); publicKey = KeyFactory.getInstance("RSA").generatePublic(new X509EncodedKeySpec(PublicKeyBytes)); privateKey = KeyFactory.getInstance("RSA").generatePrivate(new PKCS8EncodedKeySpec(privateKeyBytes)); } }