github.com/keybase/client/go@v0.0.0-20240520164431-4f512a4c85a3/libkb/saltpack_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 libkb 5 6 import ( 7 "bytes" 8 "strings" 9 "testing" 10 11 "github.com/keybase/saltpack" 12 saltpackBasic "github.com/keybase/saltpack/basic" 13 "github.com/stretchr/testify/require" 14 15 "github.com/keybase/client/go/saltpackkeystest" 16 ) 17 18 type outputBuffer struct { 19 bytes.Buffer 20 } 21 22 func (ob outputBuffer) Close() error { 23 return nil 24 } 25 26 // Encrypt a message, and make sure recipients can decode it, and 27 // non-recipients can't decode it. 28 func TestSaltpackEncDec(t *testing.T) { 29 tc := SetupTest(t, "TestSaltpackEncDec", 1) 30 defer tc.Cleanup() 31 32 m := NewMetaContextForTest(tc) 33 34 senderKP, err := GenerateNaclDHKeyPair() 35 if err != nil { 36 t.Fatal(err) 37 } 38 39 senderSigningKP, err := GenerateNaclSigningKeyPair() 40 if err != nil { 41 t.Fatal(err) 42 } 43 44 var receiverKPs []NaclDHKeyPair 45 var receiverPKs []NaclDHKeyPublic 46 for i := 0; i < 12; i++ { 47 kp, err := GenerateNaclDHKeyPair() 48 if err != nil { 49 t.Fatal(err) 50 } 51 receiverKPs = append(receiverKPs, kp) 52 receiverPKs = append(receiverPKs, kp.Public) 53 } 54 55 nonReceiverKP, err := GenerateNaclDHKeyPair() 56 if err != nil { 57 t.Fatal(err) 58 } 59 60 message := "The Magic Words are Squeamish Ossifrage" 61 62 var buf outputBuffer 63 64 arg := SaltpackEncryptArg{ 65 Source: strings.NewReader(message), 66 Sink: &buf, 67 Receivers: receiverPKs, 68 Sender: senderKP, 69 SenderSigning: senderSigningKP, 70 } 71 if err := SaltpackEncrypt(m, &arg); err != nil { 72 t.Fatal(err) 73 } 74 75 ciphertext := buf.String() 76 if !strings.HasPrefix(ciphertext, saltpack.MakeArmorHeader(saltpack.MessageTypeEncryption, KeybaseSaltpackBrand)) { 77 t.Errorf("ciphertext doesn't have header: %s", ciphertext) 78 } 79 80 if !strings.HasSuffix(ciphertext, saltpack.MakeArmorFooter(saltpack.MessageTypeEncryption, KeybaseSaltpackBrand)+".\n") { 81 t.Errorf("ciphertext doesn't have footer: %s", ciphertext) 82 } 83 84 for _, key := range receiverKPs { 85 buf.Reset() 86 87 // Create a keyring with only one key 88 keyring := saltpackBasic.NewKeyring() 89 keyring.ImportBoxKey((*[NaclDHKeysize]byte)(&key.Public), (*[NaclDHKeysize]byte)(key.Private)) 90 91 _, err = SaltpackDecrypt(m, 92 strings.NewReader(ciphertext), 93 &buf, keyring, nil, nil, saltpackkeystest.NewMockPseudonymResolver(t)) 94 if err != nil { 95 t.Fatal(err) 96 } 97 98 plaintext := buf.String() 99 if plaintext != message { 100 t.Errorf("expected %s, got %s", 101 message, plaintext) 102 } 103 } 104 105 // Sender is a non-recipient, too. 106 nonReceiverKPs := []NaclDHKeyPair{nonReceiverKP, senderKP} 107 108 for _, key := range nonReceiverKPs { 109 buf.Reset() 110 111 // Create a keyring with only one key 112 keyring := saltpackBasic.NewKeyring() 113 keyring.ImportBoxKey((*[NaclDHKeysize]byte)(&key.Public), (*[NaclDHKeysize]byte)(key.Private)) 114 115 _, err = SaltpackDecrypt(m, 116 strings.NewReader(ciphertext), &buf, keyring, nil, nil, saltpackkeystest.NewMockPseudonymResolver(t)) 117 // An unauthorized receiver trying to decrypt should receive an error 118 decError := err.(DecryptionError) 119 require.Equal(t, decError.Cause.Err, saltpack.ErrNoDecryptionKey) 120 } 121 }