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 17 package com.google.crypto.tink.testing; 18 19 import com.google.crypto.tink.StreamingAead; 20 import com.google.crypto.tink.testing.proto.CreationRequest; 21 import com.google.crypto.tink.testing.proto.CreationResponse; 22 import com.google.crypto.tink.testing.proto.StreamingAeadDecryptRequest; 23 import com.google.crypto.tink.testing.proto.StreamingAeadDecryptResponse; 24 import com.google.crypto.tink.testing.proto.StreamingAeadEncryptRequest; 25 import com.google.crypto.tink.testing.proto.StreamingAeadEncryptResponse; 26 import com.google.crypto.tink.testing.proto.StreamingAeadGrpc.StreamingAeadImplBase; 27 import com.google.protobuf.ByteString; 28 import io.grpc.stub.StreamObserver; 29 import java.io.ByteArrayOutputStream; 30 import java.io.IOException; 31 import java.io.InputStream; 32 import java.io.OutputStream; 33 import java.security.GeneralSecurityException; 34 35 /** Implements a gRPC StreamingAead Testing service. */ 36 public final class StreamingAeadServiceImpl extends StreamingAeadImplBase { 37 StreamingAeadServiceImpl()38 public StreamingAeadServiceImpl() throws GeneralSecurityException { 39 } 40 41 @Override create(CreationRequest request, StreamObserver<CreationResponse> responseObserver)42 public void create(CreationRequest request, StreamObserver<CreationResponse> responseObserver) { 43 Util.createPrimitiveForRpc(request, responseObserver, StreamingAead.class); 44 } 45 encrypt(StreamingAeadEncryptRequest request)46 private StreamingAeadEncryptResponse encrypt(StreamingAeadEncryptRequest request) 47 throws GeneralSecurityException { 48 try { 49 StreamingAead streamingAead = 50 Util.parseBinaryProtoKeyset(request.getAnnotatedKeyset()) 51 .getPrimitive(StreamingAead.class); 52 53 ByteArrayOutputStream ciphertextStream = new ByteArrayOutputStream(); 54 try (OutputStream encryptingStream = 55 streamingAead.newEncryptingStream( 56 ciphertextStream, request.getAssociatedData().toByteArray())) { 57 request.getPlaintext().writeTo(encryptingStream); 58 } 59 return StreamingAeadEncryptResponse.newBuilder() 60 .setCiphertext(ByteString.copyFrom(ciphertextStream.toByteArray())) 61 .build(); 62 63 } catch (GeneralSecurityException e) { 64 return StreamingAeadEncryptResponse.newBuilder().setErr(e.toString()).build(); 65 } catch (IOException e) { 66 throw new GeneralSecurityException(e); 67 } 68 } 69 70 @Override encrypt( StreamingAeadEncryptRequest request, StreamObserver<StreamingAeadEncryptResponse> responseObserver)71 public void encrypt( 72 StreamingAeadEncryptRequest request, 73 StreamObserver<StreamingAeadEncryptResponse> responseObserver) { 74 try { 75 responseObserver.onNext(encrypt(request)); 76 responseObserver.onCompleted(); 77 } catch (GeneralSecurityException e) { 78 responseObserver.onError(e); 79 } 80 } 81 decrypt(StreamingAeadDecryptRequest request)82 private StreamingAeadDecryptResponse decrypt(StreamingAeadDecryptRequest request) 83 throws GeneralSecurityException { 84 try { 85 StreamingAead streamingAead = 86 Util.parseBinaryProtoKeyset(request.getAnnotatedKeyset()) 87 .getPrimitive(StreamingAead.class); 88 89 InputStream ciphertextStream = request.getCiphertext().newInput(); 90 InputStream decryptingStream = streamingAead.newDecryptingStream( 91 ciphertextStream, request.getAssociatedData().toByteArray()); 92 ByteArrayOutputStream plaintextStream = new ByteArrayOutputStream(); 93 while (true) { 94 int bytesRead = decryptingStream.read(); 95 if (bytesRead == -1) { 96 break; 97 } 98 plaintextStream.write(bytesRead); 99 } 100 101 return StreamingAeadDecryptResponse.newBuilder().setPlaintext( 102 ByteString.copyFrom(plaintextStream.toByteArray())).build(); 103 } catch (GeneralSecurityException | IOException e) { 104 return StreamingAeadDecryptResponse.newBuilder().setErr(e.toString()).build(); 105 } 106 } 107 108 @Override decrypt( StreamingAeadDecryptRequest request, StreamObserver<StreamingAeadDecryptResponse> responseObserver)109 public void decrypt( 110 StreamingAeadDecryptRequest request, 111 StreamObserver<StreamingAeadDecryptResponse> responseObserver) { 112 try { 113 responseObserver.onNext(decrypt(request)); 114 responseObserver.onCompleted(); 115 } catch (GeneralSecurityException e) { 116 responseObserver.onError(e); 117 } 118 } 119 } 120