github.com/keybase/client/go@v0.0.0-20240309051027-028f7c731f8b/engine/pgp_import_key_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 "bytes" 8 "testing" 9 10 "github.com/keybase/client/go/libkb" 11 keybase1 "github.com/keybase/client/go/protocol/keybase1" 12 "github.com/stretchr/testify/require" 13 "golang.org/x/net/context" 14 15 "github.com/keybase/go-crypto/openpgp" 16 "github.com/keybase/go-crypto/openpgp/armor" 17 ) 18 19 // TestPGPSavePublicPush runs the PGPSave engine, pushing the 20 // public key to api server and checks that it runs without error. 21 func TestPGPImportAndExport(t *testing.T) { 22 tc := SetupEngineTest(t, "pgpsave") 23 defer tc.Cleanup() 24 25 u := CreateAndSignupFakeUser(tc, "login") 26 secui := &libkb.TestSecretUI{Passphrase: u.Passphrase} 27 uis := libkb.UIs{LogUI: tc.G.UI.GetLogUI(), SecretUI: secui} 28 29 // try all four permutations of push options: 30 31 _, _, key := genPGPKeyAndArmor(t, tc, u.Email) 32 eng, err := NewPGPKeyImportEngineFromBytes(tc.G, []byte(key), false) 33 if err != nil { 34 t.Fatal(err) 35 } 36 m := NewMetaContextForTest(tc).WithUIs(uis) 37 if err = RunEngine2(m, eng); err != nil { 38 t.Fatal(err) 39 } 40 41 fp, _, key := genPGPKeyAndArmor(t, tc, u.Email) 42 eng, err = NewPGPKeyImportEngineFromBytes(tc.G, []byte(key), true) 43 if err != nil { 44 t.Fatal(err) 45 } 46 if err = RunEngine2(m, eng); err != nil { 47 t.Fatal(err) 48 } 49 50 arg := keybase1.PGPExportArg{ 51 Options: keybase1.PGPQuery{ 52 Secret: true, 53 Query: fp.String(), 54 }, 55 } 56 57 xe := NewPGPKeyExportEngine(tc.G, arg) 58 if err := RunEngine2(m, xe); err != nil { 59 t.Fatal(err) 60 } 61 62 if len(xe.Results()) != 1 { 63 t.Fatalf("Expected 1 key back out") 64 } 65 66 arg = keybase1.PGPExportArg{ 67 Options: keybase1.PGPQuery{ 68 Secret: true, 69 Query: fp.String()[0:10] + "aabb", 70 }, 71 } 72 73 xe = NewPGPKeyExportEngine(tc.G, arg) 74 if err := RunEngine2(m, xe); err != nil { 75 t.Fatal(err) 76 } 77 if len(xe.Results()) != 0 { 78 t.Fatalf("num keys exported: %d, expected 0", len(xe.Results())) 79 } 80 81 arg = keybase1.PGPExportArg{ 82 Options: keybase1.PGPQuery{ 83 Secret: false, 84 }, 85 } 86 xe = NewPGPKeyExportEngine(tc.G, arg) 87 if err := RunEngine2(m, xe); err != nil { 88 t.Fatal(err) 89 } 90 if len(xe.Results()) != 2 { 91 t.Fatalf("Expected two keys back out; got %d", len(xe.Results())) 92 } 93 } 94 95 // TestPGPImportPrivImport - import the same key twice, only importing the 96 // private key the second time / on the second device (CORE-10562). 97 func TestPGPImportPrivImport(t *testing.T) { 98 user, dev1, dev2, cleanup := SetupTwoDevices(t, "login") 99 defer cleanup() 100 101 secui := &libkb.TestSecretUI{Passphrase: user.Passphrase} 102 uis := libkb.UIs{LogUI: dev1.G.UI.GetLogUI(), SecretUI: secui} 103 104 // Import a private key into dev1 105 fp, _, key := genPGPKeyAndArmor(t, dev1, user.Email) 106 eng, err := NewPGPKeyImportEngineFromBytes(dev1.G, []byte(key), false) 107 if err != nil { 108 t.Fatal(err) 109 } 110 m := NewMetaContextForTest(dev1).WithUIs(uis) 111 if err = RunEngine2(m, eng); err != nil { 112 t.Fatal(err) 113 } 114 115 // Make sure that we've imported it successfully 116 xe := NewPGPKeyExportEngine(dev1.G, keybase1.PGPExportArg{ 117 Options: keybase1.PGPQuery{ 118 Secret: true, 119 Query: fp.String(), 120 }, 121 }) 122 if err := RunEngine2(m, xe); err != nil { 123 t.Fatal(err) 124 } 125 if len(xe.Results()) != 1 { 126 t.Fatalf("Expected 1 key back out") 127 } 128 129 // Make sure that we only have a public key on dev2 130 uis = libkb.UIs{LogUI: dev2.G.UI.GetLogUI(), SecretUI: secui} 131 m = NewMetaContextForTest(dev2).WithUIs(uis) 132 133 xe = NewPGPKeyExportEngine(dev2.G, keybase1.PGPExportArg{ 134 Options: keybase1.PGPQuery{ 135 Secret: true, 136 Query: fp.String(), 137 }, 138 }) 139 if err := RunEngine2(m, xe); err != nil { 140 t.Fatal(err) 141 } 142 if len(xe.Results()) != 0 { 143 t.Fatalf("Expected 0 keys back out") 144 } 145 xe = NewPGPKeyExportEngine(dev2.G, keybase1.PGPExportArg{ 146 Options: keybase1.PGPQuery{ 147 Secret: false, 148 Query: fp.String(), 149 }, 150 }) 151 if err := RunEngine2(m, xe); err != nil { 152 t.Fatal(err) 153 } 154 if len(xe.Results()) != 1 { 155 t.Fatalf("Expected 1 key back out") 156 } 157 158 // Run import on dev2 159 eng, err = NewPGPKeyImportEngineFromBytes(dev2.G, []byte(key), false) 160 if err != nil { 161 t.Fatal(err) 162 } 163 if err = RunEngine2(m, eng); err != nil { 164 t.Fatal(err) 165 } 166 167 // Secret key should be present 168 xe = NewPGPKeyExportEngine(dev1.G, keybase1.PGPExportArg{ 169 Options: keybase1.PGPQuery{ 170 Secret: true, 171 Query: fp.String(), 172 }, 173 }) 174 if err := RunEngine2(m, xe); err != nil { 175 t.Fatal(err) 176 } 177 if len(xe.Results()) != 1 { 178 t.Fatalf("Expected 1 key back out") 179 } 180 xe = NewPGPKeyExportEngine(dev1.G, keybase1.PGPExportArg{ 181 Options: keybase1.PGPQuery{ 182 Secret: false, 183 Query: fp.String(), 184 }, 185 }) 186 if err := RunEngine2(m, xe); err != nil { 187 t.Fatal(err) 188 } 189 if len(xe.Results()) != 1 { 190 t.Fatalf("Expected 1 key back out") 191 } 192 } 193 194 func TestPGPImportLocalPrivateThenServer(t *testing.T) { 195 tc := SetupEngineTest(t, "pgpsave") 196 defer tc.Cleanup() 197 198 user := CreateAndSignupFakeUser(tc, "login") 199 secui := &libkb.TestSecretUI{Passphrase: user.Passphrase} 200 uis := libkb.UIs{LogUI: tc.G.UI.GetLogUI(), SecretUI: secui} 201 202 _, _, key := genPGPKeyAndArmor(t, tc, user.Email) 203 204 // Import a private key locally first. 205 eng, err := NewPGPKeyImportEngineFromBytes(tc.G, []byte(key), false /* pushSecret*/) 206 require.NoError(t, err) 207 mctx := NewMetaContextForTest(tc).WithUIs(uis) 208 err = RunEngine2(mctx, eng) 209 require.NoError(t, err) 210 211 // Can we import locally twice? 212 eng, err = NewPGPKeyImportEngineFromBytes(tc.G, []byte(key), false /* pushSecret*/) 213 require.NoError(t, err) 214 mctx = NewMetaContextForTest(tc).WithUIs(uis) 215 err = RunEngine2(mctx, eng) 216 require.NoError(t, err) 217 218 kid := eng.GetKID() 219 220 ss, err := mctx.ActiveDevice().SyncSecretsForce(mctx) 221 require.NoError(t, err) 222 _, ok := ss.FindPrivateKey(kid.String()) 223 require.False(t, ok) 224 225 // Try to import with push secret afterwards - user also wants 226 // to have this key available online. 227 eng, err = NewPGPKeyImportEngineFromBytes(tc.G, []byte(key), true /* pushSecret*/) 228 require.NoError(t, err) 229 mctx = NewMetaContextForTest(tc).WithUIs(uis) 230 err = RunEngine2(mctx, eng) 231 require.NoError(t, err) 232 233 ss, err = mctx.ActiveDevice().SyncSecretsForce(mctx) 234 require.NoError(t, err) 235 privKey, ok := ss.FindPrivateKey(kid.String()) 236 require.True(t, ok) 237 require.NotEmpty(t, privKey.Bundle) 238 } 239 240 // Test for issue 325. 241 func TestPGPImportPublicKey(t *testing.T) { 242 tc := SetupEngineTest(t, "pgpsave") 243 defer tc.Cleanup() 244 245 _, err := NewPGPKeyImportEngineFromBytes(tc.G, []byte(pubkeyIssue325), false) 246 if err == nil { 247 t.Fatal("import of public key didn't generate error") 248 } 249 if _, ok := err.(libkb.NoSecretKeyError); !ok { 250 t.Error(err) 251 t.Errorf("error returned for import of public key: %T, expected libkb.NoSecretKeyError", err) 252 } 253 } 254 255 func TestPGPImportNotLoggedIn(t *testing.T) { 256 tc := SetupEngineTest(t, "pgpnotloggedin") 257 defer tc.Cleanup() 258 259 u := CreateAndSignupFakeUser(tc, "login") 260 secui := &libkb.TestSecretUI{Passphrase: u.Passphrase} 261 uis := libkb.UIs{LogUI: tc.G.UI.GetLogUI(), SecretUI: secui} 262 263 _, _, key := genPGPKeyAndArmor(t, tc, u.Email) 264 eng, err := NewPGPKeyImportEngineFromBytes(tc.G, []byte(key), false) 265 if err != nil { 266 t.Fatal(err) 267 } 268 m := NewMetaContextForTest(tc).WithUIs(uis) 269 Logout(tc) 270 err = RunEngine2(m, eng) 271 require.Error(t, err) 272 require.Contains(t, err.Error(), "Login required") 273 } 274 275 func TestIssue454(t *testing.T) { 276 testImportKey(t, "pgp454", keyIssue454, "test") 277 } 278 279 func TestIssue2147(t *testing.T) { 280 testImportKey(t, "issue2147", keyIssue2147, keyIssue2147Passphrase) 281 } 282 283 func testImportKey(t *testing.T, which string, armor string, pp string) { 284 tc := SetupEngineTest(t, which) 285 defer tc.Cleanup() 286 287 CreateAndSignupFakeUser(tc, "login") 288 secui := &libkb.TestSecretUI{Passphrase: pp} 289 uis := libkb.UIs{LogUI: tc.G.UI.GetLogUI(), SecretUI: secui} 290 eng, err := NewPGPKeyImportEngineFromBytes(tc.G, []byte(armor), false) 291 eng.arg.OnlySave = true 292 if err != nil { 293 t.Fatal(err) 294 } 295 m := NewMetaContextForTest(tc).WithUIs(uis) 296 err = RunEngine2(m, eng) 297 if err != nil { 298 t.Fatal(err) 299 } 300 } 301 302 // Issue CORE-2063: check that generated secret key is exported 303 // to user's GPG keyring. 304 func TestPGPImportGPGExport(t *testing.T) { 305 tc := SetupEngineTest(t, "pgpexp") 306 defer tc.Cleanup() 307 308 u := CreateAndSignupFakeUser(tc, "pgp") 309 uis := libkb.UIs{LogUI: tc.G.UI.GetLogUI(), SecretUI: u.NewSecretUI()} 310 311 // before running, they should have no pgp keys in key family or in gpg 312 me, err := libkb.LoadMe(libkb.NewLoadUserArg(tc.G)) 313 if err != nil { 314 t.Fatal(err) 315 } 316 if len(me.GetActivePGPKeys(false)) != 0 { 317 t.Fatalf("active pgp keys: %d, expected 0", len(me.GetActivePGPKeys(false))) 318 } 319 gpgPrivate, err := numPrivateGPGKeys(tc.G) 320 if err != nil { 321 t.Fatal(err) 322 } 323 if gpgPrivate != 0 { 324 t.Fatalf("private gpg keys: %d, expected 0", gpgPrivate) 325 } 326 327 // this is similar to how cmd_pgp_gen works: 328 genArg := &libkb.PGPGenArg{ 329 PrimaryBits: 1024, 330 SubkeyBits: 1024, 331 } 332 if err := genArg.MakeAllIds(tc.G); err != nil { 333 t.Fatal(err) 334 } 335 arg := PGPKeyImportEngineArg{ 336 Gen: genArg, 337 PushSecret: true, 338 AllowMulti: true, 339 DoExport: true, 340 } 341 m := NewMetaContextForTest(tc).WithUIs(uis) 342 eng := NewPGPKeyImportEngine(tc.G, arg) 343 if err := RunEngine2(m, eng); err != nil { 344 t.Fatal(err) 345 } 346 347 // after running, they should have one pgp keys in key family and in gpg 348 me, err = libkb.LoadMe(libkb.NewLoadUserArg(tc.G)) 349 if err != nil { 350 t.Fatal(err) 351 } 352 if len(me.GetActivePGPKeys(false)) != 1 { 353 t.Errorf("active pgp keys: %d, expected 1", len(me.GetActivePGPKeys(false))) 354 } 355 gpgPrivate, err = numPrivateGPGKeys(tc.G) 356 if err != nil { 357 t.Fatal(err) 358 } 359 if gpgPrivate != 1 { 360 t.Errorf("private gpg keys: %d, expected 1", gpgPrivate) 361 } 362 } 363 364 // TestPGPImportPushSecretWithoutPassword - the engine should prevent nopw 365 // users from importing secret keys 366 func TestPGPImportPushSecretWithoutPassword(t *testing.T) { 367 tc := SetupEngineTest(t, "pgpnopw") 368 defer tc.Cleanup() 369 370 user, _ := NewFakeUser("login") 371 arg := MakeTestSignupEngineRunArg(user) 372 arg.StoreSecret = true 373 arg.GenerateRandomPassphrase = true 374 arg.Passphrase = "" 375 _, err := CreateAndSignupFakeUserSafeWithArg(tc.G, user, arg) 376 require.NoError(t, err) 377 378 secui := &libkb.TestSecretUI{} 379 uis := libkb.UIs{LogUI: tc.G.UI.GetLogUI(), SecretUI: secui} 380 _, _, key := genPGPKeyAndArmor(t, tc, user.Email) 381 eng, err := NewPGPKeyImportEngineFromBytes(tc.G, []byte(key), true) 382 require.Nil(t, err, "engine initialization should succeed") 383 m := NewMetaContextForTest(tc).WithUIs(uis) 384 err = RunEngine2(m, eng) 385 require.NotNil(t, err, "import should fail") 386 require.Contains(t, err.Error(), "You need to set your password first before uploading secret keys") 387 } 388 389 func numPrivateGPGKeys(g *libkb.GlobalContext) (int, error) { 390 gpg := g.GetGpgClient() 391 if err := gpg.Configure(libkb.NewMetaContext(context.Background(), g)); err != nil { 392 return 0, err 393 } 394 395 index, _, err := gpg.Index(libkb.NewMetaContext(context.Background(), g), true, "") 396 if err != nil { 397 return 0, err 398 } 399 400 return index.Len(), nil 401 } 402 403 func encodeArmoredPrivatePGP(entity *openpgp.Entity) (buf bytes.Buffer, err error) { 404 writer, err := armor.Encode(&buf, "PGP PRIVATE KEY BLOCK", nil) 405 if err != nil { 406 return buf, err 407 } 408 if err := entity.SerializePrivate(writer, nil); err != nil { 409 return buf, err 410 } 411 if err := writer.Close(); err != nil { 412 return buf, err 413 } 414 return buf, nil 415 } 416 417 func genPGPKeyAndArmor(t *testing.T, tc libkb.TestContext, email string) (libkb.PGPFingerprint, keybase1.KID, string) { 418 bundle, err := tc.MakePGPKey(email) 419 if err != nil { 420 t.Fatal(err) 421 } 422 buf, err := encodeArmoredPrivatePGP(bundle.Entity) 423 require.NoError(t, err) 424 fp := *bundle.GetFingerprintP() 425 kid := bundle.GetKID() 426 return fp, kid, buf.String() 427 } 428 429 const pubkeyIssue325 = `-----BEGIN PGP PUBLIC KEY BLOCK----- 430 Comment: GPGTools - http://gpgtools.org 431 432 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 463 =DDQ1 464 -----END PGP PUBLIC KEY BLOCK-----` 465 466 const keyIssue454 = `-----BEGIN PGP PRIVATE KEY BLOCK----- 467 Comment: GPGTools - http://gpgtools.org 468 469 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 570 LpRtxqDTDVA6H/R+dqEhg/ni2jAapEr4VzIbew== 571 =bXrj 572 -----END PGP PRIVATE KEY BLOCK-----` 573 574 const keyIssue2147 = `-----BEGIN PGP PRIVATE KEY BLOCK----- 575 Version: GnuPG v1 576 577 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 663 =aaae 664 -----END PGP PRIVATE KEY BLOCK----- 665 ` 666 const keyIssue2147Passphrase = "abcd"