Anforderungen  |   Konzepte  |   Entwurf  |   Entwicklung  |   Qualitätssicherung  |   Lebenszyklus  |   Steuerung
 
 
 
 


Quelle  ece.js   Sprache: JAVA

 
async function HKDF({ salt, ikm, info, length }) {
  return await crypto.subtle.deriveBits(
    { name: "HKDF", hash: "SHA-256", salt, info },
    await crypto.subtle.importKey("raw", ikm, { name: "HKDF" }, false, [
      "deriveBits",
    ]),
    length * 8
  );
}

// https://datatracker.ietf.org/doc/html/rfc8188#section-2.2
// https://datatracker.ietf.org/doc/html/rfc8188#section-2.3
async function deriveKeyAndNonce(header) {
  const { salt } = header;
  const ikm = await getInputKeyingMaterial(header);

  // cek_info = "Content-Encoding: aes128gcm" || 0x00
  const cekInfo = new TextEncoder().encode("Content-Encoding: aes128gcm\0");
  // nonce_info = "Content-Encoding: nonce" || 0x00
  const nonceInfo = new TextEncoder().encode("Content-Encoding: nonce\0");

  // (The XOR SEQ is skipped as we only create single record here, thus becoming noop)
  return {
    // the length (L) parameter to HKDF is 16
    key: await HKDF({ salt, ikm, info: cekInfo, length: 16 }),
    // The length (L) parameter is 12 octets
    nonce: await HKDF({ salt, ikm, info: nonceInfo, length: 12 }),
  };
}

// https://datatracker.ietf.org/doc/html/rfc8291#section-3.3
// https://datatracker.ietf.org/doc/html/rfc8291#section-3.4
async function getInputKeyingMaterial(header) {
  // IKM:  the shared secret derived using ECDH
  // ecdh_secret = ECDH(as_private, ua_public)
  const ikm = await crypto.subtle.deriveBits(
    {
      name: "ECDH",
      public: await crypto.subtle.importKey(
        "raw",
        header.userAgentPublicKey,
        { name: "ECDH", namedCurve: "P-256" },
        true,
        []
      ),
    },
    header.appServer.privateKey,
    256
  );
  // key_info = "WebPush: info" || 0x00 || ua_public || as_public
  const keyInfo = new Uint8Array([
    ...new TextEncoder().encode("WebPush: info\0"),
    ...header.userAgentPublicKey,
    ...header.appServer.publicKey,
  ])
  return await HKDF({ salt: header.authSecret, ikm, info: keyInfo, length: 32 });
}

// https://datatracker.ietf.org/doc/html/rfc8188#section-2
async function encryptRecord(key, nonce, data) {
  // add a delimiter octet (0x01 or 0x02)
  // The last record uses a padding delimiter octet set to the value 2
  //
  // (This implementation only creates a single record, thus always 2,
  // per https://datatracker.ietf.org/doc/html/rfc8291/#section-4:
  // An application server MUST encrypt a push message with a single
  // record.)
  const padded = new Uint8Array([...data, 2]);

  // encrypt with AEAD_AES_128_GCM
  return await crypto.subtle.encrypt(
    { name: "AES-GCM", iv: nonce, tagLength: 128 },
    await crypto.subtle.importKey("raw", key, { name: "AES-GCM" }, false, [
      "encrypt",
    ]),
    padded
  );
}

// https://datatracker.ietf.org/doc/html/rfc8188#section-2.1
function writeHeader(header) {
  var dataView = new DataView(new ArrayBuffer(5));
  dataView.setUint32(0, header.recordSize);
  dataView.setUint8(4, header.keyid.length);
  return new Uint8Array([
    ...header.salt,
    ...new Uint8Array(dataView.buffer),
    ...header.keyid,
  ]);
}

function validateParams(params) {
  const header = { ...params };
  if (!header.salt) {
    throw new Error("Must include a salt parameter");
  }
  if (header.salt.length !== 16) {
    // https://datatracker.ietf.org/doc/html/rfc8188#section-2.1
    // The "salt" parameter comprises the first 16 octets of the
    // "aes128gcm" content-coding header.
    throw new Error("The salt parameter must be 16 bytes");
  }
  if (header.appServer.publicKey.byteLength !== 65) {
    // https://datatracker.ietf.org/doc/html/rfc8291#section-4
    // A push message MUST include the application server ECDH public key in
    // the "keyid" parameter of the encrypted content coding header.  The
    // uncompressed point form defined in [X9.62] (that is, a 65-octet
    // sequence that starts with a 0x04 octet) forms the entirety of the
    // "keyid".
    throw new Error("The appServer.publicKey parameter must be 65 bytes");
  }
  if (!header.authSecret) {
    throw new Error("No authentication secret for webpush");
  }
  return header;
}

export async function encrypt(data, params) {
  const header = validateParams(params);

  // https://datatracker.ietf.org/doc/html/rfc8291#section-2
  // The ECDH public key is encoded into the "keyid" parameter of the encrypted content coding header
  header.keyid = header.appServer.publicKey;
  header.recordSize = data.byteLength + 18 + 1;

  // https://datatracker.ietf.org/doc/html/rfc8188#section-2
  // The final encoding consists of a header (see Section 2.1) and zero or more
  // fixed-size encrypted records; the final record can be smaller than the record size.
  const saltedHeader = writeHeader(header);
  const { key, nonce } = await deriveKeyAndNonce(header);
  const encrypt = await encryptRecord(key, nonce, data);
  return new Uint8Array([...saltedHeader, ...new Uint8Array(encrypt)]);
}

Messung V0.5
C=86 H=91 G=88

¤ Dauer der Verarbeitung: 0.13 Sekunden  (vorverarbeitet)  ¤

*© Formatika GbR, Deutschland






Wurzel

Suchen

Beweissystem der NASA

Beweissystem Isabelle

NIST Cobol Testsuite

Cephes Mathematical Library

Wiener Entwicklungsmethode

Haftungshinweis

Die Informationen auf dieser Webseite wurden nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit, noch Qualität der bereit gestellten Informationen zugesichert.

Bemerkung:

Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.






                                                                                                                                                                                                                                                                                                                                                                                                     


Neuigkeiten

     Aktuelles
     Motto des Tages

Software

     Produkte
     Quellcodebibliothek

Aktivitäten

     Artikel über Sicherheit
     Anleitung zur Aktivierung von SSL

Muße

     Gedichte
     Musik
     Bilder

Jenseits des Üblichen ....
    

Besucherstatistik

Besucherstatistik

Monitoring

Montastic status badge