github.com/keybase/client/go@v0.0.0-20241007131713-f10651d043c8/engine/pgp_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  	"runtime/debug"
     8  	"strings"
     9  	"testing"
    10  
    11  	"github.com/keybase/client/go/libkb"
    12  	"github.com/stretchr/testify/require"
    13  )
    14  
    15  func TestGenerateNewPGPKey(t *testing.T) {
    16  	tc := SetupEngineTest(t, "pgp")
    17  	defer tc.Cleanup()
    18  	fu := CreateAndSignupFakeUser(tc, "pgp")
    19  	secui := &libkb.TestSecretUI{Passphrase: fu.Passphrase}
    20  	arg := PGPKeyImportEngineArg{
    21  		Gen: &libkb.PGPGenArg{
    22  			PrimaryBits: 768,
    23  			SubkeyBits:  768,
    24  		},
    25  	}
    26  	err := arg.Gen.MakeAllIds(tc.G)
    27  	require.NoError(t, err)
    28  	uis := libkb.UIs{
    29  		LogUI:    tc.G.UI.GetLogUI(),
    30  		SecretUI: secui,
    31  	}
    32  	eng := NewPGPKeyImportEngine(tc.G, arg)
    33  	m := NewMetaContextForTest(tc).WithUIs(uis)
    34  	err = RunEngine2(m, eng)
    35  	if err != nil {
    36  		t.Fatal(err)
    37  	}
    38  }
    39  
    40  func TestPGPUserInterface(t *testing.T) {
    41  	p := newPgpPair(t)
    42  	defer p.cleanup()
    43  
    44  	p.assert(!p.senderTracksRecipient(), "sender shouldn't track recipient")
    45  	p.assert(!p.recipientTracksSender(), "recipient shouldn't track sender")
    46  
    47  	// encrypt, not signed
    48  	notSigned, idCount := p.encrypt(false)
    49  
    50  	// test that identify ui was shown once to sender for recipient
    51  	p.assertEqual(idCount, 1, "identify ui count [encrypt, not signed]")
    52  	// with identify2, no tracking, so test that sender doesn't track recipient
    53  	p.assert(!p.senderTracksRecipient(), "after encrypt, sender shouldn't track recipient")
    54  	p.assert(!p.recipientTracksSender(), "after encrypt, recipient shouldn't track sender")
    55  
    56  	// encrypt, signed
    57  	signed, idCount := p.encrypt(true)
    58  
    59  	// test that identify ui was *not* shown to sender for recipient since
    60  	// just shown in previous p.encrypt() call.
    61  	p.assertEqual(idCount, 0, "identify ui count [encrypt, signed]")
    62  	// with identify2, not tracking, so test that sender doesn't track recipient
    63  	p.assert(!p.senderTracksRecipient(), "after encrypt, sender shouldn't track recipient")
    64  	p.assert(!p.recipientTracksSender(), "after encrypt, recipient shouldn't track sender")
    65  
    66  	// decrypt, not signed
    67  	p.checkIdentifyUIAndPgpUI("decrypt not signed", p.decrypt, notSigned, 0)
    68  
    69  	// decrypt signed
    70  	p.checkIdentifyUIAndPgpUI("decrypt signed", p.decrypt, signed, 1)
    71  
    72  	// decrypt signed, assert signed by anyone
    73  	p.checkIdentifyUIAndPgpUI("decrypt assert signed", p.decryptAssertSigned, signed, 1)
    74  
    75  	// decrypt signed with user assertion
    76  	p.checkIdentifyUIAndPgpUI("decrypt assert signed by", p.decryptAssertSignedBySender, signed, 1)
    77  
    78  	// decrypt signed by self
    79  	p.checkIdentifyUIAndPgpUI("decrypt self", p.decryptSelf, signed, 1)
    80  
    81  	// decrypt assert signed by self
    82  	p.checkIdentifyUIAndPgpUI("decrypt assert signed by self", p.decryptAssertSignedBySelf, signed, 1)
    83  
    84  	// verify signed
    85  	p.checkIdentifyUIAndPgpUI("verify signed", p.verify, signed, 1)
    86  
    87  	// verify signed with assertion
    88  	p.checkIdentifyUIAndPgpUI("verify assert signed by", p.verifyAssertSignedBySender, signed, 1)
    89  
    90  	// verify signed by self
    91  	p.checkIdentifyUIAndPgpUI("verify self", p.verifySelf, signed, 1)
    92  
    93  	// verify assert signed by self
    94  	p.checkIdentifyUIAndPgpUI("verify assert signed by self", p.verifyAssertSignedBySelf, signed, 1)
    95  }
    96  
    97  type pgpPair struct {
    98  	t         *testing.T
    99  	tcS       libkb.TestContext
   100  	tcR       libkb.TestContext
   101  	sender    *FakeUser
   102  	recipient *FakeUser
   103  }
   104  
   105  func newPgpPair(t *testing.T) *pgpPair {
   106  	p := pgpPair{t: t}
   107  	p.tcS = SetupEngineTest(t, "sender")
   108  	p.sender = createFakeUserWithPGPSibkey(p.tcS)
   109  
   110  	p.tcR = SetupEngineTest(t, "recip")
   111  	p.recipient = createFakeUserWithPGPSibkey(p.tcR)
   112  	return &p
   113  }
   114  
   115  func (p *pgpPair) cleanup() {
   116  	p.tcS.Cleanup()
   117  	p.tcR.Cleanup()
   118  }
   119  
   120  func (p *pgpPair) assert(b bool, m string) {
   121  	if b {
   122  		return
   123  	}
   124  	p.t.Fatal(m)
   125  }
   126  
   127  func (p *pgpPair) assertEqual(actual, expected int, m string) {
   128  	if actual == expected {
   129  		return
   130  	}
   131  	p.t.Fatalf("%s: %d, expected %d", m, actual, expected)
   132  }
   133  
   134  func (p *pgpPair) checkIdentifyUIAndPgpUI(name string, f func(string) (int, int), m string, n int) {
   135  	idCount, sigCount := f(m)
   136  
   137  	// test that identify ui was shown n times
   138  	p.assertEqual(idCount, n, name+": identify ui count")
   139  	// test that recipient does not track sender
   140  	p.assert(!p.recipientTracksSender(), name+": recipient shouldn't track sender")
   141  	// test that signature success was shown n times
   142  	p.assertEqual(sigCount, n, name+": sig ui count")
   143  }
   144  
   145  func (p *pgpPair) senderTracksRecipient() bool {
   146  	return p.isTracking(p.tcS, p.recipient.Username)
   147  }
   148  
   149  func (p *pgpPair) recipientTracksSender() bool {
   150  	return p.isTracking(p.tcR, p.sender.Username)
   151  }
   152  
   153  func (p *pgpPair) isTracking(meContext libkb.TestContext, username string) bool {
   154  	me, err := libkb.LoadMe(libkb.NewLoadUserArg(meContext.G))
   155  	if err != nil {
   156  		p.t.Fatal(err)
   157  	}
   158  	them, err := libkb.LoadUser(libkb.NewLoadUserByNameArg(meContext.G, username))
   159  	if err != nil {
   160  		p.t.Fatal(err)
   161  	}
   162  	m := NewMetaContextForTest(meContext)
   163  	s, err := me.TrackChainLinkFor(m, them.GetNormalizedName(), them.GetUID())
   164  	if err != nil {
   165  		p.t.Fatal(err)
   166  	}
   167  	return s != nil
   168  }
   169  
   170  func (p *pgpPair) encrypt(sign bool) (string, int) {
   171  	uis := libkb.UIs{
   172  		IdentifyUI: &FakeIdentifyUI{},
   173  		PgpUI:      &TestPgpUI{},
   174  		SecretUI:   p.sender.NewSecretUI(),
   175  	}
   176  	sink := libkb.NewBufferCloser()
   177  	arg := &PGPEncryptArg{
   178  		Recips: []string{p.recipient.Username},
   179  		Source: strings.NewReader("thank you for your order"),
   180  		Sink:   sink,
   181  		NoSign: !sign,
   182  	}
   183  
   184  	eng := NewPGPEncrypt(p.tcS.G, arg)
   185  	m := NewMetaContextForTest(p.tcS).WithUIs(uis)
   186  	if err := RunEngine2(m, eng); err != nil {
   187  		p.t.Fatal(err)
   188  	}
   189  
   190  	out := sink.Bytes()
   191  
   192  	return string(out), p.idc(m)
   193  }
   194  
   195  func (p *pgpPair) decrypt(msg string) (int, int) {
   196  	return p.doDecrypt(msg, &PGPDecryptArg{})
   197  }
   198  
   199  func (p *pgpPair) decryptAssertSigned(msg string) (int, int) {
   200  	return p.doDecrypt(msg, &PGPDecryptArg{AssertSigned: true})
   201  }
   202  
   203  func (p *pgpPair) decryptAssertSignedBySender(msg string) (int, int) {
   204  	return p.doDecrypt(msg, &PGPDecryptArg{SignedBy: p.sender.Username})
   205  }
   206  
   207  func (p *pgpPair) decryptSelf(msg string) (int, int) {
   208  	ctx := decengctx(p.sender, p.tcS)
   209  	arg := &PGPDecryptArg{
   210  		Source: strings.NewReader(msg),
   211  		Sink:   libkb.NewBufferCloser(),
   212  	}
   213  	dec := NewPGPDecrypt(p.tcS.G, arg)
   214  	if err := RunEngine2(ctx, dec); err != nil {
   215  		p.t.Fatal(err)
   216  	}
   217  	return p.idc(ctx), p.sigc(ctx)
   218  }
   219  
   220  func (p *pgpPair) decryptAssertSignedBySelf(msg string) (int, int) {
   221  	ctx := decengctx(p.sender, p.tcS)
   222  	arg := &PGPDecryptArg{
   223  		Source:   strings.NewReader(msg),
   224  		Sink:     libkb.NewBufferCloser(),
   225  		SignedBy: p.sender.Username,
   226  	}
   227  	dec := NewPGPDecrypt(p.tcS.G, arg)
   228  	if err := RunEngine2(ctx, dec); err != nil {
   229  		p.t.Fatal(err)
   230  	}
   231  	return p.idc(ctx), p.sigc(ctx)
   232  }
   233  
   234  func (p *pgpPair) doDecrypt(msg string, arg *PGPDecryptArg) (int, int) {
   235  	ctx := decengctx(p.recipient, p.tcR)
   236  	arg.Source = strings.NewReader(msg)
   237  	arg.Sink = libkb.NewBufferCloser()
   238  	dec := NewPGPDecrypt(p.tcR.G, arg)
   239  	if err := RunEngine2(ctx, dec); err != nil {
   240  		debug.PrintStack()
   241  		p.t.Fatal(err)
   242  	}
   243  	return p.idc(ctx), p.sigc(ctx)
   244  }
   245  
   246  func (p *pgpPair) verify(msg string) (int, int) {
   247  	ctx := decengctx(p.recipient, p.tcR)
   248  	arg := &PGPVerifyArg{
   249  		Source: strings.NewReader(msg),
   250  	}
   251  	eng := NewPGPVerify(p.tcR.G, arg)
   252  	if err := RunEngine2(ctx, eng); err != nil {
   253  		p.t.Fatal(err)
   254  	}
   255  	return p.idc(ctx), p.sigc(ctx)
   256  }
   257  
   258  func (p *pgpPair) verifyAssertSignedBySender(msg string) (int, int) {
   259  	ctx := decengctx(p.recipient, p.tcR)
   260  	arg := &PGPVerifyArg{
   261  		Source:   strings.NewReader(msg),
   262  		SignedBy: p.sender.Username,
   263  	}
   264  	eng := NewPGPVerify(p.tcR.G, arg)
   265  	if err := RunEngine2(ctx, eng); err != nil {
   266  		p.t.Fatal(err)
   267  	}
   268  	return p.idc(ctx), p.sigc(ctx)
   269  }
   270  
   271  func (p *pgpPair) verifySelf(msg string) (int, int) {
   272  	ctx := decengctx(p.sender, p.tcS)
   273  	arg := &PGPVerifyArg{
   274  		Source: strings.NewReader(msg),
   275  	}
   276  	eng := NewPGPVerify(p.tcS.G, arg)
   277  	if err := RunEngine2(ctx, eng); err != nil {
   278  		p.t.Fatal(err)
   279  	}
   280  	return p.idc(ctx), p.sigc(ctx)
   281  }
   282  
   283  func (p *pgpPair) verifyAssertSignedBySelf(msg string) (int, int) {
   284  	ctx := decengctx(p.sender, p.tcS)
   285  	arg := &PGPVerifyArg{
   286  		Source:   strings.NewReader(msg),
   287  		SignedBy: p.sender.Username,
   288  	}
   289  	eng := NewPGPVerify(p.tcS.G, arg)
   290  	if err := RunEngine2(ctx, eng); err != nil {
   291  		p.t.Fatal(err)
   292  	}
   293  	return p.idc(ctx), p.sigc(ctx)
   294  }
   295  
   296  func (p *pgpPair) idc(m libkb.MetaContext) int {
   297  	ui, ok := m.UIs().IdentifyUI.(*FakeIdentifyUI)
   298  	if !ok {
   299  		p.t.Fatalf("not FakeIdentifyUI: %T", m.UIs().IdentifyUI)
   300  	}
   301  	p.t.Logf("FakeIdentifyUI: %+v", ui)
   302  	return ui.StartCount
   303  }
   304  
   305  func (p *pgpPair) sigc(m libkb.MetaContext) int {
   306  	ui, ok := m.UIs().PgpUI.(*TestPgpUI)
   307  	if !ok {
   308  		p.t.Fatalf("not TestPgpUI: %T", m.UIs().PgpUI)
   309  	}
   310  	return ui.OutputCount
   311  }