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 hybrid_test 18*e7b1675dSTing-Kang Chang 19*e7b1675dSTing-Kang Chang// [START hybrid-example] 20*e7b1675dSTing-Kang Chang 21*e7b1675dSTing-Kang Changimport ( 22*e7b1675dSTing-Kang Chang "bytes" 23*e7b1675dSTing-Kang Chang "fmt" 24*e7b1675dSTing-Kang Chang "log" 25*e7b1675dSTing-Kang Chang 26*e7b1675dSTing-Kang Chang "github.com/google/tink/go/hybrid" 27*e7b1675dSTing-Kang Chang "github.com/google/tink/go/insecurecleartextkeyset" 28*e7b1675dSTing-Kang Chang "github.com/google/tink/go/keyset" 29*e7b1675dSTing-Kang Chang) 30*e7b1675dSTing-Kang Chang 31*e7b1675dSTing-Kang Changfunc Example() { 32*e7b1675dSTing-Kang Chang // A private keyset created with 33*e7b1675dSTing-Kang Chang // "tinkey create-keyset --key-template=DHKEM_X25519_HKDF_SHA256_HKDF_SHA256_AES_256_GCM --out private_keyset.cfg". 34*e7b1675dSTing-Kang Chang // Note that this keyset has the secret key information in cleartext. 35*e7b1675dSTing-Kang Chang privateJSONKeyset := `{ 36*e7b1675dSTing-Kang Chang "key": [{ 37*e7b1675dSTing-Kang Chang "keyData": { 38*e7b1675dSTing-Kang Chang "keyMaterialType": 39*e7b1675dSTing-Kang Chang "ASYMMETRIC_PRIVATE", 40*e7b1675dSTing-Kang Chang "typeUrl": 41*e7b1675dSTing-Kang Chang "type.googleapis.com/google.crypto.tink.HpkePrivateKey", 42*e7b1675dSTing-Kang Chang "value": 43*e7b1675dSTing-Kang Chang "EioSBggBEAEYAhogVWQpmQoz74jcAp5WOD36KiBQ71MVCpn2iWfOzWLtKV4aINfn8qlMbyijNJcCzrafjsgJ493ZZGN256KTfKw0WN+p" 44*e7b1675dSTing-Kang Chang }, 45*e7b1675dSTing-Kang Chang "keyId": 958452012, 46*e7b1675dSTing-Kang Chang "outputPrefixType": "TINK", 47*e7b1675dSTing-Kang Chang "status": "ENABLED" 48*e7b1675dSTing-Kang Chang }], 49*e7b1675dSTing-Kang Chang "primaryKeyId": 958452012 50*e7b1675dSTing-Kang Chang }` 51*e7b1675dSTing-Kang Chang 52*e7b1675dSTing-Kang Chang // The corresponding public keyset created with 53*e7b1675dSTing-Kang Chang // "tinkey create-public-keyset --in private_keyset.cfg". 54*e7b1675dSTing-Kang Chang publicJSONKeyset := `{ 55*e7b1675dSTing-Kang Chang "key": [{ 56*e7b1675dSTing-Kang Chang "keyData": { 57*e7b1675dSTing-Kang Chang "keyMaterialType": 58*e7b1675dSTing-Kang Chang "ASYMMETRIC_PUBLIC", 59*e7b1675dSTing-Kang Chang "typeUrl": 60*e7b1675dSTing-Kang Chang "type.googleapis.com/google.crypto.tink.HpkePublicKey", 61*e7b1675dSTing-Kang Chang "value": 62*e7b1675dSTing-Kang Chang "EgYIARABGAIaIFVkKZkKM++I3AKeVjg9+iogUO9TFQqZ9olnzs1i7Sle" 63*e7b1675dSTing-Kang Chang }, 64*e7b1675dSTing-Kang Chang "keyId": 958452012, 65*e7b1675dSTing-Kang Chang "outputPrefixType": "TINK", 66*e7b1675dSTing-Kang Chang "status": "ENABLED" 67*e7b1675dSTing-Kang Chang }], 68*e7b1675dSTing-Kang Chang "primaryKeyId": 958452012 69*e7b1675dSTing-Kang Chang }` 70*e7b1675dSTing-Kang Chang 71*e7b1675dSTing-Kang Chang // Create a keyset handle from the keyset containing the public key. Because the 72*e7b1675dSTing-Kang Chang // public keyset does not contain any secrets, we can use [keyset.ReadWithNoSecrets]. 73*e7b1675dSTing-Kang Chang publicKeysetHandle, err := keyset.ReadWithNoSecrets( 74*e7b1675dSTing-Kang Chang keyset.NewJSONReader(bytes.NewBufferString(publicJSONKeyset))) 75*e7b1675dSTing-Kang Chang if err != nil { 76*e7b1675dSTing-Kang Chang log.Fatal(err) 77*e7b1675dSTing-Kang Chang } 78*e7b1675dSTing-Kang Chang 79*e7b1675dSTing-Kang Chang // Retrieve the HybridEncrypt primitive from publicKeysetHandle. 80*e7b1675dSTing-Kang Chang encPrimitive, err := hybrid.NewHybridEncrypt(publicKeysetHandle) 81*e7b1675dSTing-Kang Chang if err != nil { 82*e7b1675dSTing-Kang Chang log.Fatal(err) 83*e7b1675dSTing-Kang Chang } 84*e7b1675dSTing-Kang Chang 85*e7b1675dSTing-Kang Chang plaintext := []byte("message") 86*e7b1675dSTing-Kang Chang encryptionContext := []byte("encryption context") 87*e7b1675dSTing-Kang Chang ciphertext, err := encPrimitive.Encrypt(plaintext, encryptionContext) 88*e7b1675dSTing-Kang Chang if err != nil { 89*e7b1675dSTing-Kang Chang log.Fatal(err) 90*e7b1675dSTing-Kang Chang } 91*e7b1675dSTing-Kang Chang 92*e7b1675dSTing-Kang Chang // Create a keyset handle from the cleartext private keyset in the previous 93*e7b1675dSTing-Kang Chang // step. The keyset handle provides abstract access to the underlying keyset to 94*e7b1675dSTing-Kang Chang // limit the access of the raw key material. WARNING: In practice, 95*e7b1675dSTing-Kang Chang // it is unlikely you will want to use a insecurecleartextkeyset, as it implies 96*e7b1675dSTing-Kang Chang // that your key material is passed in cleartext, which is a security risk. 97*e7b1675dSTing-Kang Chang // Consider encrypting it with a remote key in Cloud KMS, AWS KMS or HashiCorp Vault. 98*e7b1675dSTing-Kang Chang // See https://github.com/google/tink/blob/master/docs/GOLANG-HOWTO.md#storing-and-loading-existing-keysets. 99*e7b1675dSTing-Kang Chang privateKeysetHandle, err := insecurecleartextkeyset.Read( 100*e7b1675dSTing-Kang Chang keyset.NewJSONReader(bytes.NewBufferString(privateJSONKeyset))) 101*e7b1675dSTing-Kang Chang if err != nil { 102*e7b1675dSTing-Kang Chang log.Fatal(err) 103*e7b1675dSTing-Kang Chang } 104*e7b1675dSTing-Kang Chang 105*e7b1675dSTing-Kang Chang // Retrieve the HybridDecrypt primitive from privateKeysetHandle. 106*e7b1675dSTing-Kang Chang decPrimitive, err := hybrid.NewHybridDecrypt(privateKeysetHandle) 107*e7b1675dSTing-Kang Chang if err != nil { 108*e7b1675dSTing-Kang Chang log.Fatal(err) 109*e7b1675dSTing-Kang Chang } 110*e7b1675dSTing-Kang Chang 111*e7b1675dSTing-Kang Chang decrypted, err := decPrimitive.Decrypt(ciphertext, encryptionContext) 112*e7b1675dSTing-Kang Chang if err != nil { 113*e7b1675dSTing-Kang Chang log.Fatal(err) 114*e7b1675dSTing-Kang Chang } 115*e7b1675dSTing-Kang Chang 116*e7b1675dSTing-Kang Chang fmt.Println(string(decrypted)) 117*e7b1675dSTing-Kang Chang // Output: message 118*e7b1675dSTing-Kang Chang} 119*e7b1675dSTing-Kang Chang// [END hybrid-example] 120