github.com/keybase/client/go@v0.0.0-20240309051027-028f7c731f8b/libkb/saltpack_verify.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 "io" 9 10 "github.com/keybase/client/go/kbcrypto" 11 "github.com/keybase/client/go/logger" 12 "github.com/keybase/saltpack" 13 ) 14 15 // SaltpackVerifyContext is context for engine calls 16 type SaltpackVerifyContext interface { 17 GetLog() logger.Logger 18 } 19 20 // Wraps kbcrypto.Verification error with libkb.VerificationError. You should 21 // expect a libkb.VerificationError if exposing the error to the GUI. 22 func getVerificationErrorWithStatusCode(kberr *kbcrypto.VerificationError) (err VerificationError) { 23 err.Cause.Err = kberr.Cause 24 switch err.Cause.Err.(type) { 25 case APINetError: 26 err.Cause.StatusCode = SCAPINetworkError 27 case saltpack.ErrNoSenderKey: 28 err.Cause.StatusCode = SCDecryptionKeyNotFound 29 case saltpack.ErrWrongMessageType: 30 err.Cause.StatusCode = SCWrongCryptoMsgType 31 } 32 return err 33 } 34 35 func SaltpackVerify(g SaltpackVerifyContext, source io.Reader, sink io.WriteCloser, checkSender func(saltpack.SigningPublicKey) error) (err error) { 36 defer func() { 37 if kbErr, ok := err.(kbcrypto.VerificationError); ok { 38 err = getVerificationErrorWithStatusCode(&kbErr) 39 } 40 }() 41 42 sc, newSource, err := ClassifyStream(source) 43 if err != nil { 44 return err 45 } 46 if sc.Format != CryptoMessageFormatSaltpack { 47 return WrongCryptoFormatError{ 48 Wanted: CryptoMessageFormatSaltpack, 49 Received: sc.Format, 50 Operation: "verify", 51 } 52 } 53 54 if sc.Type != CryptoMessageTypeAttachedSignature { 55 return kbcrypto.NewVerificationError( 56 saltpack.ErrWrongMessageType{ 57 Wanted: saltpack.MessageType(CryptoMessageTypeAttachedSignature), 58 Received: saltpack.MessageType(sc.Type), 59 }) 60 } 61 62 source = newSource 63 kr := echoKeyring{} 64 65 var skey saltpack.SigningPublicKey 66 var vs io.Reader 67 var brand string 68 if sc.Armored { 69 skey, vs, brand, err = saltpack.NewDearmor62VerifyStream(saltpack.CheckKnownMajorVersion, source, kr) 70 } else { 71 skey, vs, err = saltpack.NewVerifyStream(saltpack.CheckKnownMajorVersion, source, kr) 72 } 73 if err != nil { 74 g.GetLog().Debug("saltpack.NewDearmor62VerifyStream error: %s", err) 75 return kbcrypto.NewVerificationError(err) 76 } 77 78 if checkSender != nil { 79 if err = checkSender(skey); err != nil { 80 return kbcrypto.NewVerificationError(err) 81 } 82 } 83 84 n, err := io.Copy(sink, vs) 85 if err != nil { 86 return kbcrypto.NewVerificationError(err) 87 } 88 89 if sc.Armored { 90 if err = checkSaltpackBrand(brand); err != nil { 91 return kbcrypto.NewVerificationError(err) 92 } 93 } 94 95 g.GetLog().Debug("Verify: read %d bytes", n) 96 97 if err := sink.Close(); err != nil { 98 return kbcrypto.NewVerificationError(err) 99 } 100 return nil 101 } 102 103 func SaltpackVerifyDetached(g SaltpackVerifyContext, message io.Reader, signature []byte, checkSender func(saltpack.SigningPublicKey) error) (err error) { 104 defer func() { 105 if kbErr, ok := err.(kbcrypto.VerificationError); ok { 106 err = getVerificationErrorWithStatusCode(&kbErr) 107 } 108 }() 109 110 sc, _, err := ClassifyStream(bytes.NewReader(signature)) 111 if err != nil { 112 return err 113 } 114 if sc.Format != CryptoMessageFormatSaltpack { 115 return WrongCryptoFormatError{ 116 Wanted: CryptoMessageFormatSaltpack, 117 Received: sc.Format, 118 Operation: "verify detached", 119 } 120 } 121 122 kr := echoKeyring{} 123 124 var skey saltpack.SigningPublicKey 125 if sc.Armored { 126 var brand string 127 skey, brand, err = saltpack.Dearmor62VerifyDetachedReader(saltpack.CheckKnownMajorVersion, message, string(signature), kr) 128 if err != nil { 129 g.GetLog().Debug("saltpack.Dearmor62VerifyDetachedReader error: %s", err) 130 return kbcrypto.NewVerificationError(err) 131 } 132 if err = checkSaltpackBrand(brand); err != nil { 133 return kbcrypto.NewVerificationError(err) 134 } 135 } else { 136 skey, err = saltpack.VerifyDetachedReader(saltpack.CheckKnownMajorVersion, message, signature, kr) 137 if err != nil { 138 g.GetLog().Debug("saltpack.VerifyDetachedReader error: %s", err) 139 return kbcrypto.NewVerificationError(err) 140 } 141 } 142 143 if checkSender != nil { 144 if err = checkSender(skey); err != nil { 145 return kbcrypto.NewVerificationError(err) 146 } 147 } 148 149 return nil 150 } 151 152 type echoKeyring struct { 153 Contextified 154 } 155 156 func (e echoKeyring) LookupSigningPublicKey(kid []byte) saltpack.SigningPublicKey { 157 var k kbcrypto.NaclSigningKeyPublic 158 copy(k[:], kid) 159 return saltSignerPublic{key: k} 160 }