Example #1
0
// DecryptTLFCryptKeyClientHalf implements the Crypto interface for
// CryptoClient.
func (c *CryptoClient) DecryptTLFCryptKeyClientHalf(ctx context.Context,
	publicKey TLFEphemeralPublicKey,
	encryptedClientHalf EncryptedTLFCryptKeyClientHalf) (
	clientHalf TLFCryptKeyClientHalf, err error) {
	c.log.CDebugf(ctx, "Decrypting TLF client key half")
	defer func() {
		c.deferLog.CDebugf(ctx, "Decrypted TLF client key half: %v", err)
	}()
	encryptedData, nonce, err := c.prepareTLFCryptKeyClientHalf(encryptedClientHalf)
	if err != nil {
		return
	}

	timer := c.logAboutLongRPCUnlessCancelled(ctx, "UnboxBytes32")
	defer timer.Stop()
	decryptedClientHalf, err := c.client.UnboxBytes32(ctx, keybase1.UnboxBytes32Arg{
		EncryptedBytes32: encryptedData,
		Nonce:            nonce,
		PeersPublicKey:   keybase1.BoxPublicKey(publicKey.data),
		Reason:           "to use kbfs",
	})
	if err != nil {
		return
	}

	clientHalf = MakeTLFCryptKeyClientHalf(decryptedClientHalf)
	return
}
Example #2
0
// Test that CryptoHandler.UnboxBytes32() decrypts a boxed 32-byte
// array correctly.
func TestCryptoUnboxBytes32(t *testing.T) {
	tc := SetupEngineTest(t, "crypto")
	defer tc.Cleanup()

	u := CreateAndSignupFakeUser(tc, "fu")
	secretUI := &libkb.TestSecretUI{Passphrase: u.Passphrase}

	key, err := getMySecretKey(
		tc.G, secretUI, libkb.DeviceEncryptionKeyType, "test")
	if err != nil {
		t.Fatal(err)
	}
	kp, ok := key.(libkb.NaclDHKeyPair)
	if !ok || kp.Private == nil {
		t.Fatalf("unexpected key %v", key)
	}

	peerKp, err := libkb.GenerateNaclDHKeyPair()
	if err != nil {
		t.Fatal(err)
	}

	expectedBytes32 := keybase1.Bytes32{0, 1, 2, 3, 4, 5}
	nonce := [24]byte{6, 7, 8, 9, 10}
	peersPublicKey := keybase1.BoxPublicKey(peerKp.Public)

	encryptedData := box.Seal(nil, expectedBytes32[:], &nonce, (*[32]byte)(&kp.Public), (*[32]byte)(peerKp.Private))

	var encryptedBytes32 keybase1.EncryptedBytes32
	if len(encryptedBytes32) != len(encryptedData) {
		t.Fatalf("Expected %d bytes, got %d", len(encryptedBytes32), len(encryptedData))
	}

	copy(encryptedBytes32[:], encryptedData)

	bytes32, err := UnboxBytes32(tc.G, secretUI, keybase1.UnboxBytes32Arg{
		EncryptedBytes32: encryptedBytes32,
		Nonce:            nonce,
		PeersPublicKey:   peersPublicKey,
	})

	if err != nil {
		t.Fatal(err)
	}

	if bytes32 != expectedBytes32 {
		t.Errorf("expected %s, got %s", expectedBytes32, bytes32)
	}
}
Example #3
0
// DecryptTLFCryptKeyClientHalfAny implements the Crypto interface for
// CryptoClient.
func (c *CryptoClient) DecryptTLFCryptKeyClientHalfAny(ctx context.Context,
	keys []EncryptedTLFCryptKeyClientAndEphemeral, promptPaper bool) (
	clientHalf TLFCryptKeyClientHalf, index int, err error) {
	c.log.CDebugf(ctx, "Decrypting TLF client key half with any key")
	defer func() {
		c.deferLog.CDebugf(ctx, "Decrypted TLF client key half with any key: %v",
			err)
	}()
	if len(keys) == 0 {
		return clientHalf, index, NoKeysError{}
	}
	bundles := make([]keybase1.CiphertextBundle, 0, len(keys))
	errors := make([]error, 0, len(keys))
	indexLookup := make([]int, 0, len(keys))
	for i, k := range keys {
		encryptedData, nonce, err := c.prepareTLFCryptKeyClientHalf(k.ClientHalf)
		if err != nil {
			errors = append(errors, err)
		} else {
			bundles = append(bundles, keybase1.CiphertextBundle{
				Kid:        k.PubKey.kidContainer.kid,
				Ciphertext: encryptedData,
				Nonce:      nonce,
				PublicKey:  keybase1.BoxPublicKey(k.EPubKey.data),
			})
			indexLookup = append(indexLookup, i)
		}
	}
	if len(bundles) == 0 {
		err = errors[0]
		return
	}
	timer := c.logAboutLongRPCUnlessCancelled(ctx, "UnboxBytes32Any")
	defer timer.Stop()
	res, err := c.client.UnboxBytes32Any(ctx, keybase1.UnboxBytes32AnyArg{
		Bundles:     bundles,
		Reason:      "to rekey for kbfs",
		PromptPaper: promptPaper,
	})
	if err != nil {
		return
	}
	return MakeTLFCryptKeyClientHalf(res.Plaintext), indexLookup[res.Index], nil
}
Example #4
0
// DecryptTLFCryptKeyClientHalf implements the Crypto interface for
// CryptoClient.
func (c *CryptoClient) DecryptTLFCryptKeyClientHalf(ctx context.Context,
	publicKey TLFEphemeralPublicKey,
	encryptedClientHalf EncryptedTLFCryptKeyClientHalf) (
	clientHalf TLFCryptKeyClientHalf, err error) {
	encryptedData, nonce, err := c.prepareTLFCryptKeyClientHalf(encryptedClientHalf)
	if err != nil {
		return
	}

	decryptedClientHalf, err := c.client.UnboxBytes32(ctx, keybase1.UnboxBytes32Arg{
		EncryptedBytes32: encryptedData,
		Nonce:            nonce,
		PeersPublicKey:   keybase1.BoxPublicKey(publicKey.data),
		Reason:           "to use kbfs",
	})
	if err != nil {
		return
	}

	clientHalf = MakeTLFCryptKeyClientHalf(decryptedClientHalf)
	return
}
Example #5
0
// DecryptTLFCryptKeyClientHalfAny implements the Crypto interface for
// CryptoClient.
func (c *CryptoClient) DecryptTLFCryptKeyClientHalfAny(ctx context.Context,
	keys []EncryptedTLFCryptKeyClientAndEphemeral) (
	clientHalf TLFCryptKeyClientHalf, index int, err error) {
	if len(keys) == 0 {
		return clientHalf, index, NoKeysError{}
	}
	bundles := make([]keybase1.CiphertextBundle, 0, len(keys))
	errors := make([]error, 0, len(keys))
	indexLookup := make([]int, 0, len(keys))
	for i, k := range keys {
		encryptedData, nonce, err := c.prepareTLFCryptKeyClientHalf(k.ClientHalf)
		if err != nil {
			errors = append(errors, err)
		} else {
			bundles = append(bundles, keybase1.CiphertextBundle{
				Kid:        k.PubKey.kidContainer.kid,
				Ciphertext: encryptedData,
				Nonce:      nonce,
				PublicKey:  keybase1.BoxPublicKey(k.EPubKey.data),
			})
			indexLookup = append(indexLookup, i)
		}
	}
	if len(bundles) == 0 {
		err = errors[0]
		return
	}
	res, err := c.client.UnboxBytes32Any(ctx, keybase1.UnboxBytes32AnyArg{
		Bundles: bundles,
		Reason:  "to rekey for kbfs",
	})
	if err != nil {
		return
	}
	return MakeTLFCryptKeyClientHalf(res.Plaintext), indexLookup[res.Index], nil
}
Example #6
0
func TestCryptoUnboxBytes32AnyPaper(t *testing.T) {
	tc := SetupEngineTest(t, "crypto")
	defer tc.Cleanup()

	u := CreateAndSignupFakeUser(tc, "fu")

	// create a paper key and cache it
	ctx := &Context{
		LogUI:    tc.G.UI.GetLogUI(),
		LoginUI:  &libkb.TestLoginUI{},
		SecretUI: u.NewSecretUI(),
	}
	peng := NewPaperKey(tc.G)
	if err := RunEngine(peng, ctx); err != nil {
		t.Fatal(err)
	}
	err := tc.G.LoginState().Account(func(a *libkb.Account) {
		a.SetUnlockedPaperKey(peng.SigKey(), peng.EncKey())
	}, "TestCryptoUnboxBytes32AnyPaper")

	key := peng.EncKey()
	kp, ok := key.(libkb.NaclDHKeyPair)
	if !ok {
		t.Fatalf("paper enc key type: %T, expected libkb.NaclDHKeyPair", key)
	}
	if kp.Private == nil {
		t.Fatalf("paper enc key has nil private key")
	}

	peerKp, err := libkb.GenerateNaclDHKeyPair()
	if err != nil {
		t.Fatal(err)
	}

	expectedBytes32 := keybase1.Bytes32{0, 1, 2, 3, 4, 5}
	nonce := [24]byte{6, 7, 8, 9, 10}
	peersPublicKey := keybase1.BoxPublicKey(peerKp.Public)

	encryptedData := box.Seal(nil, expectedBytes32[:], &nonce, (*[32]byte)(&kp.Public), (*[32]byte)(peerKp.Private))

	var encryptedBytes32 keybase1.EncryptedBytes32
	if len(encryptedBytes32) != len(encryptedData) {
		t.Fatalf("Expected %d bytes, got %d", len(encryptedBytes32), len(encryptedData))
	}

	copy(encryptedBytes32[:], encryptedData)

	_, err = UnboxBytes32(tc.G, u.NewSecretUI(), keybase1.UnboxBytes32Arg{
		EncryptedBytes32: encryptedBytes32,
		Nonce:            nonce,
		PeersPublicKey:   peersPublicKey,
	})

	// this should fail
	if err == nil {
		t.Fatal("UnboxBytes32 worked with paper key encrypted data")
	}
	if _, ok := err.(libkb.DecryptionError); !ok {
		t.Fatalf("error %T, expected libkb.DecryptionError", err)
	}

	// this should work
	arg := keybase1.UnboxBytes32AnyArg{
		Bundles: []keybase1.CiphertextBundle{
			{Kid: kp.GetKID(), Ciphertext: encryptedBytes32, Nonce: nonce},
		},
		PeersPublicKey: peersPublicKey,
	}
	res, err := UnboxBytes32Any(tc.G, u.NewSecretUI(), arg)
	if err != nil {
		t.Fatal(err)
	}
	if res.Plaintext != expectedBytes32 {
		t.Errorf("UnboxBytes32Any plaintext: %x, expected %x", res.Plaintext, expectedBytes32)
	}
	if res.Kid.IsNil() {
		t.Errorf("UnboxBytes32Any kid is nil")
	}

	// clear the paper key cache to test getting a paper key via UI
	err = tc.G.LoginState().Account(func(a *libkb.Account) {
		a.ClearCachedSecretKeys()
	}, "TestCryptoUnboxBytes32AnyPaper")
	if err != nil {
		t.Fatal(err)
	}

	// set the passphrase in the secretUI to the paper key
	secretUI := u.NewSecretUI()
	secretUI.Passphrase = peng.Passphrase()

	res, err = UnboxBytes32Any(tc.G, secretUI, arg)
	if err != nil {
		t.Fatal(err)
	}
	if res.Plaintext != expectedBytes32 {
		t.Errorf("UnboxBytes32Any plaintext: %x, expected %x", res.Plaintext, expectedBytes32)
	}
	if res.Kid.IsNil() {
		t.Errorf("UnboxBytes32Any kid is nil")
	}
}
Example #7
0
// Test that CryptoHandler.UnboxBytes32() decrypts a boxed 32-byte
// array correctly.
func TestCryptoUnboxBytes32(t *testing.T) {
	tc := SetupEngineTest(t, "crypto")
	defer tc.Cleanup()

	u := CreateAndSignupFakeUser(tc, "fu")
	f := func() libkb.SecretUI {
		return &libkb.TestSecretUI{Passphrase: u.Passphrase}
	}

	key, err := getMySecretKey(
		tc.G, f, libkb.DeviceEncryptionKeyType, "test")
	if err != nil {
		t.Fatal(err)
	}
	kp, ok := key.(libkb.NaclDHKeyPair)
	if !ok || kp.Private == nil {
		t.Fatalf("unexpected key %v", key)
	}

	peerKp, err := libkb.GenerateNaclDHKeyPair()
	if err != nil {
		t.Fatal(err)
	}

	expectedBytes32 := keybase1.Bytes32{0, 1, 2, 3, 4, 5}
	nonce := [24]byte{6, 7, 8, 9, 10}
	peersPublicKey := keybase1.BoxPublicKey(peerKp.Public)

	encryptedData := box.Seal(nil, expectedBytes32[:], &nonce, (*[32]byte)(&kp.Public), (*[32]byte)(peerKp.Private))

	var encryptedBytes32 keybase1.EncryptedBytes32
	if len(encryptedBytes32) != len(encryptedData) {
		t.Fatalf("Expected %d bytes, got %d", len(encryptedBytes32), len(encryptedData))
	}

	copy(encryptedBytes32[:], encryptedData)

	bytes32, err := UnboxBytes32(tc.G, f, keybase1.UnboxBytes32Arg{
		EncryptedBytes32: encryptedBytes32,
		Nonce:            nonce,
		PeersPublicKey:   peersPublicKey,
	})

	if err != nil {
		t.Fatal(err)
	}

	if bytes32 != expectedBytes32 {
		t.Errorf("expected %s, got %s", expectedBytes32, bytes32)
	}

	// also test UnboxBytes32Any:
	arg := keybase1.UnboxBytes32AnyArg{
		Bundles: []keybase1.CiphertextBundle{
			{Kid: kp.GetKID(), Ciphertext: encryptedBytes32, Nonce: nonce, PublicKey: peersPublicKey},
		},
	}
	res, err := UnboxBytes32Any(tc.G, f, arg)
	if err != nil {
		t.Fatal(err)
	}
	if res.Plaintext != expectedBytes32 {
		t.Errorf("UnboxBytes32Any plaintext: %x, expected %x", res.Plaintext, expectedBytes32)
	}
	if res.Kid.IsNil() {
		t.Errorf("UnboxBytes32Any kid is nil")
	}
}