xref: /aosp_15_r20/external/tink/go/hybrid/subtle/ecies_aead_hkdf_hybrid_encrypt.go (revision e7b1675dde1b92d52ec075b0a92829627f2c52a5)
1// Copyright 2020 Google LLC
2//
3// Licensed under the Apache License, Version 2.0 (the "License");
4// you may not use this file except in compliance with the License.
5// You may obtain a copy of the License at
6//
7//      http://www.apache.org/licenses/LICENSE-2.0
8//
9// Unless required by applicable law or agreed to in writing, software
10// distributed under the License is distributed on an "AS IS" BASIS,
11// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12// See the License for the specific language governing permissions and
13// limitations under the License.
14//
15////////////////////////////////////////////////////////////////////////////////
16
17package subtle
18
19import (
20	"bytes"
21	"errors"
22
23	"github.com/google/tink/go/tink"
24)
25
26// ECIESAEADHKDFHybridEncrypt is an instance of ECIES encryption with HKDF-KEM (key encapsulation mechanism)
27// and AEAD-DEM (data encapsulation mechanism).
28type ECIESAEADHKDFHybridEncrypt struct {
29	publicKey    *ECPublicKey
30	hkdfSalt     []byte
31	hkdfHMACAlgo string
32	pointFormat  string
33	demHelper    EciesAEADHKDFDEMHelper
34}
35
36// NewECIESAEADHKDFHybridEncrypt returns ECIES encryption construct with HKDF-KEM (key encapsulation mechanism)
37// and AEAD-DEM (data encapsulation mechanism).
38func NewECIESAEADHKDFHybridEncrypt(pub *ECPublicKey, hkdfSalt []byte, hkdfHMACAlgo string, ptFormat string, demHelper EciesAEADHKDFDEMHelper) (*ECIESAEADHKDFHybridEncrypt, error) {
39	c, err := GetCurve(pub.Curve.Params().Name)
40	if err != nil {
41		return nil, err
42	}
43	return &ECIESAEADHKDFHybridEncrypt{
44		publicKey: &ECPublicKey{
45			Curve: c,
46			Point: pub.Point,
47		},
48		hkdfSalt:     hkdfSalt,
49		hkdfHMACAlgo: hkdfHMACAlgo,
50		pointFormat:  ptFormat,
51		demHelper:    demHelper,
52	}, nil
53}
54
55// Encrypt is used to encrypt using ECIES with a HKDF-KEM and AEAD-DEM mechanisms.
56func (e *ECIESAEADHKDFHybridEncrypt) Encrypt(plaintext, contextInfo []byte) ([]byte, error) {
57	var b bytes.Buffer
58	sKem := &ECIESHKDFSenderKem{
59		recipientPublicKey: e.publicKey,
60	}
61	kemKey, err := sKem.encapsulate(e.hkdfHMACAlgo, e.hkdfSalt, contextInfo, e.demHelper.GetSymmetricKeySize(), e.pointFormat)
62	if err != nil {
63		return nil, err
64	}
65	prim, err := e.demHelper.GetAEADOrDAEAD(kemKey.SymmetricKey)
66	if err != nil {
67		return nil, err
68	}
69	var ct []byte
70	switch a := prim.(type) {
71	case tink.AEAD:
72		ct, err = a.Encrypt(plaintext, []byte{})
73	case tink.DeterministicAEAD:
74		ct, err = a.EncryptDeterministically(plaintext, []byte{})
75	default:
76		err = errors.New("Internal error: unexpected primitive type")
77	}
78	if err != nil {
79		return nil, err
80	}
81	b.Write(kemKey.Kem)
82	b.Write(ct)
83	return b.Bytes(), nil
84}
85