github.com/keybase/client/go@v0.0.0-20241007131713-f10651d043c8/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"