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 static java.nio.charset.StandardCharsets.UTF_8; 20 21 import com.google.crypto.tink.Aead; 22 import com.google.crypto.tink.InsecureSecretKeyAccess; 23 import com.google.crypto.tink.KeyTemplate; 24 import com.google.crypto.tink.KeyTemplates; 25 import com.google.crypto.tink.KeysetHandle; 26 import com.google.crypto.tink.TinkJsonProtoKeysetFormat; 27 import com.google.crypto.tink.TinkProtoKeysetFormat; 28 import com.google.crypto.tink.internal.KeyTemplateProtoConverter; 29 import com.google.crypto.tink.testing.proto.KeysetFromJsonRequest; 30 import com.google.crypto.tink.testing.proto.KeysetFromJsonResponse; 31 import com.google.crypto.tink.testing.proto.KeysetGenerateRequest; 32 import com.google.crypto.tink.testing.proto.KeysetGenerateResponse; 33 import com.google.crypto.tink.testing.proto.KeysetGrpc.KeysetImplBase; 34 import com.google.crypto.tink.testing.proto.KeysetPublicRequest; 35 import com.google.crypto.tink.testing.proto.KeysetPublicResponse; 36 import com.google.crypto.tink.testing.proto.KeysetReadEncryptedRequest; 37 import com.google.crypto.tink.testing.proto.KeysetReadEncryptedResponse; 38 import com.google.crypto.tink.testing.proto.KeysetReaderType; 39 import com.google.crypto.tink.testing.proto.KeysetTemplateRequest; 40 import com.google.crypto.tink.testing.proto.KeysetTemplateResponse; 41 import com.google.crypto.tink.testing.proto.KeysetToJsonRequest; 42 import com.google.crypto.tink.testing.proto.KeysetToJsonResponse; 43 import com.google.crypto.tink.testing.proto.KeysetWriteEncryptedRequest; 44 import com.google.crypto.tink.testing.proto.KeysetWriteEncryptedResponse; 45 import com.google.crypto.tink.testing.proto.KeysetWriterType; 46 import com.google.protobuf.ByteString; 47 import io.grpc.stub.StreamObserver; 48 import java.security.GeneralSecurityException; 49 50 /** Implement a gRPC Keyset Testing service. */ 51 public final class KeysetServiceImpl extends KeysetImplBase { 52 KeysetServiceImpl()53 public KeysetServiceImpl() throws GeneralSecurityException { 54 } 55 56 @Override getTemplate( KeysetTemplateRequest request, StreamObserver<KeysetTemplateResponse> responseObserver)57 public void getTemplate( 58 KeysetTemplateRequest request, StreamObserver<KeysetTemplateResponse> responseObserver) { 59 KeysetTemplateResponse response; 60 try { 61 KeyTemplate template = KeyTemplates.get(request.getTemplateName()); 62 response = 63 KeysetTemplateResponse.newBuilder() 64 .setKeyTemplate(ByteString.copyFrom(KeyTemplateProtoConverter.toByteArray(template))) 65 .build(); 66 } catch (GeneralSecurityException e) { 67 response = KeysetTemplateResponse.newBuilder().setErr(e.toString()).build(); 68 } 69 responseObserver.onNext(response); 70 responseObserver.onCompleted(); 71 } 72 73 @Override generate( KeysetGenerateRequest request, StreamObserver<KeysetGenerateResponse> responseObserver)74 public void generate( 75 KeysetGenerateRequest request, StreamObserver<KeysetGenerateResponse> responseObserver) { 76 KeysetGenerateResponse response; 77 try { 78 KeyTemplate template = 79 KeyTemplateProtoConverter.fromByteArray(request.getTemplate().toByteArray()); 80 KeysetHandle keysetHandle = KeysetHandle.generateNew(template); 81 byte[] serializedPublicKeyset = 82 TinkProtoKeysetFormat.serializeKeyset(keysetHandle, InsecureSecretKeyAccess.get()); 83 response = 84 KeysetGenerateResponse.newBuilder() 85 .setKeyset(ByteString.copyFrom(serializedPublicKeyset)) 86 .build(); 87 } catch (GeneralSecurityException e) { 88 response = KeysetGenerateResponse.newBuilder().setErr(e.toString()).build(); 89 } 90 responseObserver.onNext(response); 91 responseObserver.onCompleted(); 92 } 93 94 @Override public_( KeysetPublicRequest request, StreamObserver<KeysetPublicResponse> responseObserver)95 public void public_( 96 KeysetPublicRequest request, StreamObserver<KeysetPublicResponse> responseObserver) { 97 KeysetPublicResponse response; 98 try { 99 KeysetHandle privateKeysetHandle = 100 TinkProtoKeysetFormat.parseKeyset( 101 request.getPrivateKeyset().toByteArray(), InsecureSecretKeyAccess.get()); 102 KeysetHandle publicKeysetHandle = privateKeysetHandle.getPublicKeysetHandle(); 103 byte[] serializedPublicKeyset = 104 TinkProtoKeysetFormat.serializeKeyset(publicKeysetHandle, InsecureSecretKeyAccess.get()); 105 response = 106 KeysetPublicResponse.newBuilder() 107 .setPublicKeyset(ByteString.copyFrom(serializedPublicKeyset)) 108 .build(); 109 } catch (GeneralSecurityException e) { 110 response = KeysetPublicResponse.newBuilder().setErr(e.toString()).build(); 111 } 112 responseObserver.onNext(response); 113 responseObserver.onCompleted(); 114 } 115 116 @Override toJson( KeysetToJsonRequest request, StreamObserver<KeysetToJsonResponse> responseObserver)117 public void toJson( 118 KeysetToJsonRequest request, StreamObserver<KeysetToJsonResponse> responseObserver) { 119 KeysetToJsonResponse response; 120 try { 121 KeysetHandle keysetHandle = 122 TinkProtoKeysetFormat.parseKeyset( 123 request.getKeyset().toByteArray(), InsecureSecretKeyAccess.get()); 124 String jsonKeyset = 125 TinkJsonProtoKeysetFormat.serializeKeyset(keysetHandle, InsecureSecretKeyAccess.get()); 126 response = KeysetToJsonResponse.newBuilder().setJsonKeyset(jsonKeyset).build(); 127 } catch (GeneralSecurityException e) { 128 response = KeysetToJsonResponse.newBuilder().setErr(e.toString()).build(); 129 } 130 responseObserver.onNext(response); 131 responseObserver.onCompleted(); 132 } 133 134 @Override fromJson( KeysetFromJsonRequest request, StreamObserver<KeysetFromJsonResponse> responseObserver)135 public void fromJson( 136 KeysetFromJsonRequest request, StreamObserver<KeysetFromJsonResponse> responseObserver) { 137 KeysetFromJsonResponse response; 138 try { 139 KeysetHandle keysetHandle = 140 TinkJsonProtoKeysetFormat.parseKeyset( 141 request.getJsonKeyset(), InsecureSecretKeyAccess.get()); 142 byte[] serializeKeyset = 143 TinkProtoKeysetFormat.serializeKeyset(keysetHandle, InsecureSecretKeyAccess.get()); 144 response = 145 KeysetFromJsonResponse.newBuilder() 146 .setKeyset(ByteString.copyFrom(serializeKeyset)) 147 .build(); 148 } catch (GeneralSecurityException e) { 149 response = KeysetFromJsonResponse.newBuilder().setErr(e.toString()).build(); 150 } 151 responseObserver.onNext(response); 152 responseObserver.onCompleted(); 153 } 154 155 @Override readEncrypted( KeysetReadEncryptedRequest request, StreamObserver<KeysetReadEncryptedResponse> responseObserver)156 public void readEncrypted( 157 KeysetReadEncryptedRequest request, 158 StreamObserver<KeysetReadEncryptedResponse> responseObserver) { 159 KeysetReadEncryptedResponse response; 160 try { 161 // get masterAead 162 KeysetHandle masterKeysetHandle = 163 TinkProtoKeysetFormat.parseKeyset( 164 request.getMasterKeyset().toByteArray(), InsecureSecretKeyAccess.get()); 165 Aead masterAead = masterKeysetHandle.getPrimitive(Aead.class); 166 167 // read encrypted keyset to keysetHandle 168 byte[] associatedData = request.getAssociatedData().getValue().toByteArray(); 169 170 KeysetHandle keysetHandle; 171 if (request.getKeysetReaderType() == KeysetReaderType.KEYSET_READER_BINARY) { 172 keysetHandle = 173 TinkProtoKeysetFormat.parseEncryptedKeyset( 174 request.getEncryptedKeyset().toByteArray(), masterAead, associatedData); 175 } else if (request.getKeysetReaderType() == KeysetReaderType.KEYSET_READER_JSON) { 176 keysetHandle = 177 TinkJsonProtoKeysetFormat.parseEncryptedKeyset( 178 request.getEncryptedKeyset().toStringUtf8(), masterAead, associatedData); 179 } else { 180 throw new IllegalArgumentException("unknown keyset reader type"); 181 } 182 183 // get keyset from keysetHandle 184 byte[] keyset = 185 TinkProtoKeysetFormat.serializeKeyset(keysetHandle, InsecureSecretKeyAccess.get()); 186 response = 187 KeysetReadEncryptedResponse.newBuilder().setKeyset(ByteString.copyFrom(keyset)).build(); 188 } catch (GeneralSecurityException e) { 189 response = KeysetReadEncryptedResponse.newBuilder().setErr(e.toString()).build(); 190 } 191 responseObserver.onNext(response); 192 responseObserver.onCompleted(); 193 } 194 195 @Override writeEncrypted( KeysetWriteEncryptedRequest request, StreamObserver<KeysetWriteEncryptedResponse> responseObserver)196 public void writeEncrypted( 197 KeysetWriteEncryptedRequest request, 198 StreamObserver<KeysetWriteEncryptedResponse> responseObserver) { 199 KeysetWriteEncryptedResponse response; 200 try { 201 // get masterAead 202 KeysetHandle masterKeysetHandle = 203 TinkProtoKeysetFormat.parseKeyset( 204 request.getMasterKeyset().toByteArray(), InsecureSecretKeyAccess.get()); 205 Aead masterAead = masterKeysetHandle.getPrimitive(Aead.class); 206 207 // get keysetHandle 208 KeysetHandle keysetHandle = 209 TinkProtoKeysetFormat.parseKeyset( 210 request.getKeyset().toByteArray(), InsecureSecretKeyAccess.get()); 211 212 // write keysetHandle as encrypted keyset 213 byte[] associatedData = request.getAssociatedData().getValue().toByteArray(); 214 byte[] keyset; 215 if (request.getKeysetWriterType() == KeysetWriterType.KEYSET_WRITER_BINARY) { 216 keyset = 217 TinkProtoKeysetFormat.serializeEncryptedKeyset( 218 keysetHandle, masterAead, associatedData); 219 } else if (request.getKeysetWriterType() == KeysetWriterType.KEYSET_WRITER_JSON) { 220 keyset = 221 TinkJsonProtoKeysetFormat.serializeEncryptedKeyset( 222 keysetHandle, masterAead, associatedData) 223 .getBytes(UTF_8); 224 } else { 225 throw new IllegalArgumentException("unknown keyset writer type"); 226 } 227 response = 228 KeysetWriteEncryptedResponse.newBuilder() 229 .setEncryptedKeyset(ByteString.copyFrom(keyset)) 230 .build(); 231 } catch (GeneralSecurityException e) { 232 response = KeysetWriteEncryptedResponse.newBuilder().setErr(e.toString()).build(); 233 } 234 responseObserver.onNext(response); 235 responseObserver.onCompleted(); 236 } 237 } 238