github.com/keybase/client/go@v0.0.0-20240309051027-028f7c731f8b/engine/saltpack_decrypt_test.go (about) 1 // Copyright 2015 Keybase, Inc. All rights reserved. Use of 2 // this source code is governed by the included BSD license. 3 4 package engine 5 6 import ( 7 "errors" 8 "fmt" 9 "strings" 10 "testing" 11 12 "github.com/keybase/client/go/libkb" 13 keybase1 "github.com/keybase/client/go/protocol/keybase1" 14 "github.com/keybase/client/go/saltpackkeystest" 15 "github.com/keybase/saltpack" 16 "github.com/stretchr/testify/require" 17 "golang.org/x/net/context" 18 ) 19 20 type fakeSaltpackUI struct{} 21 22 func (s fakeSaltpackUI) SaltpackPromptForDecrypt(_ context.Context, arg keybase1.SaltpackPromptForDecryptArg, usedDelegateUI bool) (err error) { 23 return nil 24 } 25 26 func (s fakeSaltpackUI) SaltpackVerifySuccess(_ context.Context, arg keybase1.SaltpackVerifySuccessArg) error { 27 return nil 28 } 29 30 type FakeBadSenderError struct { 31 senderType keybase1.SaltpackSenderType 32 } 33 34 func (e *FakeBadSenderError) Error() string { 35 return fmt.Sprintf("fakeSaltpackUI bad sender error: %s", e.senderType.String()) 36 } 37 38 func (s fakeSaltpackUI) SaltpackVerifyBadSender(_ context.Context, arg keybase1.SaltpackVerifyBadSenderArg) error { 39 return &FakeBadSenderError{arg.Sender.SenderType} 40 } 41 42 func initPerUserKeyringInTestContext(t *testing.T, tc libkb.TestContext) { 43 kr, err := tc.G.GetPerUserKeyring(context.Background()) 44 require.NoError(t, err) 45 err = kr.Sync(libkb.NewMetaContext(context.Background(), tc.G)) 46 require.NoError(t, err) 47 } 48 49 func TestSaltpackDecrypt(t *testing.T) { 50 tc := SetupEngineTest(t, "SaltpackDecrypt") 51 defer tc.Cleanup() 52 fu := CreateAndSignupFakeUser(tc, "naclp") 53 54 initPerUserKeyringInTestContext(t, tc) 55 56 // encrypt a message 57 msg := "10 days in Japan" 58 sink := libkb.NewBufferCloser() 59 uis := libkb.UIs{ 60 IdentifyUI: &FakeIdentifyUI{}, 61 SecretUI: fu.NewSecretUI(), 62 LogUI: tc.G.UI.GetLogUI(), 63 SaltpackUI: &fakeSaltpackUI{}, 64 } 65 // Should encrypt for self, too. 66 arg := &SaltpackEncryptArg{ 67 Opts: keybase1.SaltpackEncryptOptions{ 68 UseEntityKeys: true, 69 }, 70 Source: strings.NewReader(msg), 71 Sink: sink, 72 } 73 enc := NewSaltpackEncrypt(arg, NewSaltpackUserKeyfinderAsInterface) 74 m := NewMetaContextForTest(tc).WithUIs(uis) 75 if err := RunEngine2(m, enc); err != nil { 76 t.Fatal(err) 77 } 78 out := sink.String() 79 80 t.Logf("encrypted data: %s", out) 81 82 // decrypt it 83 decoded := libkb.NewBufferCloser() 84 decarg := &SaltpackDecryptArg{ 85 Source: strings.NewReader(out), 86 Sink: decoded, 87 } 88 dec := NewSaltpackDecrypt(decarg, saltpackkeystest.NewMockPseudonymResolver(t)) 89 if err := RunEngine2(m, dec); err != nil { 90 t.Fatal(err) 91 } 92 decmsg := decoded.String() 93 if decmsg != msg { 94 t.Errorf("decoded: %s, expected: %s", decmsg, msg) 95 } 96 97 pgpMsg := `-----BEGIN PGP MESSAGE----- 98 Version: GnuPG v1 99 100 hQEMA5gKPw0B/gTfAQf+JacZcP+4d1cdmRV5qlrDUhK3qm5dtzAh8KE3z6OMSOmE 101 fUAdMZweHZMkWA5C1OZbvZ6SKaFLFHjmiD0DWlcdiXsvgPH9RpTHOSrxdjRlBuwK 102 JBz5OrDM/OStIam6jKcxBcrI43JkWOG64AOwJ4Rx3OjAnzbKJKeUCAaopbXc2M5O 103 iyTPzEsexRFjSfPGRk9cQD5zfar3Qjk2cRWElgABiQczWtfNAQ3NyQLzmRU6mw+i 104 ZLoViAwQm2BMYa2i6MYOJCQtxHLwZCtAbRXTGFZ2nP0gVVX50KIeL/rnzrQ4I05M 105 CljEVk3BBSQBl3jqecfT2Ooh+rwgf3VSQ684HIEt5dI/Aama8l7S3ypwVyt8gWhN 106 HTngZWUk8Tjn6Q8zrnnoB92G1G+rZHAiChgBFQCaYDBsWa0Pia6Vm+10OAIulGGj 107 =pNG+ 108 -----END PGP MESSAGE----- 109 ` 110 decoded = libkb.NewBufferCloser() 111 decarg = &SaltpackDecryptArg{ 112 Source: strings.NewReader(pgpMsg), 113 Sink: decoded, 114 } 115 dec = NewSaltpackDecrypt(decarg, saltpackkeystest.NewMockPseudonymResolver(t)) 116 err := RunEngine2(m, dec) 117 if wse, ok := err.(libkb.WrongCryptoFormatError); !ok { 118 t.Fatalf("Wanted a WrongCryptoFormat error, but got %T (%v)", err, err) 119 } else if wse.Wanted != libkb.CryptoMessageFormatSaltpack || 120 wse.Received != libkb.CryptoMessageFormatPGP || 121 wse.Operation != "decrypt" { 122 t.Fatalf("Bad error: %v", wse) 123 } 124 125 } 126 127 type testDecryptSaltpackUI struct { 128 fakeSaltpackUI 129 f func(arg keybase1.SaltpackPromptForDecryptArg) error 130 } 131 132 func (t *testDecryptSaltpackUI) SaltpackPromptForDecrypt(_ context.Context, arg keybase1.SaltpackPromptForDecryptArg, usedDelegateUI bool) (err error) { 133 if t.f == nil { 134 return nil 135 } 136 return t.f(arg) 137 } 138 139 func TestSaltpackDecryptBrokenTrack(t *testing.T) { 140 tc := SetupEngineTest(t, "SaltpackDecrypt") 141 defer tc.Cleanup() 142 sigVersion := libkb.GetDefaultSigVersion(tc.G) 143 144 // create a user to track the proofUser 145 trackUser := CreateAndSignupFakeUser(tc, "naclp") 146 Logout(tc) 147 148 // create a user with a rooter proof 149 proofUser := CreateAndSignupFakeUser(tc, "naclp") 150 ui, _, err := proveRooter(tc.G, proofUser, sigVersion) 151 if err != nil { 152 t.Fatal(err) 153 } 154 155 spui := testDecryptSaltpackUI{} 156 157 // encrypt a message 158 msg := "10 days in Japan" 159 sink := libkb.NewBufferCloser() 160 uis := libkb.UIs{ 161 IdentifyUI: &FakeIdentifyUI{}, 162 SecretUI: proofUser.NewSecretUI(), 163 LogUI: tc.G.UI.GetLogUI(), 164 SaltpackUI: &spui, 165 } 166 167 arg := &SaltpackEncryptArg{ 168 Source: strings.NewReader(msg), 169 Sink: sink, 170 Opts: keybase1.SaltpackEncryptOptions{ 171 NoSelfEncrypt: true, 172 UseEntityKeys: true, 173 Recipients: []string{ 174 trackUser.Username, 175 }, 176 }, 177 } 178 enc := NewSaltpackEncrypt(arg, NewSaltpackUserKeyfinderAsInterface) 179 m := NewMetaContextForTest(tc).WithUIs(uis) 180 if err := RunEngine2(m, enc); err != nil { 181 t.Fatal(err) 182 } 183 out := sink.String() 184 185 // Also output a anonymous-sender message 186 arg.Opts.AuthenticityType = keybase1.AuthenticityType_ANONYMOUS 187 sink = libkb.NewBufferCloser() 188 arg.Source = strings.NewReader(msg) 189 arg.Sink = sink 190 enc = NewSaltpackEncrypt(arg, NewSaltpackUserKeyfinderAsInterface) 191 if err := RunEngine2(m, enc); err != nil { 192 t.Fatal(err) 193 } 194 outHidden := sink.String() 195 196 Logout(tc) 197 198 // Now login as the track user and track the proofUser 199 trackUser.LoginOrBust(tc) 200 rbl := sb{ 201 social: true, 202 id: proofUser.Username + "@rooter", 203 proofState: keybase1.ProofState_OK, 204 } 205 outcome := keybase1.IdentifyOutcome{ 206 NumProofSuccesses: 1, 207 TrackStatus: keybase1.TrackStatus_NEW_OK, 208 } 209 err = checkTrack(tc, trackUser, proofUser.Username, []sb{rbl}, &outcome, sigVersion) 210 if err != nil { 211 t.Fatal(err) 212 } 213 214 // decrypt it 215 decoded := libkb.NewBufferCloser() 216 decarg := &SaltpackDecryptArg{ 217 Source: strings.NewReader(out), 218 Sink: decoded, 219 } 220 initPerUserKeyringInTestContext(t, tc) 221 dec := NewSaltpackDecrypt(decarg, saltpackkeystest.NewMockPseudonymResolver(t)) 222 spui.f = func(arg keybase1.SaltpackPromptForDecryptArg) error { 223 if arg.Sender.SenderType != keybase1.SaltpackSenderType_TRACKING_OK { 224 t.Fatalf("Bad sender type: %v", arg.Sender.SenderType) 225 } 226 return nil 227 } 228 if err := RunEngine2(m, dec); err != nil { 229 t.Fatal(err) 230 } 231 decmsg := decoded.String() 232 // Should work! 233 if decmsg != msg { 234 t.Fatalf("decoded: %s, expected: %s", decmsg, msg) 235 } 236 237 // now decrypt the hidden-self message 238 decoded = libkb.NewBufferCloser() 239 decarg = &SaltpackDecryptArg{ 240 Source: strings.NewReader(outHidden), 241 Sink: decoded, 242 } 243 initPerUserKeyringInTestContext(t, tc) 244 dec = NewSaltpackDecrypt(decarg, saltpackkeystest.NewMockPseudonymResolver(t)) 245 spui.f = func(arg keybase1.SaltpackPromptForDecryptArg) error { 246 if arg.Sender.SenderType != keybase1.SaltpackSenderType_ANONYMOUS { 247 t.Fatalf("Bad sender type: %v", arg.Sender.SenderType) 248 } 249 return nil 250 } 251 if err := RunEngine2(m, dec); err != nil { 252 t.Fatal(err) 253 } 254 decmsg = decoded.String() 255 // Should work! 256 if decmsg != msg { 257 t.Fatalf("decoded: %s, expected: %s", decmsg, msg) 258 } 259 260 // remove the rooter proof to break the tracking statement 261 Logout(tc) 262 proofUser.LoginOrBust(tc) 263 if err := proveRooterRemove(tc.G, ui.postID); err != nil { 264 t.Fatal(err) 265 } 266 267 Logout(tc) 268 269 // Decrypt the message and fail, since our tracking statement is now 270 // broken. 271 trackUser.LoginOrBust(tc) 272 decoded = libkb.NewBufferCloser() 273 decarg = &SaltpackDecryptArg{ 274 Source: strings.NewReader(out), 275 Sink: decoded, 276 Opts: keybase1.SaltpackDecryptOptions{ 277 ForceRemoteCheck: true, 278 }, 279 } 280 initPerUserKeyringInTestContext(t, tc) 281 dec = NewSaltpackDecrypt(decarg, saltpackkeystest.NewMockPseudonymResolver(t)) 282 errTrackingBroke := errors.New("tracking broke") 283 spui.f = func(arg keybase1.SaltpackPromptForDecryptArg) error { 284 if arg.Sender.SenderType != keybase1.SaltpackSenderType_TRACKING_BROKE { 285 t.Fatalf("Bad sender type: %v", arg.Sender.SenderType) 286 } 287 return errTrackingBroke 288 } 289 err = RunEngine2(m, dec) 290 if decErr, ok := err.(libkb.DecryptionError); ok && decErr.Cause.Err != errTrackingBroke { 291 t.Fatalf("Expected an error %v; but got %v", errTrackingBroke, err) 292 } 293 } 294 295 // The error info that this test is looking for is only available in legacy 296 // saltpack encryption (i.e. repudiable) mode messages (originally called 297 // encryption-only mode). Modern repudiable messages always have all-anonymous-recipients, 298 // and signcryption messages have opaque receivers. 299 func TestSaltpackNoEncryptionForDevice(t *testing.T) { 300 // userX has one device (device X) and a paper key. userZ will encrypt a message for userX, 301 // then userX will add a new device (Y) which should not be able to decrypt the message 302 // (as we are not using PUKs) but will receive an helpful error message which tells them 303 // which other devices to use to decrypt. 304 305 // device X (provisioner) context: 306 tcX := SetupEngineTest(t, "kex2provision") 307 defer tcX.Cleanup() 308 309 // device Z is the encryptor's device 310 tcZ := SetupEngineTest(t, "encryptor") 311 defer tcZ.Cleanup() 312 313 // provisioner needs to be logged in 314 userX := CreateAndSignupFakeUserPaper(tcX, "naclp") 315 316 encryptor := CreateAndSignupFakeUser(tcZ, "naclp") 317 spui := testDecryptSaltpackUI{} 318 319 // encrypt a message with encryption / tcZ 320 msg := "10 days in Japan" 321 sink := libkb.NewBufferCloser() 322 uis := libkb.UIs{ 323 IdentifyUI: &FakeIdentifyUI{}, 324 SecretUI: encryptor.NewSecretUI(), 325 LogUI: tcZ.G.UI.GetLogUI(), 326 SaltpackUI: &spui, 327 } 328 329 arg := &SaltpackEncryptArg{ 330 Source: strings.NewReader(msg), 331 Sink: sink, 332 Opts: keybase1.SaltpackEncryptOptions{ 333 Recipients: []string{ 334 userX.Username, 335 }, 336 UseDeviceKeys: true, 337 UsePaperKeys: true, 338 AuthenticityType: keybase1.AuthenticityType_REPUDIABLE, 339 }, 340 } 341 enc := NewSaltpackEncrypt(arg, NewSaltpackUserKeyfinderAsInterface) 342 m := NewMetaContextForTest(tcZ).WithUIs(uis) 343 // The error messages in this test only work for visible recipients, which 344 // aren't the default anymore. 345 enc.visibleRecipientsForTesting = true 346 347 if err := RunEngine2(m, enc); err != nil { 348 t.Fatal(err) 349 } 350 out := sink.String() 351 352 // decrypt it with userX / tcX 353 decoded := libkb.NewBufferCloser() 354 decarg := &SaltpackDecryptArg{ 355 Source: strings.NewReader(out), 356 Sink: decoded, 357 } 358 dec := NewSaltpackDecrypt(decarg, saltpackkeystest.NewMockPseudonymResolver(t)) 359 spui.f = func(arg keybase1.SaltpackPromptForDecryptArg) error { 360 if arg.Sender.SenderType != keybase1.SaltpackSenderType_NOT_TRACKED { 361 t.Fatalf("Bad sender type: %v", arg.Sender.SenderType) 362 } 363 return nil 364 } 365 uis = libkb.UIs{ 366 IdentifyUI: &FakeIdentifyUI{}, 367 SecretUI: userX.NewSecretUI(), 368 LogUI: tcX.G.UI.GetLogUI(), 369 SaltpackUI: &spui, 370 } 371 m = NewMetaContextForTest(tcX).WithUIs(uis) 372 if err := RunEngine2(m, dec); err != nil { 373 t.Fatal(err) 374 } 375 decmsg := decoded.String() 376 // Should work! 377 if decmsg != msg { 378 t.Fatalf("decoded: %s, expected: %s", decmsg, msg) 379 } 380 381 // Now make a new device for userX 382 tcY, Cleanup := provisionNewDeviceKex(&tcX, userX) 383 defer Cleanup() 384 if err := AssertProvisioned(*tcY); err != nil { 385 t.Fatal(err) 386 } 387 388 // Now try and fail to decrypt with device Y (via tcY) 389 decoded = libkb.NewBufferCloser() 390 decarg = &SaltpackDecryptArg{ 391 Source: strings.NewReader(out), 392 Sink: decoded, 393 } 394 dec = NewSaltpackDecrypt(decarg, saltpackkeystest.NewMockPseudonymResolver(t)) 395 spui.f = func(arg keybase1.SaltpackPromptForDecryptArg) error { 396 t.Fatal("should not be prompted for decryption") 397 return nil 398 } 399 uis = libkb.UIs{ 400 IdentifyUI: &FakeIdentifyUI{}, 401 SecretUI: userX.NewSecretUI(), 402 LogUI: tcY.G.UI.GetLogUI(), 403 SaltpackUI: &spui, 404 } 405 m = NewMetaContextForTest(*tcY).WithUIs(uis) 406 if err := RunEngine2(m, dec); err == nil { 407 t.Fatal("Should have seen a decryption error") 408 } 409 410 // Make sure we get the right helpful debug message back 411 me := dec.MessageInfo() 412 if len(me.Devices) != 2 { 413 t.Fatalf("expected 2 valid devices; got %d", len(me.Devices)) 414 } 415 416 backup := 0 417 desktops := 0 418 for _, d := range me.Devices { 419 switch d.Type { 420 case keybase1.DeviceTypeV2_PAPER: 421 backup++ 422 case keybase1.DeviceTypeV2_DESKTOP: 423 desktops++ 424 if !userX.EncryptionKey.GetKID().Equal(d.EncryptKey) { 425 t.Fatal("got wrong encryption key for good possibilities") 426 } 427 default: 428 t.Fatalf("wrong kind of device: %s\n", d.Type) 429 } 430 } 431 if backup != 1 { 432 t.Fatal("Only wanted 1 backup key") 433 } 434 if desktops != 1 { 435 t.Fatal("only wanted 1 desktop key") 436 } 437 } 438 439 func TestSaltpackDecryptWithPaperKey(t *testing.T) { 440 tc := SetupEngineTest(t, "SaltpackDecrypt") 441 defer tc.Cleanup() 442 443 // We don't log in as a test user here. This flow should work even if 444 // you're totally logged out. 445 446 msg := `BEGIN KEYBASE SALTPACK ENCRYPTED MESSAGE. kiPgBwdlv6bV9N8 447 dSkCbjKrku4NADt gV8qC1k8zRA0Bi0 6KvGQoMyf99b2id uGZ3EDTqb5nZVPT 448 vhMiB49BOHavdzN mySkmzwlSWDsuQA z9RIPfrIX9IJCfi yqlaD1HOqK1lilP 449 tDrign5LrAB8zLz 4NwPFBwpQJWW8sO N9Jk6yzf6QvdPav GN9SqL6YX7XEbJc 450 PLrDD7LCj7fHObD O3pTQSLjuUKqAqa 3LDiQEVEDUZzYLy TvKyMJ2U8gCuhcU 451 SeqDClUNAPKqEEM MRgyTcw0LSwK4A5 YyZhDM065PA5SHb 6ZFPGYnv81HOibR 452 FHHv5lYEqPqPAZa ETIXLblnxI61F2q 6cH3w60bbxFuQB2 fwLZQSUS4ZzyVSw 453 UN3OKZMr79vqr6S ap3vMMqGiWm3blG ptjZEmFXI5dQqZG w9AO0Djmy2fWnCB 454 Z42e7BZteGaRhz8 zVmNLdOvtWiJkRF FUo2KvUgBsk9ecJ 3iZUOhYbdqja2Xx 455 osdOqu6OUS9V4XC H9vRylZJShvVg2X NLaeeHZ6AHdxkxO NgrG1NqHeIubq8p 456 0VaDq1iKk78Qj27 4q26yqnt5E9sgnN xJ850oP5DeKWrN3 yaif8ouprlETzY3 457 CLmDsAN5vVCgVga gx1q3YEjKUmJqD2 EsY5KBKogE1YjvQ eVaoqX5qiKtS6o0 458 oGE70tbveveK0kV SErmRsOSFBieaCq JzW75TXRCHpLvVB 1ZB8Wih6cyvw1yx 459 pK5RJNfPOF6lzKm i28FT9EoCw7uvsB kBG2EfA9YRkhXKh RoqAGrkdX3ziGy8 460 j5eOK91eyIcl7f7 SfUFLzETW5ULZfm 7Z9BIeOJogk7a1B 7IUJQiYpLyG3xAF 461 p3nmeSIalwfIzhV opNxUB7ltUOn3PX t9abJAZkUodMURG zXw0dKHQKtWXce6 462 y8jHbaU0zLwxvhO W3bxHNGoQ10t7Gq hSPu7SYLYyD926w 8nv5FqiUtTf7eJq 463 Ay1c2FAYMPkB4ay 6lB0wxtpNCGt8MO RtrC1Da3aj7rLTL fFNz2kxb78hT2Tu 464 QNiHyBL. END KEYBASE SALTPACK ENCRYPTED MESSAGE.` 465 466 paperkey := "fitness weasel session truly among connect explain found measure smile ask ball shoulder" 467 468 // decrypt it 469 decoded := libkb.NewBufferCloser() 470 decarg := &SaltpackDecryptArg{ 471 Source: strings.NewReader(msg), 472 Sink: decoded, 473 Opts: keybase1.SaltpackDecryptOptions{ 474 UsePaperKey: true, 475 }, 476 } 477 dec := NewSaltpackDecrypt(decarg, saltpackkeystest.NewMockPseudonymResolver(t)) 478 uis := libkb.UIs{ 479 IdentifyUI: &FakeIdentifyUI{}, 480 // Here's where the paper key goes in! 481 SecretUI: &libkb.TestSecretUI{Passphrase: paperkey}, 482 LogUI: tc.G.UI.GetLogUI(), 483 SaltpackUI: &fakeSaltpackUI{}, 484 } 485 m := NewMetaContextForTest(tc).WithUIs(uis) 486 if err := RunEngine2(m, dec); err != nil { 487 t.Fatal(err) 488 } 489 decmsg := decoded.String() 490 expected := "message for paper key" 491 if decmsg != expected { 492 t.Errorf("decoded: %s, expected: %s", decmsg, expected) 493 } 494 } 495 496 func TestSaltpackDecryptErrors(t *testing.T) { 497 tc := SetupEngineTest(t, "SaltpackDecrypt") 498 defer tc.Cleanup() 499 fu := CreateAndSignupFakeUser(tc, "naclp") 500 501 initPerUserKeyringInTestContext(t, tc) 502 503 // encrypt a message 504 msg := "10 days in Japan" 505 sink := libkb.NewBufferCloser() 506 uis := libkb.UIs{ 507 IdentifyUI: &FakeIdentifyUI{}, 508 SecretUI: fu.NewSecretUI(), 509 LogUI: tc.G.UI.GetLogUI(), 510 SaltpackUI: &fakeSaltpackUI{}, 511 } 512 // Should encrypt for self, too. 513 arg := &SaltpackEncryptArg{ 514 Opts: keybase1.SaltpackEncryptOptions{ 515 UseEntityKeys: true, 516 }, 517 Source: strings.NewReader(msg), 518 Sink: sink, 519 } 520 enc := NewSaltpackEncrypt(arg, NewSaltpackUserKeyfinderAsInterface) 521 m := NewMetaContextForTest(tc).WithUIs(uis) 522 if err := RunEngine2(m, enc); err != nil { 523 t.Fatal(err) 524 } 525 out := sink.String() 526 527 t.Logf("encrypted data: %s", out) 528 529 // assert that decryption works 530 decoded := libkb.NewBufferCloser() 531 decarg := &SaltpackDecryptArg{ 532 Source: strings.NewReader(out), 533 Sink: decoded, 534 } 535 dec := NewSaltpackDecrypt(decarg, saltpackkeystest.NewMockPseudonymResolver(t)) 536 if err := RunEngine2(m, dec); err != nil { 537 t.Fatal(err) 538 } 539 decmsg := decoded.String() 540 if decmsg != msg { 541 t.Errorf("decoded: %s, expected: %s", decmsg, msg) 542 } 543 544 // no suitable key 545 546 noKeyOut := ` 547 BEGIN KEYBASE SALTPACK ENCRYPTED MESSAGE. keDIDMQWYvVR58B FTfTeDQNI4kF4aV 548 DVTLefltGS2t8xf vO9CL7B6UQvpJEM WofNn31JYOAziF6 5vLTstSAXwLrJQ0 549 K6KJtSb38V1EsJJ sJMdU57C9s3dYEy Fk9Rw1bK2dTnua5 b822rmZdhdw7VzS 550 RwR1shIDHPXgFGC 5HhonSburbeywdE lSriPuVhSAXX9yR kwgCa3jRY3y863C 551 pwxv8lB10IjmgSx Xb5D61t8WCZ86N0 pADtHnYeyXwezjW fSEE57xOLE8naAz 552 RJLPlTEhoqllLQh iK1yzp6bGeJyAlI ctWQKKORiIyIsNS 1oFT8dj7SUtWhxy 553 nAGjUIDfkIBzBB3 SbPgWxhBKnXbW0R LCMxKOGhgpolubZ sdlVLZmP0F. END KEYBASE 554 SALTPACK ENCRYPTED MESSAGE. 555 ` 556 557 decoded = libkb.NewBufferCloser() 558 decarg = &SaltpackDecryptArg{ 559 Source: strings.NewReader(noKeyOut), 560 Sink: decoded, 561 } 562 dec = NewSaltpackDecrypt(decarg, saltpackkeystest.NewMockPseudonymResolver(t)) 563 err := RunEngine2(m, dec) 564 require.Error(t, err) 565 require.IsType(t, libkb.DecryptionError{}, err) 566 if err, ok := err.(libkb.DecryptionError); ok { 567 require.IsType(t, libkb.NoDecryptionKeyError{}, err.Cause.Err) 568 require.Equal(t, libkb.SCDecryptionKeyNotFound, err.Cause.StatusCode) 569 } 570 571 // wrong type 572 573 wrongTypeOut := `BEGIN KEYBASE SALTPACK SIGNED MESSAGE. kXR7VktZdyH7rvq v5weRa0zkUpZbPl nShyKLCCGSyBcvL sg7Gi9ySjlkxHPS RUM4Vm3DUCrEkxO bkbzrs0zuASSJbt aRoYF7ojm5zUxFX QasNzKboA7khwAa qIlCC0iwTFB3NBq fmDjvyKYfyQACcV 4BG5Mij3RfCYqAw gLtvUzU0UmfhJoP JPbj2eztW. END KEYBASE SALTPACK SIGNED MESSAGE.` 574 575 decoded = libkb.NewBufferCloser() 576 decarg = &SaltpackDecryptArg{ 577 Source: strings.NewReader(wrongTypeOut), 578 Sink: decoded, 579 } 580 dec = NewSaltpackDecrypt(decarg, saltpackkeystest.NewMockPseudonymResolver(t)) 581 err = RunEngine2(m, dec) 582 require.Error(t, err) 583 require.IsType(t, libkb.DecryptionError{}, err) 584 if err, ok := err.(libkb.DecryptionError); ok { 585 require.IsType(t, saltpack.ErrWrongMessageType{}, err.Cause.Err) 586 require.Equal(t, libkb.SCWrongCryptoMsgType, err.Cause.StatusCode) 587 } 588 }