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