Beispiel #1
0
func TestKeys(t *testing.T) {
	var cpriv, cpub, cpub2 [32]byte
	pub, priv, err := ed25519.GenerateKey(rand.Reader)
	if assert.NoError(t, err) {
		assert.True(t, extra25519.PublicKeyToCurve25519(&cpub, pub), "Calling PublicKeyToCurve25519 failed")
		extra25519.PrivateKeyToCurve25519(&cpriv, priv)
		curve25519.ScalarBaseMult(&cpub2, &cpriv)
		assert.Equal(t, cpub, cpub2)
	}
}
Beispiel #2
0
// loadOrGenerateKeys reads the master signing key from the global
// state in DB, (generating one if it's not already there), and
// generates the boxing keys based on it.
//
// This is meant to be called exactly once at startup time.
func loadOrGenerateKeys(db *bolt.DB) (*CryptoKeys, error) {
	var k CryptoKeys

	getKey := func(tx *bolt.Tx) error {
		bucket := tx.Bucket([]byte(tokens.BucketBazil))
		val := bucket.Get([]byte(tokens.GlobalStateKey))
		if val == nil {
			// have not generated a key yet
			return nil
		}
		if len(val) != ed25519.PrivateKeySize {
			return fmt.Errorf("master key wrong is the wrong size: length=%d", len(val))
		}
		var sigPriv [ed25519.PrivateKeySize]byte
		copy(sigPriv[:], val)
		k.Sign.Priv = &sigPriv
		return nil
	}
	if err := db.View(getKey); err != nil {
		return nil, err
	}

	if k.Sign.Priv == nil {
		// did not load keys from database
		var err error
		_, signPriv, err := ed25519.GenerateKey(rand.Reader)
		if err != nil {
			return nil, err
		}
		k.Sign.Priv = signPriv

		// save it for future runs
		putKey := func(tx *bolt.Tx) error {
			bucket := tx.Bucket([]byte(tokens.BucketBazil))
			return bucket.Put([]byte(tokens.GlobalStateKey), signPriv[:])
		}
		if err := db.Update(putKey); err != nil {
			return nil, err
		}
	}

	k.Sign.Pub = extractEd25519Pubkey(k.Sign.Priv)

	// generate other keys from it
	k.Box.Priv = &[32]byte{}
	extra25519.PrivateKeyToCurve25519(k.Box.Priv, k.Sign.Priv)
	k.Box.Pub = &[32]byte{}
	extra25519.PublicKeyToCurve25519(k.Box.Pub, k.Sign.Pub)
	return &k, nil
}
Beispiel #3
0
func (c *client) loadUI() error {
	c.ui.initUI()

	c.torAddress = "127.0.0.1:9050" // default for dev mode.
	if !c.dev && !c.detectTor() {
		if err := c.ui.torPromptUI(); err != nil {
			return err
		}
	}

	c.ui.loadingUI()

	stateFile := &disk.StateFile{
		Path: c.stateFilename,
		Rand: c.rand,
		Log: func(format string, args ...interface{}) {
			c.log.Printf(format, args...)
		},
	}

	var newAccount bool
	var err error
	if c.stateLock, err = stateFile.Lock(false /* don't create */); err == nil && c.stateLock == nil {
		c.ui.errorUI("State file locked by another process. Waiting for lock.", false)
		c.log.Errorf("Waiting for locked state file")

		for {
			if c.stateLock, err = stateFile.Lock(false /* don't create */); c.stateLock != nil {
				break
			}
			if err := c.ui.sleepUI(1 * time.Second); err != nil {
				return err
			}
		}
	} else if err == nil {
	} else if os.IsNotExist(err) {
		newAccount = true
	} else {
		c.ui.errorUI(err.Error(), true)
		if err := c.ui.ShutdownAndSuspend(); err != nil {
			return err
		}
	}

	if newAccount {
		pub, priv, err := ed25519.GenerateKey(rand.Reader)
		if err != nil {
			panic(err)
		}
		copy(c.priv[:], priv[:])
		copy(c.pub[:], pub[:])

		if c.disableV2Ratchet {
			c.randBytes(c.identity[:])
		} else {
			extra25519.PrivateKeyToCurve25519(&c.identity, priv)
		}
		curve25519.ScalarBaseMult(&c.identityPublic, &c.identity)

		c.groupPriv, err = bbssig.GenerateGroup(rand.Reader)
		if err != nil {
			panic(err)
		}
		pw, err := c.ui.createPassphraseUI()
		if err != nil {
			return err
		}
		c.ui.createErasureStorage(pw, stateFile)
		if err := c.ui.createAccountUI(); err != nil {
			return err
		}
		newAccount = true
	} else {
		// First try with zero key.
		err := c.loadState(stateFile, "")
		for err == disk.BadPasswordError {
			// That didn't work, try prompting for a key.
			err = c.ui.keyPromptUI(stateFile)
		}
		if err == errInterrupted {
			return err
		}
		if err != nil {
			// Fatal error loading state. Abort.
			c.ui.errorUI(err.Error(), true)
			if err := c.ui.ShutdownAndSuspend(); err != nil {
				return err
			}
		}
	}

	if newAccount {
		c.stateLock, err = stateFile.Lock(true /* create */)
		if err != nil {
			err = errors.New("Failed to create state file: " + err.Error())
		} else if c.stateLock == nil {
			err = errors.New("Failed to obtain lock on created state file")
		}
		if err != nil {
			c.ui.errorUI(err.Error(), true)
			if err := c.ui.ShutdownAndSuspend(); err != nil {
				return err
			}
		}
		c.lastErasureStorageTime = time.Now()
	}

	c.writerChan = make(chan disk.NewState)
	c.writerDone = make(chan struct{})
	c.fetchNowChan = make(chan chan bool, 1)

	// Start disk and network workers.
	go stateFile.StartWriter(c.writerChan, c.writerDone)
	go c.transact()
	if newAccount {
		c.save()
	}

	// Start any pending key exchanges.
	for _, contact := range c.contacts {
		if len(contact.pandaKeyExchange) == 0 {
			continue
		}
		c.pandaWaitGroup.Add(1)
		contact.pandaShutdownChan = make(chan struct{})
		go c.runPANDA(contact.pandaKeyExchange, contact.id, contact.name, contact.pandaShutdownChan)
	}

	c.ui.mainUI()

	return nil
}