1*e7b1675dSTing-Kang Chang// Copyright 2020 Google LLC 2*e7b1675dSTing-Kang Chang// 3*e7b1675dSTing-Kang Chang// Licensed under the Apache License, Version 2.0 (the "License"); 4*e7b1675dSTing-Kang Chang// you may not use this file except in compliance with the License. 5*e7b1675dSTing-Kang Chang// You may obtain a copy of the License at 6*e7b1675dSTing-Kang Chang// 7*e7b1675dSTing-Kang Chang// http://www.apache.org/licenses/LICENSE-2.0 8*e7b1675dSTing-Kang Chang// 9*e7b1675dSTing-Kang Chang// Unless required by applicable law or agreed to in writing, software 10*e7b1675dSTing-Kang Chang// distributed under the License is distributed on an "AS IS" BASIS, 11*e7b1675dSTing-Kang Chang// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12*e7b1675dSTing-Kang Chang// See the License for the specific language governing permissions and 13*e7b1675dSTing-Kang Chang// limitations under the License. 14*e7b1675dSTing-Kang Chang// 15*e7b1675dSTing-Kang Chang/////////////////////////////////////////////////////////////////////////////// 16*e7b1675dSTing-Kang Chang 17*e7b1675dSTing-Kang Changpackage services 18*e7b1675dSTing-Kang Chang 19*e7b1675dSTing-Kang Changimport ( 20*e7b1675dSTing-Kang Chang "bytes" 21*e7b1675dSTing-Kang Chang "context" 22*e7b1675dSTing-Kang Chang "fmt" 23*e7b1675dSTing-Kang Chang 24*e7b1675dSTing-Kang Chang "io" 25*e7b1675dSTing-Kang Chang 26*e7b1675dSTing-Kang Chang "github.com/google/tink/go/streamingaead" 27*e7b1675dSTing-Kang Chang pb "github.com/google/tink/testing/go/protos/testing_api_go_grpc" 28*e7b1675dSTing-Kang Chang) 29*e7b1675dSTing-Kang Chang 30*e7b1675dSTing-Kang Changconst ( 31*e7b1675dSTing-Kang Chang decryptChunkSize = 2 32*e7b1675dSTing-Kang Chang) 33*e7b1675dSTing-Kang Chang 34*e7b1675dSTing-Kang Chang// StreamingAEADService implements the StreamingAead testing service. 35*e7b1675dSTing-Kang Changtype StreamingAEADService struct { 36*e7b1675dSTing-Kang Chang pb.StreamingAeadServer 37*e7b1675dSTing-Kang Chang} 38*e7b1675dSTing-Kang Chang 39*e7b1675dSTing-Kang Changfunc (s *StreamingAEADService) Create(ctx context.Context, req *pb.CreationRequest) (*pb.CreationResponse, error) { 40*e7b1675dSTing-Kang Chang handle, err := toKeysetHandle(req.GetAnnotatedKeyset()) 41*e7b1675dSTing-Kang Chang if err != nil { 42*e7b1675dSTing-Kang Chang return &pb.CreationResponse{Err: err.Error()}, nil 43*e7b1675dSTing-Kang Chang } 44*e7b1675dSTing-Kang Chang _, err = streamingaead.New(handle) 45*e7b1675dSTing-Kang Chang if err != nil { 46*e7b1675dSTing-Kang Chang return &pb.CreationResponse{Err: err.Error()}, nil 47*e7b1675dSTing-Kang Chang } 48*e7b1675dSTing-Kang Chang return &pb.CreationResponse{}, nil 49*e7b1675dSTing-Kang Chang} 50*e7b1675dSTing-Kang Chang 51*e7b1675dSTing-Kang Changfunc (s *StreamingAEADService) Encrypt(ctx context.Context, req *pb.StreamingAeadEncryptRequest) (*pb.StreamingAeadEncryptResponse, error) { 52*e7b1675dSTing-Kang Chang handle, err := toKeysetHandle(req.GetAnnotatedKeyset()) 53*e7b1675dSTing-Kang Chang if err != nil { 54*e7b1675dSTing-Kang Chang return &pb.StreamingAeadEncryptResponse{ 55*e7b1675dSTing-Kang Chang Result: &pb.StreamingAeadEncryptResponse_Err{err.Error()}}, nil 56*e7b1675dSTing-Kang Chang } 57*e7b1675dSTing-Kang Chang cipher, err := streamingaead.New(handle) 58*e7b1675dSTing-Kang Chang if err != nil { 59*e7b1675dSTing-Kang Chang return &pb.StreamingAeadEncryptResponse{ 60*e7b1675dSTing-Kang Chang Result: &pb.StreamingAeadEncryptResponse_Err{err.Error()}}, nil 61*e7b1675dSTing-Kang Chang } 62*e7b1675dSTing-Kang Chang ciphertextBuf := &bytes.Buffer{} 63*e7b1675dSTing-Kang Chang w, err := cipher.NewEncryptingWriter(ciphertextBuf, req.AssociatedData) 64*e7b1675dSTing-Kang Chang if err != nil { 65*e7b1675dSTing-Kang Chang errMsg := fmt.Sprintf("cannot create an encrypt writer: %v", err) 66*e7b1675dSTing-Kang Chang return &pb.StreamingAeadEncryptResponse{ 67*e7b1675dSTing-Kang Chang Result: &pb.StreamingAeadEncryptResponse_Err{errMsg}}, nil 68*e7b1675dSTing-Kang Chang } 69*e7b1675dSTing-Kang Chang n, err := w.Write(req.Plaintext) 70*e7b1675dSTing-Kang Chang if err != nil { 71*e7b1675dSTing-Kang Chang errMsg := fmt.Sprintf("error writing to an encrypt writer: %v", err) 72*e7b1675dSTing-Kang Chang return &pb.StreamingAeadEncryptResponse{ 73*e7b1675dSTing-Kang Chang Result: &pb.StreamingAeadEncryptResponse_Err{errMsg}}, nil 74*e7b1675dSTing-Kang Chang } 75*e7b1675dSTing-Kang Chang if n != len(req.Plaintext) { 76*e7b1675dSTing-Kang Chang errMsg := fmt.Sprintf("unexpected number of bytes written. Got=%d;want=%d", n, len(req.Plaintext)) 77*e7b1675dSTing-Kang Chang return &pb.StreamingAeadEncryptResponse{ 78*e7b1675dSTing-Kang Chang Result: &pb.StreamingAeadEncryptResponse_Err{errMsg}}, nil 79*e7b1675dSTing-Kang Chang } 80*e7b1675dSTing-Kang Chang if err := w.Close(); err != nil { 81*e7b1675dSTing-Kang Chang errMsg := fmt.Sprintf("error closing writer: %v", err) 82*e7b1675dSTing-Kang Chang return &pb.StreamingAeadEncryptResponse{ 83*e7b1675dSTing-Kang Chang Result: &pb.StreamingAeadEncryptResponse_Err{errMsg}}, nil 84*e7b1675dSTing-Kang Chang } 85*e7b1675dSTing-Kang Chang return &pb.StreamingAeadEncryptResponse{ 86*e7b1675dSTing-Kang Chang Result: &pb.StreamingAeadEncryptResponse_Ciphertext{ciphertextBuf.Bytes()}}, nil 87*e7b1675dSTing-Kang Chang} 88*e7b1675dSTing-Kang Chang 89*e7b1675dSTing-Kang Changfunc (s *StreamingAEADService) Decrypt(ctx context.Context, req *pb.StreamingAeadDecryptRequest) (*pb.StreamingAeadDecryptResponse, error) { 90*e7b1675dSTing-Kang Chang handle, err := toKeysetHandle(req.GetAnnotatedKeyset()) 91*e7b1675dSTing-Kang Chang if err != nil { 92*e7b1675dSTing-Kang Chang return &pb.StreamingAeadDecryptResponse{ 93*e7b1675dSTing-Kang Chang Result: &pb.StreamingAeadDecryptResponse_Err{err.Error()}}, nil 94*e7b1675dSTing-Kang Chang } 95*e7b1675dSTing-Kang Chang cipher, err := streamingaead.New(handle) 96*e7b1675dSTing-Kang Chang if err != nil { 97*e7b1675dSTing-Kang Chang return &pb.StreamingAeadDecryptResponse{ 98*e7b1675dSTing-Kang Chang Result: &pb.StreamingAeadDecryptResponse_Err{err.Error()}}, nil 99*e7b1675dSTing-Kang Chang } 100*e7b1675dSTing-Kang Chang r, err := cipher.NewDecryptingReader(bytes.NewBuffer(req.Ciphertext), req.AssociatedData) 101*e7b1675dSTing-Kang Chang if err != nil { 102*e7b1675dSTing-Kang Chang errMsg := fmt.Sprintf("cannot create an encrypt reader: %v", err) 103*e7b1675dSTing-Kang Chang return &pb.StreamingAeadDecryptResponse{ 104*e7b1675dSTing-Kang Chang Result: &pb.StreamingAeadDecryptResponse_Err{errMsg}}, nil 105*e7b1675dSTing-Kang Chang } 106*e7b1675dSTing-Kang Chang plaintextBuf := &bytes.Buffer{} 107*e7b1675dSTing-Kang Chang var ( 108*e7b1675dSTing-Kang Chang chunk = make([]byte, decryptChunkSize) 109*e7b1675dSTing-Kang Chang eof = false 110*e7b1675dSTing-Kang Chang ) 111*e7b1675dSTing-Kang Chang for !eof { 112*e7b1675dSTing-Kang Chang n, err := r.Read(chunk) 113*e7b1675dSTing-Kang Chang if err != nil && err != io.EOF { 114*e7b1675dSTing-Kang Chang errMsg := fmt.Sprintf("error reading chunk: %v", err) 115*e7b1675dSTing-Kang Chang return &pb.StreamingAeadDecryptResponse{ 116*e7b1675dSTing-Kang Chang Result: &pb.StreamingAeadDecryptResponse_Err{errMsg}}, nil 117*e7b1675dSTing-Kang Chang } 118*e7b1675dSTing-Kang Chang eof = err == io.EOF 119*e7b1675dSTing-Kang Chang plaintextBuf.Write(chunk[:n]) 120*e7b1675dSTing-Kang Chang } 121*e7b1675dSTing-Kang Chang return &pb.StreamingAeadDecryptResponse{ 122*e7b1675dSTing-Kang Chang Result: &pb.StreamingAeadDecryptResponse_Plaintext{plaintextBuf.Bytes()}}, nil 123*e7b1675dSTing-Kang Chang} 124