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) } }
// 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 }
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 }