1// Copyright 2015 Keybase, Inc. All rights reserved. Use of
2// this source code is governed by the included BSD license.
3
4package libkb
5
6import (
7	"crypto/sha256"
8	"encoding/base64"
9	"fmt"
10	"strconv"
11
12	"github.com/buger/jsonparser"
13	"github.com/keybase/client/go/jsonparserw"
14	"github.com/keybase/client/go/kbcrypto"
15	"github.com/keybase/client/go/msgpack"
16	"github.com/keybase/client/go/sigid"
17	pkgerrors "github.com/pkg/errors"
18
19	keybase1 "github.com/keybase/client/go/protocol/keybase1"
20)
21
22// badWhitespaceLinkIDConversion converts what we get by naively computing
23// the LinkID to what it should be (on the basis of a mistakenly stripped newline).
24var badWhitespaceLinkIDConversion = map[keybase1.LinkID]keybase1.LinkID{
25	"c6403b7eec2f2ada4f5e0349bd59488c6fc6a8ff62f7e4a9b559f3e672690f23": "03fb1e2c0e61e3715c41515045d89d2f788dbcc7eb671b94ac12ee5f805bbe70",
26	"67f63579dcb143cde80af2196037e61b8d5410677939c3635fbf44e34e106d6e": "09527db7672bf23a9681ac86c70826cdc01ed1e467252a76ca4bf4ad0964efd7",
27	"0adfc5a682a1f717469ce5781f03110ea47aad62a65fba5c9db6c93ffd1d31ef": "12c9203c98fe0b1c80a551f8933b2c870fcc3754a8ea05591e43a4d528fadc68",
28	"b068f86b9a6b12b45c4a727e2b2506900d84107a66331dadc50e9127eec1df11": "14ef90159164e19228ff21c909b764e239f27f0fff49f86414a2dde9b719845f",
29	"179ba2604ca94bd3c049fd37bc60fdf7b6f5aa331ec5432b6ce8fb5e30a76c80": "18688c45cbe05ee2b72567acc696b3856f9876dff0ec3ea927ad7632a3f48fe6",
30	"781db37c7eec976551e0c5d06a1fc64c84c06c601c093f71661892776335a360": "2c11a140d8f231af6d69543474138a503191486ae6b5739892c5e0c6c0c4c348",
31	"5f6f398fed407020498d5258183ac5cf09b96832a57c19b412b4a5a186a8ddae": "2cf8b9ffa500089b6db873acbabdba771e8e897c0a899a01f8967a7280cfd0da",
32	"2ea16dd1ed2339cc193e8e4d36f3b12955276b9bd02d00c0ccac19a865fedb8a": "2efe839231d6b03f85ab3c542e870e7062329a8c5e384f1289b00be7c7afb8ab",
33	"fc6febd300f012a8796bc29b7f9f119736fbece786b5bf41535debb4c4065e18": "32f5dd2643eabf3828f7f03ccded07d8d8a29e352df6130c3a4232104398d819",
34	"908df90fcdc82b13689c3826fec2b113d0f5ea95ab12dfccac0c8017e051523a": "33a61f19c0ca52257214f97524ef10441cf85215ff171868f53561dfd7b14c81",
35	"f025714a5b92f29ece12c5d3dfa3f1cff430d00375381ce3d3029f57cb6fbe87": "36328ab1cf15cc3dd2ba4c771ca1066b2d44714780ad8e83894611e2a2642003",
36	"3f59f95a6027faad6cd7d0ecdd087824cad743af8c460b24d8c3dd3e73fdc564": "371f9ae63d56ec853fa53941e79d29abbb4cd11aa926715d354d18d687b0ca71",
37	"8629ef8148542ba40ab650de522a08f7fcba12e1c4dd9cae702054ddd1db3469": "374f1da46fd8238ab9f288183cb78f3c6a59732f4b19705763c9d6ac356015ef",
38	"a05c5533c3a0be260c2c61d3e026c7f0ed9f050cf7fb1b3375561e9b74900f39": "3803be27ec0c61b3fdcd8b9b7c78de3df73766736ef00727267858d34a039c7d",
39	"ca574ddc1f5b1d8cfcea4c98cbf9318aa7730654fc27f155194a0331743018f2": "3ca5ef6a6115a8a86d7d94cb3565f43f05f7975d66015455dd6cc32b73936177",
40	"c342332cd2e16bef3fcd3c179b4c68e1711966a42d2f761a8cad1d9018b6e50c": "3cdd165df44ba7f8331b89213f213dab36482ef513d023c5d2b0f6bfd11d5678",
41	"2c7d63521953099c4dd1eeaecaf73ea7141358d861804581afabdb41fbc4c6dd": "43f21601ffaeae70eca2f585949f42c67e85e93cf2a6847d6c20ffd81a9ff890",
42	"608a930cd23b8326c6c54c333a3b06c5a7817e6dd0776931600d0232c9b64415": "4948115615d7dceb90bcdd818f69b66b5899339a2b747b5e6dc0f6987abbcbd0",
43	"5b01b5f4868b1a57c17dfd7e0a29e814c2ebf517124d3fc9e80de91a14f36853": "4c3f7855eb307aa5620962e15de84b2cfe3f728a9722c43906b12e0f3082cb87",
44	"e155732239cdfbc7e8f984724048ea55837f1dc2e296103f3b8b5b920e1d06a0": "5957f583bec18cc6f381355843c21f903fe47d584a9816e072f3f102f1f488be",
45	"19fb5089a2c976a3da70313509853967ddc9e7aca66bbd83b692ec6c25f42ad0": "605525686fef18180be692df6106c13dae39abb2799dc9e8bed1e2bb64e9b886",
46	"9cc3b515ef372c4dab04f634ae781eab44dc3c905b2e50eeb491cde73e6abc76": "616d9710b3a594ab00292d3d414e6e141929935a133bfa9a25ec4a155a403e5c",
47	"35567057358f9a9907f8ac53195c32a9c8297c244420f77f34973ea9aa0c99bf": "61e9f4b437fccac8abd396acfc96b17558c9c355b57f4a5f2f3698e78f19532f",
48	"992232ad3e598cad26dc8247a59ae00026c710aad8d4d0aa30c8b22c30c41068": "6f3d73ddf575f2033a48268a564575e40edbb5111cc057984f51f463d4e8ed58",
49	"2b999c0c8a6d7580fe15cad0718555d1ad4dbe7ee66fbdf064e50314e63908b0": "720b80b7c15cb9a3d21a2eec228bceb5db6f0ef54df2d0aef08aec5ed1632257",
50	"070a137418bf79584da4806d342cb85da195b81ba34ab17866301e0074a62106": "740f9140a7901defaaaec10042722b30d2fee457337b7ae8e9de3b9fc05d109f",
51	"9fe6d8d33743b1c115386f6e0640b1a1a20b78f5abd33068a122eee76b0ac1fa": "7560f896c19457365225f48be0217b8a00519f1daccefee4c097dd1b4594dd66",
52	"0a66d169b9735d3d6017bebb3c6663651d0e7945b7807da7fc0f81cd89a1bab4": "7772c99774570202a2c5ac017eefc8296f613e64c8d4adff4ba7991b553431f5",
53	"c76aed537f11f43d9f29960e64ac3826d8b588db523ecdc5d3962f370a603e91": "7d97355e5917c5bcc14ba3a1994398b3fa36416768b663c1454069de84a4fca2",
54	"f34d8e9cb975c2ff1695a62f6382705a9c8495d418fdf31b8e07ea8838726fbc": "893567013c77f45755279bf1138fecbb54cd3a55bf5814504cf0406acbe4bfeb",
55	"7a5c2c7535131175c8881f7d22425f9ceb7ac2a9c9a1bd4a1f3002f257130fbc": "8d7c1a0c99186f972afc5d3624aca2f88ddc3a5dbf84e826ef0b520c31a78aa3",
56	"9567542c190ccece597d9fd75a376406dde0c0a66dfece93bd458b7b8209001c": "94fde9d49c29cba59c949b35dd424de3a0daccf8a04ba443833e3328d495b9d8",
57	"6b4439bb3b4296fc3121e7254138da0112ee1f5d19060424a3795a52ba0118e1": "9644d4db6a4928ad1075a22b4473d1efa47c99a1a2a779450d4cd67d9115b9ba",
58	"49fdec5413bb7a31d12afd6d6d51449d51b0e294322b652dd5826d22b2240688": "9db59496652a1587ed56ec6ae15917b6d0ef4ac9a14dda97bfa4d2427a80e2b8",
59	"ccfa667ad9a1a392b51c719fcb5d526eee06e74e541d17e008b34ad8c0f2b2a6": "9f8c0a29a6ba3a521db2cd4d3e2ae15223dbcd5d5d1201e33ebb2dee1b61342f",
60	"1403ea660224a2ec5cd87c96f675cbb5d44535962c4b77c78e9711096579feec": "a9efa00bc479cb40ac0521749520f5a7a38a4ba4e698ee03355a85a8464b3840",
61	"c8890433c797440189f7dd99c8830d3524f4ed89cc5493380cbca463ef2f53bf": "ac3ecaa2aa1d638867026f0c54a1d895777f366d02bfef37403275aa0d4f8322",
62	"02e298aae0a3cefb14b53b9aa3c2757ddfd07f2b2bd70aca5d0fa1b23dd63818": "acf150b2d57a3aa65574bc2bb97e224413ce3f5344fd24fc7c3282da48cc2f3d",
63	"4b9d7cb38779b31acff69bb2426bbe7a3a5718e0b51f6197acf06f84fea30d67": "b23dfd34e58a814543e1f8368b9d07922abec213afca6d2b76722825794acffa",
64	"1cf025e248cca9ecd59936bb2c6a35f3842ca9a96bb264d2a53606476629266f": "b74b420f49b771ec04e656101f86c9729cf328b0fd32f5082d04d3c39f8ccea7",
65	"9c30bbd352353746885c0d0455c9482852f4cc824367a188d71650348847d1ad": "b9f188d0c6638e3bef3dfc3476c04078bb2aef2a9249cc77b6f009692967388a",
66	"3be37854d6b2585cab0b4371df454372b919fe688fb12bee28ccbce7c0de6375": "d380d18672da3c18f0804baf6b28f5efda76d64220a152c000f2b3f9af8b6603",
67	"9fb504227c9df7f10fe887c67038a4a9cd694a2b28ab8f5f47c23a86dce26a45": "d7ae76e4fdae7034b07e515d5684adcd51afea5a22b8520d2c61d31f5028fc6e",
68	"f74cf3b94f3896fa8a6413749072085c86544c4a51dd551128b39f57b0b43e63": "da99975f9ae8cdeb9e3a42a1166617dbf6afbcf841919dcf05145a73a7026cc2",
69	"e570d6a661985326582524f4b5d177fb2027847863cdc8d2c4a073c71f420e2d": "e449b1cd1d6f2a86a0f800c47e7d1ad26bbb6c76b983bd78154972c51f77e960",
70	"01932d6b39ab9a7ee0ca835ef4301adba0a2cd6da63fb07696153166d48fc075": "f1509495f4f1d46e43dcdd341156b975f7ad19aefeb250a80fd2b236c517a891",
71	"99668480e4731a47a81051e35d4957780395990d718d8629a8653ba718d489f2": "f5f324e91a94c073fdc936b50d56250133dc19415ae592d2c7cb99db9e980e1b",
72}
73
74func fixupSeqType(st *keybase1.SeqType) {
75	if *st == keybase1.SeqType_NONE {
76		*st = keybase1.SeqType_PUBLIC
77	}
78}
79
80func importLinkFromServerV2Stubbed(m MetaContext, parent *SigChain, raw string) (ret *ChainLink, err error) {
81	ol, err := DecodeStubbedOuterLinkV2(raw)
82	if err != nil {
83		return nil, err
84	}
85
86	fixupSeqType(&ol.SeqType)
87
88	if !ol.IgnoreIfUnsupported.Bool() && !ol.LinkType.IsSupportedType() {
89		return nil, ChainLinkStubbedUnsupportedError{fmt.Sprintf("Stubbed link with type %d is unknown and not marked with IgnoreIfUnsupported", ol.LinkType)}
90	}
91
92	linkID := ol.LinkID()
93
94	// Because the outer link does not have a highSkip parent object, we check
95	// for the nullity of highSkipSeqno to see if highSkip should be set, since
96	// a null highSkipHash is valid when specifying highSkip=0.
97	var highSkipPtr *HighSkip
98	if ol.HighSkipSeqno != nil {
99		highSkip := NewHighSkip(*ol.HighSkipSeqno, *ol.HighSkipHash)
100		highSkipPtr = &highSkip
101	}
102
103	unpacked := &ChainLinkUnpacked{
104		prev:                ol.Prev,
105		seqno:               ol.Seqno,
106		seqType:             ol.SeqType,
107		ignoreIfUnsupported: ol.IgnoreIfUnsupported,
108		highSkip:            highSkipPtr,
109		sigVersion:          ol.Version,
110		outerLinkV2:         ol,
111		stubbed:             true,
112	}
113	ret = NewChainLink(m.G(), parent, linkID)
114	ret.unpacked = unpacked
115	return ret, nil
116}
117
118type importRes struct {
119	kid     keybase1.KID
120	linkID  LinkID
121	sigID   keybase1.SigID
122	sig     string
123	payload []byte
124	ol2     *OuterLinkV2WithMetadata
125}
126
127func getPGPSig(m MetaContext, data []byte) (sig string) {
128	sig = jsonGetString(data, "sig")
129	if sig == "" || !IsPGPSig(sig) {
130		return ""
131	}
132	return sig
133}
134
135func jsonGetString(d []byte, args ...string) string {
136	s, err := jsonparserw.GetString(d, args...)
137	if err != nil {
138		return ""
139	}
140	return s
141
142}
143
144func importServerTrustFields(m MetaContext, tmp *ChainLinkUnpacked, data []byte, selfUID keybase1.UID) error {
145	if selfUID.Equal(tmp.uid) {
146		tmp.proofText = jsonGetString(data, "proof_text_full")
147	}
148
149	if i, err := jsonparserw.GetInt(data, "merkle_seqno"); err == nil {
150		tmp.firstAppearedMerkleSeqnoUnverified = keybase1.Seqno(i)
151	}
152	return nil
153}
154
155func ImportLinkFromServer(m MetaContext, parent *SigChain, data []byte, selfUID keybase1.UID) (ret *ChainLink, err error) {
156
157	sig2Stubbed := jsonGetString(data, "s2")
158	if sig2Stubbed != "" {
159		return importLinkFromServerV2Stubbed(m, parent, sig2Stubbed)
160	}
161
162	versionRaw, err := jsonparserw.GetInt(data, "sig_version")
163	if err != nil || versionRaw == 0 {
164		return nil, ChainLinkError{"cannot read signature version from server"}
165	}
166
167	pgpSig := getPGPSig(m, data)
168	sigVersion := SigVersion(versionRaw)
169
170	var ir *importRes
171	switch {
172	case sigVersion == KeybaseSignatureV1 && pgpSig != "":
173		ir, err = importLinkFromServerPGP(m, pgpSig, data)
174	case sigVersion == KeybaseSignatureV1 && pgpSig == "":
175		ir, err = importLinkFromServerV1NaCl(m, data)
176	case sigVersion == KeybaseSignatureV2 && pgpSig == "":
177		ir, err = importLinkFromServerV2Unstubbed(m, data)
178	default:
179		err = ChainLinkError{fmt.Sprintf("bad link back from server; version=%d; pgp=%v", sigVersion, (pgpSig != ""))}
180	}
181	if err != nil {
182		return nil, err
183	}
184
185	ret = NewChainLink(m.G(), parent, ir.linkID)
186	tmp := ChainLinkUnpacked{sigVersion: sigVersion}
187	tmp.outerLinkV2 = ir.ol2
188
189	err = tmp.unpackPayloadJSON(m.G(), ir.payload, ret.id)
190	if err != nil {
191		m.Debug("unpack payload json err: %s", err)
192		return nil, err
193	}
194	err = tmp.assertPayloadSigVersionMatchesHint(ir.payload)
195	if err != nil {
196		return nil, err
197	}
198
199	tmp.sig = ir.sig
200	tmp.sigID = ir.sigID
201	// this might overwrite the actions of unpackPayloadJSON. TODO: to change
202	// unpackPayloadJSON to fix this issue.
203	tmp.kid = ir.kid
204
205	err = importServerTrustFields(m, &tmp, data, selfUID)
206	if err != nil {
207		return nil, err
208	}
209
210	ret.unpacked = &tmp
211	ret.hashVerified = true
212	ret.payloadVerified = true
213
214	return ret, nil
215}
216
217func computeLinkIDFromHashWithWhitespaceFixes(m MetaContext, payload []byte) (LinkID, error) {
218	hsh := sha256.Sum256(payload)
219	linkID := LinkID(hsh[:])
220	converted, found := badWhitespaceLinkIDConversion[linkID.Export()]
221	if !found {
222		return linkID, nil
223	}
224	last := len(payload) - 1
225	if payload[last] != '\n' {
226		err := ChainLinkError{fmt.Sprintf("failed to strip newline from line '%s'", linkID.Export())}
227		return nil, err
228	}
229	m.Debug("Fixing payload hash by stripping newline on link '%s'", linkID.Export())
230	toHash := payload[0:last]
231	hsh = sha256.Sum256(toHash)
232	fixedLinkID := LinkID(hsh[:])
233	if !fixedLinkID.Export().Eq(converted) {
234		err := ChainLinkError{fmt.Sprintf("failed hash comparison after whitespace-fixing link '%s'", linkID.Export())}
235		return nil, err
236	}
237	return fixedLinkID, nil
238}
239
240func (s *sigChainPayloadJSON) KID() (ret keybase1.KID, err error) {
241	tmp, err := jsonparserw.GetString(s.b, "body", "key", "kid")
242	if err != nil {
243		return ret, err
244	}
245	ret = keybase1.KIDFromString(tmp)
246	return ret, nil
247}
248
249func (s *sigChainPayloadJSON) Seqno() (keybase1.Seqno, error) {
250	seqno, err := jsonparserw.GetInt(s.b, "seqno")
251	return keybase1.Seqno(seqno), err
252}
253
254func (s *sigChainPayloadJSON) Type() (string, error) {
255	return jsonparserw.GetString(s.b, "body", "type")
256}
257
258func (s *sigChainPayloadJSON) Version() (SigVersion, error) {
259	tmp, err := jsonparserw.GetInt(s.b, "body", "version")
260	return SigVersion(tmp), err
261}
262
263func (s *sigChainPayloadJSON) ClientNameAndVersion() (string, string) {
264	name, _ := jsonparserw.GetString(s.b, "client", "name")
265	version, _ := jsonparserw.GetString(s.b, "client", "version")
266	return name, version
267}
268
269func (s *sigChainPayloadJSON) AssertJSON(linkID LinkID) (err error) {
270	if !isJSONObject(s.b, linkID) {
271		return ChainLinkError{"JSON payload has leading garbage"}
272	}
273	return nil
274}
275
276func (s *sigChainPayloadJSON) Prev() (LinkID, error) {
277	data, typ, _, err := jsonparserw.Get(s.b, "prev")
278	if err != nil {
279		return nil, err
280	}
281	if typ == jsonparser.Null {
282		return nil, nil
283	}
284	if typ != jsonparser.String {
285		return nil, ChainLinkError{"bad JSON type for prev"}
286	}
287	tmp := string(data)
288	return LinkIDFromHex(tmp)
289}
290
291func (s *sigChainPayloadJSON) HasRevocations() bool {
292	if _, _, _, err := jsonparserw.Get(s.b, "body", "revoke", "sig_id"); err == nil {
293		return true
294	}
295	if _, _, _, err := jsonparserw.Get(s.b, "body", "revoke", "sig_ids", "[0]"); err == nil {
296		return true
297	}
298	if _, _, _, err := jsonparserw.Get(s.b, "body", "revoke", "kid"); err == nil {
299		return true
300	}
301	if _, _, _, err := jsonparserw.Get(s.b, "body", "revoke", "kids", "[0]"); err == nil {
302		return true
303	}
304	return false
305}
306
307func (s *sigChainPayloadJSON) HighSkip() (*HighSkip, error) {
308	hs, dataType, _, err := jsonparserw.Get(s.b, "high_skip")
309	// high_skip is optional, but must be an object if it exists
310	if err != nil {
311		switch pkgerrors.Cause(err) {
312		case jsonparser.KeyPathNotFoundError:
313			return nil, nil
314		default:
315			return nil, err
316		}
317	}
318
319	if dataType != jsonparser.Object {
320		return nil, ChainLinkError{fmt.Sprintf("When provided, expected high_skip to be a JSON object, was %v.", dataType)}
321	}
322
323	highSkipSeqnoInt, err := jsonparserw.GetInt(hs, "seqno")
324	if err != nil {
325		return nil, err
326	}
327
328	// highSkipHash can either be null (zero-value of a LinkID) or a hexstring.
329	// We call GetString first instead of Get so we only parse the value
330	// twice for the first link.
331	highSkipHashStr, err := jsonparserw.GetString(hs, "hash")
332	var highSkipHash LinkID
333	if err != nil {
334		// If there was an error parsing as a string, make sure the value is null.
335		_, dataType, _, getErr := jsonparserw.Get(hs, "hash")
336		if getErr != nil {
337			return nil, getErr
338		}
339		if dataType != jsonparser.Null {
340			return nil, ChainLinkError{
341				fmt.Sprintf("high_skip.hash was neither a valid string (%v) nor null.", err.Error()),
342			}
343		}
344	} else {
345		highSkipHash, err = LinkIDFromHex(highSkipHashStr)
346		if err != nil {
347			return nil, err
348		}
349	}
350
351	highSkip := NewHighSkip(keybase1.Seqno(highSkipSeqnoInt), highSkipHash)
352	return &highSkip, nil
353}
354
355func (s *sigChainPayloadJSON) toSigIDSuffixParameters() (ret keybase1.SigIDSuffixParameters, err error) {
356	var typ string
357	var vers SigVersion
358	typ, err = s.Type()
359	if err != nil {
360		return ret, err
361	}
362	vers, err = s.Version()
363	if err != nil {
364		return ret, err
365	}
366	return keybase1.SigIDSuffixParametersFromTypeAndVersion(typ, keybase1.SigVersion(vers)), nil
367}
368
369func newSigInfo(kid keybase1.KID, payload []byte, sig kbcrypto.NaclSignature) *kbcrypto.NaclSigInfo {
370	return &kbcrypto.NaclSigInfo{
371		Kid:      kid.ToBinaryKID(),
372		Payload:  payload,
373		Sig:      sig,
374		SigType:  kbcrypto.SigKbEddsa,
375		HashType: kbcrypto.HashPGPSha512,
376		Detached: true,
377	}
378}
379
380func decodeSig1Imploded(s string) (*kbcrypto.NaclSignature, error) {
381	raw, err := base64.StdEncoding.DecodeString(s)
382	if err != nil {
383		return nil, err
384	}
385	var ret kbcrypto.NaclSignature
386	copy(ret[:], raw)
387	return &ret, nil
388}
389
390func importLinkFromServerV1NaCl(m MetaContext, packed []byte) (*importRes, error) {
391	var sigBody []byte
392	var ret importRes
393	var sigIDBase keybase1.SigIDBase
394	var params keybase1.SigIDSuffixParameters
395
396	sig1ImplodedRaw := jsonGetString(packed, "si1")
397	if sig1ImplodedRaw == "" {
398		return nil, ChainLinkError{"no si1 field as expected"}
399	}
400
401	sig1Imploded, err := decodeSig1Imploded(sig1ImplodedRaw)
402	if err != nil {
403		return nil, err
404	}
405
406	payloadJSON, err := getPayloadJSONFromServerLink(packed)
407	if err != nil {
408		return nil, err
409	}
410	version, err := payloadJSON.Version()
411	if err != nil {
412		return nil, err
413	}
414	if version != KeybaseSignatureV1 {
415		return nil, ChainLinkError{"inner chainlink showed wrong version, while expecting 1"}
416	}
417	ret.linkID = payloadJSON.Hash()
418	err = payloadJSON.AssertJSON(ret.linkID)
419	if err != nil {
420		return nil, err
421	}
422	ret.kid, err = payloadJSON.KID()
423	if err != nil {
424		return nil, err
425	}
426	sigInfo := newSigInfo(ret.kid, payloadJSON.Bytes(), *sig1Imploded)
427	clientName, clientVersion := payloadJSON.ClientNameAndVersion()
428	sigBody, sigIDBase, err = sigid.ComputeSigBodyAndID(sigInfo, clientName, clientVersion)
429	if err != nil {
430		return nil, err
431	}
432	params, err = payloadJSON.toSigIDSuffixParameters()
433	if err != nil {
434		return nil, err
435	}
436	ret.sigID = sigIDBase.ToSigID(params)
437	ret.sig = base64.StdEncoding.EncodeToString(sigBody)
438	ret.payload = payloadJSON.Bytes()
439	return &ret, nil
440}
441
442type sig2Imploded struct {
443	_struct   bool `codec:",toarray"` //nolint
444	Sig       kbcrypto.NaclSignature
445	OuterLink OuterLinkV2
446	NumFields int
447}
448
449type sigChainPayloadJSON struct {
450	b []byte
451}
452
453func newSigChainPayloadJSON(s string) *sigChainPayloadJSON {
454	return &sigChainPayloadJSON{b: []byte(s)}
455}
456
457func newSigChainPayloadJSONFromBytes(b []byte) *sigChainPayloadJSON {
458	return &sigChainPayloadJSON{b: b}
459}
460
461func (s *sigChainPayloadJSON) Bytes() []byte {
462	return s.b
463}
464
465func (s *sigChainPayloadJSON) Hash() LinkID {
466	return ComputeLinkID(s.b)
467}
468
469func getPayloadJSONFromServerLink(packed []byte) (*sigChainPayloadJSON, error) {
470	data, _, _, err := jsonparserw.Get(packed, "payload_json")
471	if err != nil {
472		return nil, err
473	}
474	sdata, err := strconv.Unquote(`"` + string(data) + `"`)
475	if err != nil {
476		return nil, err
477	}
478	return newSigChainPayloadJSON(sdata), nil
479}
480
481func decodeSig2Imploded(s string) (*sig2Imploded, error) {
482	raw, err := base64.StdEncoding.DecodeString(s)
483	if err != nil {
484		return nil, err
485	}
486	var ret sig2Imploded
487	if !msgpack.IsEncodedMsgpackArray(raw) {
488		return nil, ChainLinkError{"expected a msgpack array but got leading junk"}
489	}
490	err = msgpack.Decode(&ret, raw)
491	if err != nil {
492		return nil, err
493	}
494	return &ret, nil
495}
496
497func importLinkFromServerV2Unstubbed(m MetaContext, packed []byte) (*importRes, error) {
498	var ret importRes
499	var sigIDBase keybase1.SigIDBase
500	var params keybase1.SigIDSuffixParameters
501
502	sig2ImplodedRaw := jsonGetString(packed, "si2")
503	if sig2ImplodedRaw == "" {
504		return nil, ChainLinkError{"no si2 field as expected"}
505	}
506	payloadJSON, err := getPayloadJSONFromServerLink(packed)
507	if err != nil {
508		return nil, err
509	}
510	version, err := payloadJSON.Version()
511	if err != nil {
512		return nil, err
513	}
514	if version != KeybaseSignatureV2 {
515		return nil, ChainLinkError{"inner chainlink showed wrong version, while expecting 2"}
516	}
517	innerLinkID := payloadJSON.Hash()
518	sig2Imploded, err := decodeSig2Imploded(sig2ImplodedRaw)
519	if err != nil {
520		return nil, err
521	}
522	sig2Imploded.OuterLink.Curr = innerLinkID
523	prev, err := payloadJSON.Prev()
524	if err != nil {
525		return nil, err
526	}
527	sig2Imploded.OuterLink.Prev = prev
528	seqno, err := payloadJSON.Seqno()
529	if err != nil {
530		return nil, err
531	}
532	sig2Imploded.OuterLink.Seqno = seqno
533	fixupSeqType(&sig2Imploded.OuterLink.SeqType)
534
535	outerPayload, err := sig2Imploded.OuterLink.EncodePartial(sig2Imploded.NumFields)
536	if err != nil {
537		m.Debug("EncodePartial failed on input si2=%s", sig2ImplodedRaw)
538		return nil, err
539	}
540	ret.linkID = ComputeLinkID(outerPayload)
541
542	err = payloadJSON.AssertJSON(ret.linkID)
543	if err != nil {
544		return nil, err
545	}
546
547	ret.kid, err = payloadJSON.KID()
548	if err != nil {
549		return nil, err
550	}
551
552	sigInfo := newSigInfo(ret.kid, outerPayload, sig2Imploded.Sig)
553
554	sigBody, err := kbcrypto.EncodePacketToBytes(sigInfo)
555	if err != nil {
556		return nil, err
557	}
558	ret.sig = base64.StdEncoding.EncodeToString(sigBody)
559	sigIDBase = kbcrypto.ComputeSigIDFromSigBody(sigBody)
560	params, err = payloadJSON.toSigIDSuffixParameters()
561	if err != nil {
562		return nil, err
563	}
564	ret.sigID = sigIDBase.ToSigID(params)
565
566	ret.ol2 = &OuterLinkV2WithMetadata{
567		OuterLinkV2: sig2Imploded.OuterLink,
568		raw:         outerPayload,
569		sigID:       ret.sigID,
570		sig:         base64.StdEncoding.EncodeToString(sigBody),
571		kid:         ret.kid,
572	}
573	linkTypeStr, err := payloadJSON.Type()
574	if err != nil {
575		return nil, err
576	}
577
578	linkType, err := SigchainV2TypeFromV1TypeAndRevocations(
579		linkTypeStr,
580		SigHasRevokes(payloadJSON.HasRevocations()),
581		sig2Imploded.OuterLink.IgnoreIfUnsupported,
582	)
583	if err != nil {
584		return nil, err
585	}
586	highSkip, err := payloadJSON.HighSkip()
587	if err != nil {
588		return nil, err
589	}
590	err = sig2Imploded.OuterLink.AssertFields(
591		KeybaseSignatureV2,
592		seqno,
593		prev,
594		innerLinkID,
595		linkType,
596		sig2Imploded.OuterLink.SeqType,
597		sig2Imploded.OuterLink.IgnoreIfUnsupported,
598		highSkip,
599	)
600	if err != nil {
601		return nil, err
602	}
603	ret.payload = payloadJSON.Bytes()
604	return &ret, nil
605}
606
607func importLinkFromServerPGP(m MetaContext, sig string, packed []byte) (*importRes, error) {
608	var ret importRes
609	var err error
610	var sigIDBase keybase1.SigIDBase
611
612	ret.payload, sigIDBase, err = SigExtractPGPPayload(sig)
613	if err != nil {
614		return nil, err
615	}
616	ret.sigID = sigIDBase.ToSigIDLegacy()
617	ret.linkID, err = computeLinkIDFromHashWithWhitespaceFixes(m, ret.payload)
618	if err != nil {
619		return nil, err
620	}
621	payloadJSON := newSigChainPayloadJSONFromBytes(ret.payload)
622
623	err = payloadJSON.AssertJSON(ret.linkID)
624	if err != nil {
625		return nil, err
626	}
627
628	// Very old PGP signatures did not include kids in signature bodies.
629	// So the server always returns such KIDs, and we check for equality
630	// with what's in the payload if it was specified.
631	payloadKID, _ := payloadJSON.KID()
632	rawServerKID, err := jsonparserw.GetString(packed, "kid")
633	if err != nil {
634		return nil, err
635	}
636	serverKID := keybase1.KIDFromString(rawServerKID)
637	if serverKID.IsNil() {
638		return nil, ChainLinkError{"server returned an invalid KID for PGP key"}
639	}
640	if !payloadKID.IsNil() && !payloadKID.Equal(serverKID) {
641		return nil, ChainLinkKIDMismatchError{"server returned a bad KID that didn't match PGP body"}
642	}
643	ret.kid = serverKID
644	ret.payload = payloadJSON.Bytes()
645	ret.sig = sig
646	return &ret, nil
647}
648