xref: /aosp_15_r20/external/tink/go/keyset/json_io_test.go (revision e7b1675dde1b92d52ec075b0a92829627f2c52a5)
1*e7b1675dSTing-Kang Chang// Copyright 2019 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 keyset_test
18*e7b1675dSTing-Kang Chang
19*e7b1675dSTing-Kang Changimport (
20*e7b1675dSTing-Kang Chang	"bytes"
21*e7b1675dSTing-Kang Chang	"encoding/base64"
22*e7b1675dSTing-Kang Chang	"fmt"
23*e7b1675dSTing-Kang Chang	"strings"
24*e7b1675dSTing-Kang Chang	"testing"
25*e7b1675dSTing-Kang Chang
26*e7b1675dSTing-Kang Chang	"google.golang.org/protobuf/proto"
27*e7b1675dSTing-Kang Chang	"github.com/google/tink/go/keyset"
28*e7b1675dSTing-Kang Chang	"github.com/google/tink/go/testkeyset"
29*e7b1675dSTing-Kang Chang	"github.com/google/tink/go/testutil"
30*e7b1675dSTing-Kang Chang
31*e7b1675dSTing-Kang Chang	commonpb "github.com/google/tink/go/proto/common_go_proto"
32*e7b1675dSTing-Kang Chang	tinkpb "github.com/google/tink/go/proto/tink_go_proto"
33*e7b1675dSTing-Kang Chang)
34*e7b1675dSTing-Kang Chang
35*e7b1675dSTing-Kang Changfunc TestJSONIOUnencrypted(t *testing.T) {
36*e7b1675dSTing-Kang Chang	buf := new(bytes.Buffer)
37*e7b1675dSTing-Kang Chang	w := keyset.NewJSONWriter(buf)
38*e7b1675dSTing-Kang Chang	r := keyset.NewJSONReader(buf)
39*e7b1675dSTing-Kang Chang
40*e7b1675dSTing-Kang Chang	manager := testutil.NewHMACKeysetManager()
41*e7b1675dSTing-Kang Chang	h, err := manager.Handle()
42*e7b1675dSTing-Kang Chang	if h == nil || err != nil {
43*e7b1675dSTing-Kang Chang		t.Fatalf("cannot get keyset handle: %v", err)
44*e7b1675dSTing-Kang Chang	}
45*e7b1675dSTing-Kang Chang
46*e7b1675dSTing-Kang Chang	ks1 := testkeyset.KeysetMaterial(h)
47*e7b1675dSTing-Kang Chang	if err := w.Write(ks1); err != nil {
48*e7b1675dSTing-Kang Chang		t.Fatalf("cannot write keyset: %v", err)
49*e7b1675dSTing-Kang Chang	}
50*e7b1675dSTing-Kang Chang
51*e7b1675dSTing-Kang Chang	ks2, err := r.Read()
52*e7b1675dSTing-Kang Chang	if err != nil {
53*e7b1675dSTing-Kang Chang		t.Fatalf("cannot read keyset: %v", err)
54*e7b1675dSTing-Kang Chang	}
55*e7b1675dSTing-Kang Chang
56*e7b1675dSTing-Kang Chang	if !proto.Equal(ks1, ks2) {
57*e7b1675dSTing-Kang Chang		t.Errorf("written keyset (%s) doesn't match read keyset (%s)", ks1, ks2)
58*e7b1675dSTing-Kang Chang	}
59*e7b1675dSTing-Kang Chang}
60*e7b1675dSTing-Kang Chang
61*e7b1675dSTing-Kang Changfunc TestJSONReader(t *testing.T) {
62*e7b1675dSTing-Kang Chang	gcmkey := []byte(testutil.NewAESGCMKey(0, 16).String())
63*e7b1675dSTing-Kang Chang	eaxkey := []byte(testutil.NewHMACKey(commonpb.HashType_SHA512, 32).String())
64*e7b1675dSTing-Kang Chang	jsonKeyset := fmt.Sprintf(`{
65*e7b1675dSTing-Kang Chang         "primaryKeyId":42,
66*e7b1675dSTing-Kang Chang         "key":[
67*e7b1675dSTing-Kang Chang            {
68*e7b1675dSTing-Kang Chang               "keyData":{
69*e7b1675dSTing-Kang Chang                  "typeUrl":"type.googleapis.com/google.crypto.tink.AesGcmKey",
70*e7b1675dSTing-Kang Chang                  "keyMaterialType":"SYMMETRIC",
71*e7b1675dSTing-Kang Chang                  "value": %q
72*e7b1675dSTing-Kang Chang               },
73*e7b1675dSTing-Kang Chang               "outputPrefixType":"TINK",
74*e7b1675dSTing-Kang Chang               "keyId":42,
75*e7b1675dSTing-Kang Chang               "status":"ENABLED"
76*e7b1675dSTing-Kang Chang            },
77*e7b1675dSTing-Kang Chang            {
78*e7b1675dSTing-Kang Chang               "keyData":{
79*e7b1675dSTing-Kang Chang                  "typeUrl":"type.googleapis.com/google.crypto.tink.AesEaxKey",
80*e7b1675dSTing-Kang Chang                  "keyMaterialType":"SYMMETRIC",
81*e7b1675dSTing-Kang Chang                  "value": %q
82*e7b1675dSTing-Kang Chang               },
83*e7b1675dSTing-Kang Chang               "outputPrefixType":"RAW",
84*e7b1675dSTing-Kang Chang               "keyId":711,
85*e7b1675dSTing-Kang Chang               "status":"ENABLED"
86*e7b1675dSTing-Kang Chang            }
87*e7b1675dSTing-Kang Chang         ]
88*e7b1675dSTing-Kang Chang      }`, base64.StdEncoding.EncodeToString([]byte(gcmkey)), base64.StdEncoding.EncodeToString([]byte(eaxkey)))
89*e7b1675dSTing-Kang Chang	r := keyset.NewJSONReader(bytes.NewBufferString(jsonKeyset))
90*e7b1675dSTing-Kang Chang
91*e7b1675dSTing-Kang Chang	got, err := r.Read()
92*e7b1675dSTing-Kang Chang	if err != nil {
93*e7b1675dSTing-Kang Chang		t.Fatalf("cannot read keyset: %v", err)
94*e7b1675dSTing-Kang Chang	}
95*e7b1675dSTing-Kang Chang
96*e7b1675dSTing-Kang Chang	want := &tinkpb.Keyset{
97*e7b1675dSTing-Kang Chang		PrimaryKeyId: 42,
98*e7b1675dSTing-Kang Chang		Key: []*tinkpb.Keyset_Key{
99*e7b1675dSTing-Kang Chang			{
100*e7b1675dSTing-Kang Chang				KeyData: &tinkpb.KeyData{
101*e7b1675dSTing-Kang Chang					TypeUrl:         "type.googleapis.com/google.crypto.tink.AesGcmKey",
102*e7b1675dSTing-Kang Chang					KeyMaterialType: tinkpb.KeyData_SYMMETRIC,
103*e7b1675dSTing-Kang Chang					Value:           gcmkey,
104*e7b1675dSTing-Kang Chang				},
105*e7b1675dSTing-Kang Chang				OutputPrefixType: tinkpb.OutputPrefixType_TINK,
106*e7b1675dSTing-Kang Chang				KeyId:            42,
107*e7b1675dSTing-Kang Chang				Status:           tinkpb.KeyStatusType_ENABLED,
108*e7b1675dSTing-Kang Chang			},
109*e7b1675dSTing-Kang Chang			{
110*e7b1675dSTing-Kang Chang				KeyData: &tinkpb.KeyData{
111*e7b1675dSTing-Kang Chang					TypeUrl:         "type.googleapis.com/google.crypto.tink.AesEaxKey",
112*e7b1675dSTing-Kang Chang					KeyMaterialType: tinkpb.KeyData_SYMMETRIC,
113*e7b1675dSTing-Kang Chang					Value:           eaxkey,
114*e7b1675dSTing-Kang Chang				},
115*e7b1675dSTing-Kang Chang				OutputPrefixType: tinkpb.OutputPrefixType_RAW,
116*e7b1675dSTing-Kang Chang				KeyId:            711,
117*e7b1675dSTing-Kang Chang				Status:           tinkpb.KeyStatusType_ENABLED,
118*e7b1675dSTing-Kang Chang			},
119*e7b1675dSTing-Kang Chang		},
120*e7b1675dSTing-Kang Chang	}
121*e7b1675dSTing-Kang Chang
122*e7b1675dSTing-Kang Chang	if !proto.Equal(got, want) {
123*e7b1675dSTing-Kang Chang		t.Errorf("written keyset %q doesn't match expected keyset %q", got, want)
124*e7b1675dSTing-Kang Chang	}
125*e7b1675dSTing-Kang Chang}
126*e7b1675dSTing-Kang Chang
127*e7b1675dSTing-Kang Changfunc TestJSONReaderLargeIds(t *testing.T) {
128*e7b1675dSTing-Kang Chang	gcmkey := []byte(testutil.NewAESGCMKey(0, 16).String())
129*e7b1675dSTing-Kang Chang	jsonKeyset := fmt.Sprintf(`{
130*e7b1675dSTing-Kang Chang         "primaryKeyId":4294967275,
131*e7b1675dSTing-Kang Chang         "key":[
132*e7b1675dSTing-Kang Chang            {
133*e7b1675dSTing-Kang Chang               "keyData":{
134*e7b1675dSTing-Kang Chang                  "typeUrl":"type.googleapis.com/google.crypto.tink.AesGcmKey",
135*e7b1675dSTing-Kang Chang                  "keyMaterialType":"SYMMETRIC",
136*e7b1675dSTing-Kang Chang                  "value": %q
137*e7b1675dSTing-Kang Chang               },
138*e7b1675dSTing-Kang Chang               "outputPrefixType":"TINK",
139*e7b1675dSTing-Kang Chang               "keyId":4294967275,
140*e7b1675dSTing-Kang Chang               "status":"ENABLED"
141*e7b1675dSTing-Kang Chang            }
142*e7b1675dSTing-Kang Chang         ]
143*e7b1675dSTing-Kang Chang      }`, base64.StdEncoding.EncodeToString([]byte(gcmkey)))
144*e7b1675dSTing-Kang Chang	r := keyset.NewJSONReader(bytes.NewBufferString(jsonKeyset))
145*e7b1675dSTing-Kang Chang
146*e7b1675dSTing-Kang Chang	got, err := r.Read()
147*e7b1675dSTing-Kang Chang	if err != nil {
148*e7b1675dSTing-Kang Chang		t.Fatalf("cannot read keyset: %v", err)
149*e7b1675dSTing-Kang Chang	}
150*e7b1675dSTing-Kang Chang
151*e7b1675dSTing-Kang Chang	want := &tinkpb.Keyset{
152*e7b1675dSTing-Kang Chang		PrimaryKeyId: 4294967275,
153*e7b1675dSTing-Kang Chang		Key: []*tinkpb.Keyset_Key{
154*e7b1675dSTing-Kang Chang			{
155*e7b1675dSTing-Kang Chang				KeyData: &tinkpb.KeyData{
156*e7b1675dSTing-Kang Chang					TypeUrl:         "type.googleapis.com/google.crypto.tink.AesGcmKey",
157*e7b1675dSTing-Kang Chang					KeyMaterialType: tinkpb.KeyData_SYMMETRIC,
158*e7b1675dSTing-Kang Chang					Value:           gcmkey,
159*e7b1675dSTing-Kang Chang				},
160*e7b1675dSTing-Kang Chang				OutputPrefixType: tinkpb.OutputPrefixType_TINK,
161*e7b1675dSTing-Kang Chang				KeyId:            4294967275,
162*e7b1675dSTing-Kang Chang				Status:           tinkpb.KeyStatusType_ENABLED,
163*e7b1675dSTing-Kang Chang			},
164*e7b1675dSTing-Kang Chang		},
165*e7b1675dSTing-Kang Chang	}
166*e7b1675dSTing-Kang Chang
167*e7b1675dSTing-Kang Chang	if !proto.Equal(got, want) {
168*e7b1675dSTing-Kang Chang		t.Errorf("written keyset %q doesn't match expected keyset %q", got, want)
169*e7b1675dSTing-Kang Chang	}
170*e7b1675dSTing-Kang Chang}
171*e7b1675dSTing-Kang Chang
172*e7b1675dSTing-Kang Changfunc TestJSONReaderRejectsNegativeKeyIds(t *testing.T) {
173*e7b1675dSTing-Kang Chang	gcmkey := []byte(testutil.NewAESGCMKey(0, 16).String())
174*e7b1675dSTing-Kang Chang	jsonKeyset := fmt.Sprintf(`{
175*e7b1675dSTing-Kang Chang         "primaryKeyId": -10,
176*e7b1675dSTing-Kang Chang         "key":[
177*e7b1675dSTing-Kang Chang            {
178*e7b1675dSTing-Kang Chang               "keyData":{
179*e7b1675dSTing-Kang Chang                  "typeUrl":"type.googleapis.com/google.crypto.tink.AesGcmKey",
180*e7b1675dSTing-Kang Chang                  "keyMaterialType":"SYMMETRIC",
181*e7b1675dSTing-Kang Chang                  "value": %q
182*e7b1675dSTing-Kang Chang               },
183*e7b1675dSTing-Kang Chang               "outputPrefixType":"TINK",
184*e7b1675dSTing-Kang Chang               "keyId": -10,
185*e7b1675dSTing-Kang Chang               "status":"ENABLED"
186*e7b1675dSTing-Kang Chang            }
187*e7b1675dSTing-Kang Chang         ]
188*e7b1675dSTing-Kang Chang      }`, base64.StdEncoding.EncodeToString(gcmkey))
189*e7b1675dSTing-Kang Chang	r := keyset.NewJSONReader(bytes.NewBufferString(jsonKeyset))
190*e7b1675dSTing-Kang Chang
191*e7b1675dSTing-Kang Chang	_, err := r.Read()
192*e7b1675dSTing-Kang Chang	if err == nil {
193*e7b1675dSTing-Kang Chang		t.Fatalf("Expected failure due to negative key id")
194*e7b1675dSTing-Kang Chang	}
195*e7b1675dSTing-Kang Chang}
196*e7b1675dSTing-Kang Chang
197*e7b1675dSTing-Kang Changfunc TestJSONReaderRejectsKeyIdLargerThanUint32(t *testing.T) {
198*e7b1675dSTing-Kang Chang	// 4294967296 = 2^32, which is too large for uint32.
199*e7b1675dSTing-Kang Chang	gcmkey := []byte(testutil.NewAESGCMKey(0, 16).String())
200*e7b1675dSTing-Kang Chang	jsonKeyset := fmt.Sprintf(`{
201*e7b1675dSTing-Kang Chang         "primaryKeyId": 4294967296,
202*e7b1675dSTing-Kang Chang         "key":[
203*e7b1675dSTing-Kang Chang            {
204*e7b1675dSTing-Kang Chang               "keyData":{
205*e7b1675dSTing-Kang Chang                  "typeUrl":"type.googleapis.com/google.crypto.tink.AesGcmKey",
206*e7b1675dSTing-Kang Chang                  "keyMaterialType":"SYMMETRIC",
207*e7b1675dSTing-Kang Chang                  "value": %q
208*e7b1675dSTing-Kang Chang               },
209*e7b1675dSTing-Kang Chang               "outputPrefixType":"TINK",
210*e7b1675dSTing-Kang Chang               "keyId": 4294967296,
211*e7b1675dSTing-Kang Chang               "status":"ENABLED"
212*e7b1675dSTing-Kang Chang            }
213*e7b1675dSTing-Kang Chang         ]
214*e7b1675dSTing-Kang Chang      }`, base64.StdEncoding.EncodeToString(gcmkey))
215*e7b1675dSTing-Kang Chang	r := keyset.NewJSONReader(bytes.NewBufferString(jsonKeyset))
216*e7b1675dSTing-Kang Chang
217*e7b1675dSTing-Kang Chang	_, err := r.Read()
218*e7b1675dSTing-Kang Chang	if err == nil {
219*e7b1675dSTing-Kang Chang		t.Fatalf("Expected failure due to negative key id")
220*e7b1675dSTing-Kang Chang	}
221*e7b1675dSTing-Kang Chang}
222*e7b1675dSTing-Kang Chang
223*e7b1675dSTing-Kang Chang// Tests that large IDs (>2^31) are written correctly.
224*e7b1675dSTing-Kang Changfunc TestJSONWriterLargeId(t *testing.T) {
225*e7b1675dSTing-Kang Chang	eaxkey := []byte(testutil.NewHMACKey(commonpb.HashType_SHA512, 32).String())
226*e7b1675dSTing-Kang Chang
227*e7b1675dSTing-Kang Chang	ks := tinkpb.Keyset{
228*e7b1675dSTing-Kang Chang		PrimaryKeyId: 4294967275,
229*e7b1675dSTing-Kang Chang		Key: []*tinkpb.Keyset_Key{
230*e7b1675dSTing-Kang Chang			{
231*e7b1675dSTing-Kang Chang				KeyData: &tinkpb.KeyData{
232*e7b1675dSTing-Kang Chang					TypeUrl:         "type.googleapis.com/google.crypto.tink.AesEaxKey",
233*e7b1675dSTing-Kang Chang					KeyMaterialType: tinkpb.KeyData_SYMMETRIC,
234*e7b1675dSTing-Kang Chang					Value:           eaxkey,
235*e7b1675dSTing-Kang Chang				},
236*e7b1675dSTing-Kang Chang				OutputPrefixType: tinkpb.OutputPrefixType_RAW,
237*e7b1675dSTing-Kang Chang				KeyId:            4294967275,
238*e7b1675dSTing-Kang Chang				Status:           tinkpb.KeyStatusType_ENABLED,
239*e7b1675dSTing-Kang Chang			},
240*e7b1675dSTing-Kang Chang		},
241*e7b1675dSTing-Kang Chang	}
242*e7b1675dSTing-Kang Chang
243*e7b1675dSTing-Kang Chang	buf := new(bytes.Buffer)
244*e7b1675dSTing-Kang Chang	w := keyset.NewJSONWriter(buf)
245*e7b1675dSTing-Kang Chang	if err := w.Write(&ks); err != nil {
246*e7b1675dSTing-Kang Chang		t.Fatalf("cannot write keyset: %v", err)
247*e7b1675dSTing-Kang Chang	}
248*e7b1675dSTing-Kang Chang
249*e7b1675dSTing-Kang Chang	if !strings.Contains(buf.String(), `"keyId":4294967275`) {
250*e7b1675dSTing-Kang Chang		t.Errorf("written keyset %q does not contain a key with keyId 4294967275", buf.Bytes())
251*e7b1675dSTing-Kang Chang	}
252*e7b1675dSTing-Kang Chang	if !strings.Contains(buf.String(), "\"primaryKeyId\":4294967275") {
253*e7b1675dSTing-Kang Chang		t.Errorf("written keyset %q does not contain have primaryKeyId 4294967275", buf.Bytes())
254*e7b1675dSTing-Kang Chang	}
255*e7b1675dSTing-Kang Chang}
256*e7b1675dSTing-Kang Chang
257*e7b1675dSTing-Kang Changfunc TestJSONIOEncrypted(t *testing.T) {
258*e7b1675dSTing-Kang Chang	buf := new(bytes.Buffer)
259*e7b1675dSTing-Kang Chang	w := keyset.NewJSONWriter(buf)
260*e7b1675dSTing-Kang Chang	r := keyset.NewJSONReader(buf)
261*e7b1675dSTing-Kang Chang
262*e7b1675dSTing-Kang Chang	kse1 := &tinkpb.EncryptedKeyset{EncryptedKeyset: []byte(strings.Repeat("A", 32))}
263*e7b1675dSTing-Kang Chang
264*e7b1675dSTing-Kang Chang	if err := w.WriteEncrypted(kse1); err != nil {
265*e7b1675dSTing-Kang Chang		t.Fatalf("cannot write encrypted keyset: %v", err)
266*e7b1675dSTing-Kang Chang	}
267*e7b1675dSTing-Kang Chang
268*e7b1675dSTing-Kang Chang	kse2, err := r.ReadEncrypted()
269*e7b1675dSTing-Kang Chang	if err != nil {
270*e7b1675dSTing-Kang Chang		t.Fatalf("cannot read encryped keyset: %v", err)
271*e7b1675dSTing-Kang Chang	}
272*e7b1675dSTing-Kang Chang
273*e7b1675dSTing-Kang Chang	if !proto.Equal(kse1, kse2) {
274*e7b1675dSTing-Kang Chang		t.Errorf("written encryped keyset %q doesn't match read encryped keyset %q", kse1, kse2)
275*e7b1675dSTing-Kang Chang	}
276*e7b1675dSTing-Kang Chang}
277