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