func (k *KeybaseDaemonRPC) filterKeys(ctx context.Context, uid keybase1.UID, keys []keybase1.PublicKey) ([]VerifyingKey, []CryptPublicKey, error) { var verifyingKeys []VerifyingKey var cryptPublicKeys []CryptPublicKey for _, publicKey := range keys { if len(publicKey.PGPFingerprint) > 0 { continue } // Import the KID to validate it. key, err := libkb.ImportKeypairFromKID(publicKey.KID) if err != nil { return nil, nil, err } if publicKey.IsSibkey { k.log.CDebugf( ctx, "got verifying key %s for user %s", key.VerboseDescription(), uid) verifyingKeys = append( verifyingKeys, MakeVerifyingKey(key.GetKID())) } else { k.log.CDebugf( ctx, "got crypt public key %s for user %s", key.VerboseDescription(), uid) cryptPublicKeys = append( cryptPublicKeys, MakeCryptPublicKey(key.GetKID())) } } return verifyingKeys, cryptPublicKeys, nil }
// checkReverseSig verifies that the reverse sig in jw is valid // and matches jw. func (e *Kex2Provisioner) checkReverseSig(jw *jsonw.Wrapper) error { kid, err := jw.AtPath("body.sibkey.kid").GetString() if err != nil { return err } keypair, err := libkb.ImportKeypairFromKID(keybase1.KIDFromString(kid)) if err != nil { return err } revsig, err := jw.AtPath("body.sibkey.reverse_sig").GetString() if err != nil { return err } // set reverse_sig to nil to verify it: jw.SetValueAtPath("body.sibkey.reverse_sig", jsonw.NewNil()) msg, err := jw.Marshal() if err != nil { return err } _, err = keypair.VerifyString(revsig, msg) if err != nil { return err } // put reverse_sig back in jw.SetValueAtPath("body.sibkey.reverse_sig", jsonw.NewString(revsig)) return nil }
// EncryptTLFCryptKeyClientHalf implements the Crypto interface for // CryptoCommon. func (c *CryptoCommon) EncryptTLFCryptKeyClientHalf(privateKey TLFEphemeralPrivateKey, publicKey CryptPublicKey, clientHalf TLFCryptKeyClientHalf) (encryptedClientHalf EncryptedTLFCryptKeyClientHalf, err error) { var nonce [24]byte err = cryptoRandRead(nonce[:]) if err != nil { return } keypair, err := libkb.ImportKeypairFromKID(publicKey.kid) if err != nil { return } dhKeyPair, ok := keypair.(libkb.NaclDHKeyPair) if !ok { err = libkb.KeyCannotEncryptError{} return } encryptedData := box.Seal(nil, clientHalf.data[:], &nonce, (*[32]byte)(&dhKeyPair.Public), (*[32]byte)(&privateKey.data)) encryptedClientHalf = EncryptedTLFCryptKeyClientHalf{ Version: EncryptionSecretbox, Nonce: nonce[:], EncryptedData: encryptedData, } return }
// CurrentSession implements the KeybaseDaemon interface for KeybaseDaemonRPC. func (k *KeybaseDaemonRPC) CurrentSession(ctx context.Context, sessionID int) ( SessionInfo, error) { cachedCurrentSession := k.getCachedCurrentSession() if cachedCurrentSession != (SessionInfo{}) { return cachedCurrentSession, nil } res, err := k.sessionClient.CurrentSession(ctx, sessionID) if err != nil { if ncs := (NoCurrentSessionError{}); err.Error() == NoCurrentSessionExpectedError { // Use an error with a proper OS error code attached to // it. TODO: move ErrNoSession from client/go/service to // client/go/libkb, so we can use types for the check // above. err = ncs } return SessionInfo{}, err } // Import the KIDs to validate them. deviceSubkey, err := libkb.ImportKeypairFromKID(res.DeviceSubkeyKid) if err != nil { return SessionInfo{}, err } deviceSibkey, err := libkb.ImportKeypairFromKID(res.DeviceSibkeyKid) if err != nil { return SessionInfo{}, err } cryptPublicKey := MakeCryptPublicKey(deviceSubkey.GetKID()) verifyingKey := MakeVerifyingKey(deviceSibkey.GetKID()) s := SessionInfo{ Name: libkb.NewNormalizedUsername(res.Username), UID: keybase1.UID(res.Uid), Token: res.Token, CryptPublicKey: cryptPublicKey, VerifyingKey: verifyingKey, } k.log.CDebugf( ctx, "new session with username %s, uid %s, crypt public key %s, and verifying key %s", s.Name, s.UID, s.CryptPublicKey, s.VerifyingKey) k.setCachedCurrentSession(s) return s, nil }
// Test that decrypting an TLF crypt key client half encrypted with // box.Seal works. func TestCryptoClientDecryptTLFCryptKeyClientHalfBoxSeal(t *testing.T) { signingKey := MakeFakeSigningKeyOrBust("client sign") cryptPrivateKey := MakeFakeCryptPrivateKeyOrBust("client crypt private") config := testCryptoClientConfig(t) fc := NewFakeCryptoClient(config, signingKey, cryptPrivateKey, nil, nil) c := newCryptoClientWithClient(config, fc) _, _, ephPublicKey, ephPrivateKey, cryptKey, err := c.MakeRandomTLFKeys() if err != nil { t.Fatal(err) } serverHalf, err := c.MakeRandomTLFCryptKeyServerHalf() if err != nil { t.Fatal(err) } clientHalf, err := c.MaskTLFCryptKey(serverHalf, cryptKey) if err != nil { t.Fatal(err) } var nonce [24]byte err = cryptoRandRead(nonce[:]) if err != nil { t.Fatal(err) } keypair, err := libkb.ImportKeypairFromKID(cryptPrivateKey.getPublicKey().kid) if err != nil { t.Fatal(err) } dhKeyPair, ok := keypair.(libkb.NaclDHKeyPair) if !ok { t.Fatal(libkb.KeyCannotEncryptError{}) } encryptedData := box.Seal(nil, clientHalf.data[:], &nonce, (*[32]byte)(&dhKeyPair.Public), (*[32]byte)(&ephPrivateKey.data)) encryptedClientHalf := EncryptedTLFCryptKeyClientHalf{ Version: EncryptionSecretbox, Nonce: nonce[:], EncryptedData: encryptedData, } decryptedClientHalf, err := c.DecryptTLFCryptKeyClientHalf( context.Background(), ephPublicKey, encryptedClientHalf) if err != nil { t.Fatal(err) } if clientHalf != decryptedClientHalf { t.Error("clientHalf != decryptedClientHalf") } }
// CurrentSession implements the KeybaseDaemon interface for KeybaseDaemonRPC. func (k *KeybaseDaemonRPC) CurrentSession(ctx context.Context, sessionID int) ( SessionInfo, error) { cachedCurrentSession := k.getCachedCurrentSession() if cachedCurrentSession != (SessionInfo{}) { return cachedCurrentSession, nil } res, err := k.sessionClient.CurrentSession(ctx, sessionID) if err != nil { if ncs := (NoCurrentSessionError{}); err.Error() == ncs.Error() { // Use an error with a proper OS error code attached to it. err = ncs } return SessionInfo{}, err } // Import the KIDs to validate them. deviceSubkey, err := libkb.ImportKeypairFromKID(res.DeviceSubkeyKid) if err != nil { return SessionInfo{}, err } deviceSibkey, err := libkb.ImportKeypairFromKID(res.DeviceSibkeyKid) if err != nil { return SessionInfo{}, err } cryptPublicKey := MakeCryptPublicKey(deviceSubkey.GetKID()) verifyingKey := MakeVerifyingKey(deviceSibkey.GetKID()) s := SessionInfo{ UID: keybase1.UID(res.Uid), Token: res.Token, CryptPublicKey: cryptPublicKey, VerifyingKey: verifyingKey, } k.log.CDebugf( ctx, "new session with uid %s, crypt public key %s, and verifying key %s", s.UID, s.CryptPublicKey, s.VerifyingKey) k.setCachedCurrentSession(s) return s, nil }
// processKey adds the given public key to the appropriate verifying // or crypt list (as return values), and also updates the given name // map in place. func processKey(publicKey keybase1.PublicKey, addVerifyingKey addVerifyingKeyFunc, addCryptPublicKey addCryptPublicKeyFunc, kidNames map[keybase1.KID]string) error { if len(publicKey.PGPFingerprint) > 0 { return nil } // Import the KID to validate it. key, err := libkb.ImportKeypairFromKID(publicKey.KID) if err != nil { return err } if publicKey.IsSibkey { addVerifyingKey(MakeVerifyingKey(key.GetKID())) } else { addCryptPublicKey(MakeCryptPublicKey(key.GetKID())) } if publicKey.DeviceDescription != "" { kidNames[publicKey.KID] = publicKey.DeviceDescription } return nil }
// Run starts the engine. func (e *SaltpackEncrypt) Run(ctx *Context) (err error) { e.G().Log.Debug("+ SaltpackEncrypt::Run") defer func() { e.G().Log.Debug("- SaltpackEncrypt::Run -> %v", err) }() var receivers []libkb.NaclDHKeyPublic var sender libkb.NaclDHKeyPair if err = e.loadMe(ctx); err != nil { return err } if !e.arg.Opts.NoSelfEncrypt && e.me != nil { receivers, err = e.loadMyPublicKeys() if err != nil { return err } } kfarg := DeviceKeyfinderArg{ Users: e.arg.Opts.Recipients, NeedEncryptKeys: true, Self: e.me, } kf := NewDeviceKeyfinder(e.G(), kfarg) if err := RunEngine(kf, ctx); err != nil { return err } uplus := kf.UsersPlusKeys() for _, up := range uplus { for _, k := range up.DeviceKeys { gk, err := libkb.ImportKeypairFromKID(k.KID) if err != nil { return err } kp, ok := gk.(libkb.NaclDHKeyPair) if !ok { return libkb.KeyCannotEncryptError{} } receivers = append(receivers, kp.Public) } } if !e.arg.Opts.HideSelf && e.me != nil { ska := libkb.SecretKeyArg{ Me: e.me, KeyType: libkb.DeviceEncryptionKeyType, } key, err := e.G().Keyrings.GetSecretKeyWithPrompt(ctx.SecretKeyPromptArg(ska, "encrypting a message/file")) if err != nil { return err } kp, ok := key.(libkb.NaclDHKeyPair) if !ok || kp.Private == nil { return libkb.KeyCannotDecryptError{} } sender = kp } encarg := libkb.SaltpackEncryptArg{ Source: e.arg.Source, Sink: e.arg.Sink, Receivers: receivers, Sender: sender, Binary: e.arg.Opts.Binary, HideRecipients: e.arg.Opts.HideRecipients, } return libkb.SaltpackEncrypt(e.G(), &encarg) }
func (k *KexProvisioner) handlePleaseSign(ctx *Context, m *kex.Msg) error { eddsa := m.Args().SigningKey sig := m.Args().Sig keypair := libkb.NaclSigningKeyPair{Public: eddsa} sigPayload, _, err := keypair.VerifyStringAndExtract(sig) if err != nil { return err } k.G().Log.Debug("Got PleaseSign() on verified JSON blob %s\n", string(sigPayload)) // k.deviceSibkey is public only if k.sigKey == nil { var err error arg := libkb.SecretKeyArg{ Me: k.user, KeyType: libkb.DeviceSigningKeyType, } k.sigKey, err = k.G().Keyrings.GetSecretKeyWithPrompt(nil, arg, k.engctx.SecretUI, "new device install") if err != nil { return err } } jw, err := jsonw.Unmarshal(sigPayload) if err != nil { return err } var newKID keybase1.KID var newKey libkb.GenericKey if newKID, err = libkb.GetKID(jw.AtPath("body.sibkey.kid")); err != nil { return err } if newKey, err = libkb.ImportKeypairFromKID(newKID); err != nil { return err } if err = k.verifyPleaseSign(jw, newKID); err != nil { return err } if err = jw.SetValueAtPath("body.sibkey.reverse_sig", jsonw.NewString(sig)); err != nil { return err } del := libkb.Delegator{ NewKey: newKey, ExistingKey: k.sigKey, Me: k.user, Expire: libkb.NaclEdDSAExpireIn, DelegationType: libkb.SibkeyType, EldestKID: k.user.GetEldestKID(), Contextified: libkb.NewContextified(k.G()), } if err = del.CheckArgs(); err != nil { return err } if err = del.SignAndPost(ctx.LoginContext, jw); err != nil { return err } return nil }
func (k *KexNewDevice) handleHello(ctx *Context, m *kex.Msg) (err error) { k.xDevKey, err = libkb.ImportKeypairFromKID(m.Args().DevKeyID) return }