blob: 70ef63e2509df399eb51a8189cdadd1a5abbfeb0 [file] [log] [blame]
// Copyright 2021 Google LLC
//
// 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 com.google.crypto.tink.hybrid.internal;
import com.google.crypto.tink.HybridEncrypt;
import com.google.crypto.tink.proto.HpkeParams;
import com.google.crypto.tink.proto.HpkePublicKey;
import com.google.crypto.tink.subtle.Bytes;
import com.google.errorprone.annotations.Immutable;
import java.security.GeneralSecurityException;
/**
* Hybrid Public Key Encryption (HPKE) encryption.
*
* <p>HPKE RFC: https://www.rfc-editor.org/rfc/rfc9180.html
*/
@Immutable
final class HpkeEncrypt implements HybridEncrypt {
private static final byte[] EMPTY_ASSOCIATED_DATA = new byte[0];
private final HpkePublicKey recipientPublicKey;
private final HpkeKem kem;
private final HpkeKdf kdf;
private final HpkeAead aead;
private HpkeEncrypt(HpkePublicKey recipientPublicKey, HpkeKem kem, HpkeKdf kdf, HpkeAead aead) {
this.recipientPublicKey = recipientPublicKey;
this.kem = kem;
this.kdf = kdf;
this.aead = aead;
}
/** Returns an HPKE encryption primitive created from {@code recipientPublicKey} */
static HpkeEncrypt createHpkeEncrypt(HpkePublicKey recipientPublicKey)
throws GeneralSecurityException {
if (recipientPublicKey.getPublicKey().isEmpty()) {
throw new IllegalArgumentException("HpkePublicKey.public_key is empty.");
}
HpkeParams params = recipientPublicKey.getParams();
HpkeKem kem = HpkePrimitiveFactory.createKem(params);
HpkeKdf kdf = HpkePrimitiveFactory.createKdf(params);
HpkeAead aead = HpkePrimitiveFactory.createAead(params);
return new HpkeEncrypt(recipientPublicKey, kem, kdf, aead);
}
@Override
public byte[] encrypt(final byte[] plaintext, final byte[] contextInfo)
throws GeneralSecurityException {
byte[] info = contextInfo;
if (info == null) {
info = new byte[0];
}
HpkeContext context = HpkeContext.createSenderContext(recipientPublicKey, kem, kdf, aead, info);
byte[] ciphertext = context.seal(plaintext, EMPTY_ASSOCIATED_DATA);
return Bytes.concat(context.getEncapsulatedKey(), ciphertext);
}
}