All Downloads are FREE. Search and download functionalities are using the official Maven repository.

de.gematik.bbriccs.rest.vau.VauProtocol Maven / Gradle / Ivy

The newest version!
/*
 * Copyright 2024 gematik GmbH
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package de.gematik.bbriccs.rest.vau;

import de.gematik.bbriccs.crypto.BC;
import de.gematik.bbriccs.rest.vau.exceptions.VauProtocolException;
import java.nio.ByteBuffer;
import java.nio.charset.StandardCharsets;
import java.security.SecureRandom;
import java.security.interfaces.ECPublicKey;
import java.util.Random;
import javax.crypto.BadPaddingException;
import javax.crypto.SecretKey;
import lombok.Getter;
import lombok.SneakyThrows;
import lombok.val;

public class VauProtocol {

  private final Random rnd;
  private final ECPublicKey publicKey;
  @Getter private final SecretKey decryptionKey;
  @Getter private final VauVersion vauVersion;

  public VauProtocol(VauVersion vauVersion, ECPublicKey publicKey) {
    this.rnd = new SecureRandom();
    this.vauVersion = vauVersion;
    this.publicKey = publicKey;
    this.decryptionKey = BC.generateAESDecryptionKey(vauVersion.getKeySize());
  }

  @SuppressWarnings({"java:S1130"})
  public byte[] decrypt(byte[] innerHttp) throws BadPaddingException {
    return vauVersion.getSymmetricMethod().decrypt(decryptionKey, innerHttp);
  }

  public VauEncryptionEnvelope encrypt(String accessToken, byte[] innerHttp) {
    val symmetricalKeyHex = this.toLowerCaseHex(decryptionKey.getEncoded());
    val requestId = this.genRequestId(vauVersion.getReqIdSize());
    val requestIdHex = this.toLowerCaseHex(requestId);
    val encrypted =
        vauVersion
            .getAsymmetricMethod()
            .encrypt(
                publicKey,
                composeInnerHttp(
                    innerHttp,
                    vauVersion.getVersionForInnerHttp(),
                    accessToken.getBytes(StandardCharsets.UTF_8),
                    requestIdHex,
                    symmetricalKeyHex));
    return new VauEncryptionEnvelope(vauVersion, decryptionKey, requestId, accessToken, encrypted);
  }

  private byte[] genRequestId(int size) {
    val requestId = new byte[size];
    this.rnd.nextBytes(requestId);
    return requestId;
  }

  private byte[] toLowerCaseHex(byte[] data) {
    val buffer = new byte[data.length * 2];
    for (int i = 0; i < data.length; i++) {
      val value = data[i] & 0xFF;
      buffer[i * 2] = hexMap((value / 16) % 16);
      buffer[i * 2 + 1] = hexMap(value % 16);
    }
    return buffer;
  }

  @SneakyThrows
  private byte hexMap(int intValue) {
    if (intValue >= 0 && intValue <= 9) {
      val integerValue = Integer.valueOf(intValue + 48);
      return integerValue.byteValue();
    } else if (intValue >= 10 && intValue <= 15) {
      val integerValue = Integer.valueOf(intValue + 97 - 10);
      return integerValue.byteValue();
    } else {
      throw new VauProtocolException("parameter must be between 0 to 15");
    }
  }

  private byte[] composeInnerHttp(
      byte[] innerHttp, char version, byte[] bearer, byte[] requestId, byte[] symmetricalKey) {
    val byteSpace = (byte) 32;
    val len =
        1
            + 1
            + bearer.length
            + 1
            + requestId.length
            + 1
            + symmetricalKey.length
            + 1
            + innerHttp.length;
    return ByteBuffer.allocate(len)
        .put((byte) version)
        .put(byteSpace)
        .put(bearer)
        .put(byteSpace)
        .put(requestId)
        .put(byteSpace)
        .put(symmetricalKey)
        .put(byteSpace)
        .put(innerHttp)
        .array();
  }
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy