// KeyInit returns a new KeyInit message for the given UID message. It also // returns the pubKeyHash and privateKey for convenient further use. // msgcount must increase for each message of the same type and user. // notafter is the unixtime after which the key(s) should not be used anymore. // notbefore is the unixtime before which the key(s) should not be used yet. // fallback determines if the key may serve as a fallback key. // repoURI is URI of the corresponding KeyInit repository. // Necessary randomness is read from rand. func (msg *Message) KeyInit( msgcount, notafter, notbefore uint64, fallback bool, repoURI, mixaddress, nymaddress string, rand io.Reader, ) (ki *KeyInit, pubKeyHash, privateKey string, err error) { var keyInit KeyInit // time checks if notbefore >= notafter { log.Error(ErrInvalidTimes) return nil, "", "", ErrInvalidTimes } if notafter < uint64(times.Now()) { log.Error(ErrExpired) return nil, "", "", ErrExpired } if notafter > uint64(times.Now())+MaxNotAfter { log.Error(ErrFuture) return nil, "", "", ErrFuture } // init keyInit.Contents.VERSION = ProtocolVersion keyInit.Contents.MSGCOUNT = msgcount keyInit.Contents.NOTAFTER = notafter keyInit.Contents.NOTBEFORE = notbefore keyInit.Contents.FALLBACK = fallback keyHash, err := base64.Decode(msg.UIDContent.SIGKEY.HASH) if err != nil { return nil, "", "", err } keyInit.Contents.SIGKEYHASH = base64.Encode(cipher.SHA512(keyHash)) // make sure REPOURIS is set to the first REPOURI of UIDContent.REPOURIS // TODO: support different KeyInit repository configurations if repoURI != msg.UIDContent.REPOURIS[0] { return nil, "", "", log.Error("uri: repoURI differs from msg.UIDContent.REPOURIS[0]") } keyInit.Contents.REPOURI = repoURI // create SessionAnchor sa, sah, pubKeyHash, privateKey, err := msg.sessionAnchor(keyHash, mixaddress, nymaddress, rand) if err != nil { return nil, "", "", err } keyInit.Contents.SESSIONANCHOR = sa keyInit.Contents.SESSIONANCHORHASH = sah // sign KeyInit: the content doesn't have to be hashed, because Ed25519 is // already taking care of that. sig := msg.UIDContent.SIGKEY.ed25519Key.Sign(keyInit.Contents.json()) keyInit.SIGNATURE = base64.Encode(sig) ki = &keyInit return }
func TestKeyList(t *testing.T) { now := times.Now() timeNow = func() int64 { return now - 2 } _, privkey, _ := ed25519.GenerateKey(rand.Reader) kl := New(privkey, "*****@*****.**", 5, 5, testDir) kl.AddKey() kl.AddKey() timeNow = func() int64 { return now } kl.AddKey() timeNow = func() int64 { return times.Now() } marshalled := kl.Marshal() kl2 := New(privkey, "*****@*****.**", 5, 5, testDir) err := kl2.Unmarshal(marshalled) if err != nil { t.Errorf("Unmarshal failed: %s", err) } for k := range kl.Keys { if _, ok := kl2.Keys[k]; !ok { t.Errorf("Not found after unmarshal: %x", k) } } first, last := kl2.GetBoundaryTime() if last-first < 1 { t.Error("GetBoundaryTime failed") } timeNow = func() int64 { return now + 4 } // kl2.Maintain() kl2.Expire() if len(kl2.Keys) != 1 { t.Error("Expire wrong number of keys") } timeNow = func() int64 { return times.Now() + 10 } kl2.AddKey() kl2.Expire() if len(kl2.Keys) != 1 { t.Error("Expire wrong number of keys") } timeNow = func() int64 { return time.Now().Unix() } if !testing.Short() { kl2 := New(privkey, "*****@*****.**", 20, 10, testDir) kl2.Maintain() time.Sleep(time.Second * 33) close(kl2.stopchan) time.Sleep(time.Second * 1) if len(kl2.Keys) > 4 || len(kl2.Keys) < 2 { t.Error("Expire/Add maintainer inconsistent") } } }
func TestPublicKeyInit(t *testing.T) { tmpdir, keyDB, err := createDB() if err != nil { t.Fatal(err) } defer os.RemoveAll(tmpdir) defer keyDB.Close() msg, err := uid.Create("*****@*****.**", false, "", "", uid.Strict, hashchain.TestEntry, cipher.RandReader) if err != nil { t.Fatal(err) } now := uint64(times.Now()) ki, _, _, err := msg.KeyInit(1, now+times.Day, now-times.Day, false, "mute.berlin", "", "", cipher.RandReader) if err != nil { t.Fatal(err) } if err := keyDB.AddPublicKeyInit(ki); err != nil { t.Fatal(err) } rKI, err := keyDB.GetPublicKeyInit(ki.SigKeyHash()) if err != nil { t.Fatal(err) } if !bytes.Equal(rKI.JSON(), ki.JSON()) { t.Error("KeyInits differ") } }
func TestPrivateKeyInit(t *testing.T) { tmpdir, keyDB, err := createDB() if err != nil { t.Fatal(err) } defer os.RemoveAll(tmpdir) defer keyDB.Close() msg, err := uid.Create("*****@*****.**", false, "", "", uid.Strict, hashchain.TestEntry, cipher.RandReader) if err != nil { t.Fatal(err) } now := uint64(times.Now()) ki, pubKeyHash, privateKey, err := msg.KeyInit(1, now+times.Day, now-times.Day, false, "mute.berlin", "", "", cipher.RandReader) if err != nil { t.Fatal(err) } err = keyDB.AddPrivateKeyInit(ki, pubKeyHash, msg.SigPubKey(), privateKey, "/63l/c3XB5yimoGKv6GS9TjuiM3PKVH/H/dlhnQixeIRsFRkWRl8fjXmKyQl5bk4N7DjkBPg/1GQVndhG+HWAg==") if err != nil { t.Fatal(err) } rKI, rSigPubKey, rPrivKey, err := keyDB.GetPrivateKeyInit(pubKeyHash) if !bytes.Equal(rKI.JSON(), ki.JSON()) { t.Error("KeyInits differ") } if rSigPubKey != msg.SigPubKey() { t.Error("SigPubKeys differ") } if rPrivKey != privateKey { t.Error("PrivKeys differ") } }
func TestCheckToken(t *testing.T) { now := uint64(times.Now()) / SkewWindow pubkey, privkey, err := ed25519.GenerateKey(rand.Reader) if err != nil { t.Fatalf("Key generation failed: %s", err) } authtoken := CreateToken(pubkey, privkey, 1) pubkey2, ltime, lcounter, err := authtoken.CheckToken() if err != nil { t.Errorf("Token verification failed: %s", err) } if *pubkey2 != *pubkey { t.Errorf("Token decode failed, pubkey does not match: %x!=%x", *pubkey2, *pubkey) } if lcounter != 1 { t.Errorf("Token decode failed. Counter %d!=1", lcounter) } if uint64(math.Abs(float64(ltime-now))) > 1 { t.Errorf("Token decode failed. Time: %d!=%d", now, ltime) } authtoken[0] = 0x00 _, _, _, err = authtoken.CheckToken() if err == nil { t.Error("Token verification MUST fail") } }
// ExpireUnusable expires all tokens that cannot be used anymore (expired). Returns bool if it should be called // again since it only expires 10 tokens at a time func (ws *Storage) ExpireUnusable() bool { var hashS string var counted int var tokens [][]byte expireTime := times.Now() - ExpireEdge rows, err := ws.finalExpireQuery.Query(expireTime) if err != nil { return false } for rows.Next() { if err := rows.Scan(&hashS); err == nil { tokenHash, err := hex.DecodeString(hashS) if err == nil { counted++ tokens = append(tokens, tokenHash) } } } rows.Close() for _, token := range tokens { ws.DelToken(token) } if counted >= 10 { return true } return false }
// Current returns the current key and the previous key. func (kp *KeyPool) Current() (*signkeys.KeyPair, *signkeys.KeyPair, error) { if kp.Generator.PrivateKey == nil { return nil, nil, ErrNoGenerator } generate := false kp.mapMutex.Lock() defer kp.mapMutex.Unlock() if kp.currentKey == nil { // Always generate if we dont have one yet generate = true } else if kp.currentKey.PublicKey.Expire < times.Now()-kp.Generator.ExpireTime/2 { // Key has half expired, generate new one generate = true } if generate { newKey, err := kp.Generator.GenKey() if err != nil { return nil, nil, err } // Write currentKey to file err = kp.WriteKey(&newKey.PublicKey) if err != nil { return nil, nil, err } if kp.currentKey != nil { kp.previousKey = kp.currentKey } kp.currentKey = newKey kp.keys[kp.currentKey.PublicKey.KeyID] = &newKey.PublicKey } return kp.currentKey, kp.previousKey, nil }
func TestSessionAnchor(t *testing.T) { // create UID message msg, err := Create("*****@*****.**", false, "", "", Strict, hashchain.TestEntry, cipher.RandReader) if err != nil { t.Fatal(err) } // KeyInit now := uint64(times.Now()) ki, _, privKey, err := msg.KeyInit(1, now+times.Day, now-times.Day, false, "mute.berlin", "", "", cipher.RandReader) if err != nil { t.Fatal(err) } // SesionAnchor sa, err := ki.SessionAnchor(msg.SigPubKey()) if err != nil { t.Fatal(err) } // check private key methods if err := sa.SetPrivateKey(privKey); err != nil { t.Fatal(err) } if privKey != sa.PrivateKey() { t.Fatal("private keys differ") } }
// CleanLocks cleans all locks. If force is true all locks are removed, not only expired locks func (ws *Storage) CleanLocks(force bool) { locktime := times.Now() + MaxLockAge if force { locktime = int64(^uint32(0)) // MaxUInt32 } ws.cleanLocksQuery.Exec(locktime) }
// GenerateCertificate returns a signed and encoded SortedMap. func (sm StringMap) GenerateCertificate(privKey *[ed25519.PrivateKeySize]byte) ([]byte, error) { so := sm.Sort() sigmap := new(SignedMap) sigmap.SignDate = uint64(times.Now()) sigmap.Signature = so.Sign(sigmap.SignDate, privKey) sigmap.Config = sm return sigmap.Marshal() }
func TestKeyEntry(t *testing.T) { // create UID message msg, err := Create("*****@*****.**", false, "", "", Strict, hashchain.TestEntry, cipher.RandReader) if err != nil { t.Fatal(err) } // KeyInit now := uint64(times.Now()) ki, _, privateKey, err := msg.KeyInit(1, now+times.Day, now-times.Day, false, "mute.berlin", "", "", cipher.RandReader) if err != nil { t.Fatal(err) } // KeyEntry ke, err := ki.KeyEntryECDHE25519(msg.SigPubKey()) if err != nil { t.Fatal(err) } // verify consistency if err := ke.Verify(); err != nil { t.Fatal(err) } // equal if !KeyEntryEqual(ke, ke) { t.Error("ke should be equal to itself") } a := ke var b KeyEntry b.CIPHERSUITE = a.CIPHERSUITE b.FUNCTION = a.FUNCTION b.HASH = a.HASH b.PUBKEY = a.PUBKEY if !KeyEntryEqual(a, &b) { t.Error("a and b should be equal to itself") } // private key check if err := ke.SetPrivateKey(privateKey); err != nil { t.Fatal(err) } privKey := ke.PrivateKey32() if privateKey != base64.Encode(privKey[:]) { t.Error("private keys differ") } // public key check var publicKey [32]byte curve25519.ScalarBaseMult(&publicKey, privKey) pubKey := ke.PublicKey32() if !bytes.Equal(publicKey[:], pubKey[:]) { t.Error("public keys differ") } }
// lookup a public key from keypool without lock func (kp *KeyPool) lookup(keyid [signkeys.KeyIDSize]byte) (*signkeys.PublicKey, error) { if d, ok := kp.keys[keyid]; ok { if d.Expire > times.Now() { return d, nil } return nil, ErrExpired } return nil, ErrNotFound }
// Verify verifies that the KeyInit is valid and contains a valid ECDHE25519 // key. func (ki *KeyInit) Verify(keyInitRepositoryURIs []string, sigPubKey string) error { // The REPOURI points to this KeyInit Repository if !util.ContainsString(keyInitRepositoryURIs, ki.Contents.REPOURI) { log.Error(ErrRepoURI) return ErrRepoURI } // verify that SESSIONANCHORHASH matches decrypted SESSIONANCHOR sa, err := ki.SessionAnchor(sigPubKey) if err != nil { return err } // get KeyEntry message from SessionAnchor ke, err := sa.KeyEntry("ECDHE25519") if err != nil { return err } // verify KeyEntry message if err := ke.Verify(); err != nil { return err } // NOTAFTER and NOTBEFORE are valid if ki.Contents.NOTBEFORE >= ki.Contents.NOTAFTER { log.Error(ErrInvalidTimes) return ErrInvalidTimes } // not expired if ki.Contents.NOTAFTER < uint64(times.Now()) { log.Error(ErrExpired) return ErrExpired } // SIGNATURE was made with UIDMessage.UIDContent.SIGKEY over Contents var ed25519Key cipher.Ed25519Key sig, err := base64.Decode(ki.SIGNATURE) if err != nil { return err } pubKey, err := base64.Decode(sigPubKey) if err != nil { return err } // create ed25519 key ed25519Key.SetPublicKey(pubKey) // verify self-signature if !ed25519Key.Verify(ki.Contents.json(), sig) { log.Error(ErrInvalidKeyInitSig) return ErrInvalidKeyInitSig } return nil }
// ParseAddress parses an address. func ParseAddress(address []byte) (*Address, error) { a := new(Address) _, err := asn1.Unmarshal(address, a) if err != nil { return nil, err } if a.Expire < times.Now() { return nil, ErrExpired } return a, nil }
func encrypt(sign bool, flipUIDs bool) ( sender, recipient *uid.Message, w bytes.Buffer, recipientTemp *uid.KeyEntry, privateKey string, err error, ) { sender, err = uid.Create("*****@*****.**", false, "", "", uid.Strict, hashchain.TestEntry, cipher.RandReader) if err != nil { return } recipient, err = uid.Create("*****@*****.**", false, "", "", uid.Strict, hashchain.TestEntry, cipher.RandReader) if err != nil { return } if flipUIDs { sender, recipient = recipient, sender } r := bytes.NewBufferString(msgs.Message1) now := uint64(times.Now()) recipientKI, _, privateKey, err := recipient.KeyInit(1, now+times.Day, now-times.Day, false, "mute.berlin", "", "", cipher.RandReader) if err != nil { return } recipientTemp, err = recipientKI.KeyEntryECDHE25519(recipient.SigPubKey()) if err != nil { return } // encrypt var privateSigKey *[64]byte if sign { privateSigKey = sender.PrivateSigKey64() } ms := memstore.New() ms.AddPublicKeyEntry(recipient.Identity(), recipientTemp) args := &EncryptArgs{ Writer: &w, From: sender, To: recipient, SenderLastKeychainHash: hashchain.TestEntry, PrivateSigKey: privateSigKey, Reader: r, Rand: cipher.RandReader, KeyStore: ms, } if _, err = Encrypt(args); err != nil { return } return }
// GetExpire returns the first expiring tokenHash or nil func (ws *Storage) GetExpire() []byte { var hashS string expireLimit := times.Now() + ExpireEdge err := ws.getExpireQuery.QueryRow(expireLimit).Scan(&hashS) if err != nil { return nil } tokenHash, err := hex.DecodeString(hashS) if err != nil { return nil } return tokenHash }
// LockToken locks token against other use. Return lockID > 0 on success, <0 on failure func (ws *Storage) LockToken(tokenHash []byte) int64 { lockID := getLockID() tokenHashS := hex.EncodeToString(tokenHash) lockTime := times.Now() res, err := ws.lockQuery.Exec(lockID, lockTime, tokenHashS, lockID) if err != nil || res == nil { return -1 } if num, _ := res.RowsAffected(); num == 0 { return -1 } return lockID }
func TestUpkeep(t *testing.T) { tmpdir, msgDB, err := createDB() if err != nil { t.Fatal(err) } defer os.RemoveAll(tmpdir) defer msgDB.Close() a := "*****@*****.**" if err := msgDB.AddNym(a, a, "Alice"); err != nil { t.Fatal(err) } // upkeep all tp, err := msgDB.GetUpkeepAll(a) if err != nil { t.Fatal(err) } if tp != 0 { t.Error("tp != 0") } now := times.Now() if err := msgDB.SetUpkeepAll(a, now); err != nil { t.Fatal(err) } tp, err = msgDB.GetUpkeepAll(a) if err != nil { t.Fatal(err) } if tp != now { t.Error("tp != now") } // upkeep accounts tp, err = msgDB.GetUpkeepAccounts(a) if err != nil { t.Fatal(err) } if tp != 0 { t.Error("tp != 0") } now++ if err := msgDB.SetUpkeepAccounts(a, now); err != nil { t.Fatal(err) } tp, err = msgDB.GetUpkeepAccounts(a) if err != nil { t.Fatal(err) } if tp != now { t.Error("tp != now") } }
func (ce *CtrlEngine) upkeepFetchconf( msgDB *msgdb.MsgDB, homedir string, show bool, outfp, statfp io.Writer, ) error { netDomain, pubkeyStr, configURL := def.ConfigParams() log.Infof("fetch config for '%s'", netDomain) fmt.Fprintf(statfp, "fetch config for '%s'\n", netDomain) publicKey, err := hex.DecodeString(pubkeyStr) if err != nil { log.Error(err) } ce.config.PublicKey = publicKey ce.config.URLList = "10," + configURL ce.config.Timeout = 0 // use default timeout if err := ce.config.Update(); err != nil { return log.Error(err) } jsn, err := json.Marshal(ce.config) if err != nil { return log.Error(err) } if err := msgDB.AddValue(netDomain, string(jsn)); err != nil { return err } err = msgDB.AddValue("time."+netDomain, strconv.FormatInt(times.Now(), 10)) if err != nil { return err } // apply new configuration if err := def.InitMute(&ce.config); err != nil { return err } // format configuration nicely jsn, err = json.MarshalIndent(ce.config, "", " ") if err != nil { return log.Error(err) } // write new configuration file if err := writeConfigFile(homedir, netDomain, jsn); err != nil { return err } // show new configuration if show { fmt.Fprintf(outfp, string(jsn)+"\n") } return nil }
// Certify verifies an encoded certificate. func Certify(lastSignDate uint64, publicKey []byte, cert []byte) (*SignedMap, error) { sm, err := Unmarshal(cert) if err != nil { return nil, err } if lastSignDate > 0 && sm.SignDate < lastSignDate { return nil, ErrWalkBack } if diff(uint64(times.Now()), sm.SignDate) > MaxSignatureAge { return nil, ErrBadTime } if !sm.Config.Sort().Verify(sm.SignDate, publicKey, sm.Signature) { return nil, ErrNoVerify } return sm, nil }
func TestKeyEntry(t *testing.T) { ms := New() uidMsg, err := uid.Create("*****@*****.**", false, "", "", uid.Strict, hashchain.TestEntry, cipher.RandReader) if err != nil { t.Fatal(err) } now := uint64(times.Now()) ki, _, _, err := uidMsg.KeyInit(1, now+times.Day, now-times.Day, false, "mute.berlin", "", "", cipher.RandReader) if err != nil { t.Fatal(err) } ke, err := ki.KeyEntryECDHE25519(uidMsg.SigPubKey()) if err != nil { t.Fatal(err) } // private ms.AddPrivateKeyEntry(ke) entry, err := ms.GetPrivateKeyEntry(ke.HASH) if err != nil { t.Error(err) } else if entry != ke { t.Error("entry != ke") } if _, err := ms.GetPrivateKeyEntry("MUTE"); err == nil { t.Error("should fail") } // public ms.AddPublicKeyEntry(uidMsg.Identity(), ke) entry, _, err = ms.GetPublicKeyEntry(uidMsg) if err != nil { t.Error(err) } else if entry != ke { t.Error("entry != ke") } uidMsg, err = uid.Create("*****@*****.**", false, "", "", uid.Strict, hashchain.TestEntry, cipher.RandReader) if err != nil { t.Fatal(err) } if _, _, err := ms.GetPublicKeyEntry(uidMsg); err != session.ErrNoKeyEntry { t.Error("should fail with session.ErrNoKeyEntry") } }
func TestExpired(t *testing.T) { msg, err := Create("*****@*****.**", false, "", "", Strict, hashchain.TestEntry, cipher.RandReader) if err != nil { t.Fatal(err) } // success ki, _, _, err := msg.KeyInit(1, uint64(times.Now()), 0, false, "mute.berlin", "", "", cipher.RandReader) if err != nil { t.Fatal(err) } // wait until key init expires time.Sleep(time.Second) // verify uris := make([]string, 1) uris[0] = "mute.berlin" if err := ki.Verify(uris, msg.UIDContent.SIGKEY.PUBKEY); err != ErrExpired { t.Error("should fail") } }
// Verify a given inputToken and return it's public key if it verifies. func (c *Client) Verify(inputToken []byte) (outputToken *TokenEntry, err error) { tokenUnmarshalled, err := token.Unmarshal(inputToken) if err != nil { c.LastError = err return nil, ErrFatal } keyid, owner := tokenUnmarshalled.Properties() pubkey, err := c.getPubKey(*keyid) if err != nil { return nil, err } // Check if it is expired. Duplicate. Keypool does that as well if pubkey.Expire < times.Now() { c.LastError = ErrExpireToken return nil, ErrFinal } // Get data from token, signature first signature := tokenUnmarshalled.GetSignature() tempSignature := jjm.NewClearSignature(&pubkey.PublicKey) tempSignature.PointR = signature.PointR tempSignature.ScalarS = signature.ScalarS tempSignature.ScalarR = signature.ScalarR // Get signature message clearMessage := jjm.NewClearMessage(tokenUnmarshalled.Hash()) // Verify the signature blindClient := jjm.NewGenericBlindingClient(&pubkey.PublicKey, c.packetClient.Curve) ok, err := blindClient.Verify(tempSignature, clearMessage) if err != nil || !ok { c.LastError = err return nil, ErrFinal } outputToken = &TokenEntry{ Hash: tokenUnmarshalled.Hash(), Token: inputToken, OwnerPubKey: owner, Usage: pubkey.Usage, Expire: pubkey.Expire, } return outputToken, nil }
// GenKey generates a new key structure. func (kg KeyGenerator) GenKey() (*KeyPair, error) { if kg.PrivateKey == nil { return nil, ErrNoSigner } privateKey, publicKey, err := kg.Curve.GenerateKey() if err != nil { return nil, err } k := &KeyPair{ PrivateKey: privateKey, PublicKey: PublicKey{ PublicKey: *publicKey, Expire: times.Now() + kg.ExpireTime, Usage: kg.Usage, Signer: *kg.PublicKey, }, } // Create signature k.PublicKey.KeyID = k.PublicKey.CalcKeyID() sig := ed25519.Sign(kg.PrivateKey, k.PublicKey.KeyID[:]) k.PublicKey.Signature = *sig return k, nil }
// loadKey adds a single key to the keypool. Without lock. func (kp *KeyPool) loadKey(loadKey *signkeys.PublicKey) (*[signkeys.KeyIDSize]byte, error) { if kp.Generator.Usage != "" && loadKey.Usage != kp.Generator.Usage { // Don't load if usage is a mismatch return nil, ErrBadUsage } if loadKey.Expire < times.Now() { // Don't load expired keys return nil, ErrExpired } if !kp.HasVerifyKey(&loadKey.Signer, true) { // Don't load keys without matching signature return nil, ErrBadSigner } if !loadKey.Verify(&loadKey.Signer) { // Don't load keys without matching signature return nil, ErrBadSigner } if _, exists := kp.keys[loadKey.KeyID]; exists { return &loadKey.KeyID, ErrExists } kp.keys[loadKey.KeyID] = loadKey return &loadKey.KeyID, nil }
func (ce *CtrlEngine) upkeepAccounts( unmappedID, period, remaining string, statfp io.Writer, ) error { mappedID, err := identity.Map(unmappedID) if err != nil { return err } exec, now, err := checkExecution(mappedID, period, func(mappedID string) (int64, error) { return ce.msgDB.GetUpkeepAccounts(mappedID) }) if err != nil { return err } if !exec { log.Info(statfp, "ctrlengine: upkeep accounts not due") fmt.Fprintf(statfp, "ctrlengine: upkeep accounts not due\n") return nil } remain, err := time.ParseDuration(remaining) if err != nil { return err } contacts, err := ce.msgDB.GetAccounts(mappedID) if err != nil { return err } for _, contact := range contacts { privkey, server, _, _, _, _, err := ce.msgDB.GetAccount(mappedID, contact) if err != nil { return err } last, err := ce.msgDB.GetAccountTime(mappedID, contact) if err != nil { return err } if last == 0 { last, err = mixclient.AccountStat(privkey, server, def.CACert) if err != nil { return err } err := ce.msgDB.SetAccountTime(mappedID, contact, last) if err != nil { return err } } if times.Now()+int64(remain.Seconds()) >= last { token, err := wallet.GetToken(ce.client, def.AccdUsage, def.AccdOwner) if err != nil { return err } _, err = mixclient.PayAccount(privkey, token.Token, server, def.CACert) if err != nil { ce.client.UnlockToken(token.Hash) return log.Error(err) } ce.client.DelToken(token.Hash) last, err = mixclient.AccountStat(privkey, server, def.CACert) if err != nil { return err } err = ce.msgDB.SetAccountTime(mappedID, contact, last) if err != nil { return err } } } // record time of execution if err := ce.msgDB.SetUpkeepAccounts(mappedID, now); err != nil { return err } return nil }
// Update a configuration structure. func (c *Config) Update() error { var err error var cert *sortedmap.SignedMap var myCAhash, certHashb []byte var hisHash string var ok bool if c.Timeout == 0 { c.Timeout = 30 } ts := roundrobin.ParseServers(c.URLList) sort.Sort(ts) c.servers = ts.Order() if len(c.servers) < 1 { return ErrNoServers } if c.LastSignDate == 0 { c.LastSignDate = uint64(times.Now() - skew) } GetConfigLoop: for ; c.curServer < len(c.servers); c.curServer++ { cert, err = getConfig(c.servers[c.curServer], c.PublicKey, c.LastSignDate, c.Timeout) if err == nil { break GetConfigLoop } } if err != nil { return err } // Change server ordering to make working and untested first c.servers = append(c.servers[c.curServer:], c.servers[:c.curServer]...) c.curServer = 0 if hisHash, ok = cert.Config["CACertHash"]; !ok { c.Map = cert.Config c.LastSignDate = cert.SignDate return nil } if certHashb, err = hex.DecodeString(hisHash); err != nil { return err } if c.CACert != nil { if myCAhash, err = cahash.Hash(c.CACert); err != nil { return err } } if !bytes.Equal(myCAhash, certHashb) { CALoop: for ; c.curServer < len(c.servers); c.curServer++ { c.CACert, err = getCACert(c.servers[c.curServer], hisHash, c.Timeout) if err == nil { break CALoop } } } if err != nil { return err } c.Map = cert.Config c.LastSignDate = cert.SignDate return nil }
func TestSendReceiveRelay(t *testing.T) { _, privkey, _ := ed25519.GenerateKey(rand.Reader) mixAddress := "*****@*****.**" recAddress := "mailbox001@001." pseudonym := []byte("Pseudonym001") pseudoHash := sha256.Sum256(pseudonym) kl := mixaddr.New(privkey, mixAddress, 7200, 24*3600, "/tmp/mixkeydir") kl.AddKey() stmt := kl.GetStatement() // AddressTemplate contains parameters for address creation addressTemplate := nymaddr.AddressTemplate{ Secret: []byte("something super-secret"), MixCandidates: stmt.Addresses, Expire: times.Now() + 3600, SingleUse: true, MinDelay: 10, MaxDelay: 30, } NymAddress, err := addressTemplate.NewAddress([]byte(recAddress), pseudoHash[:]) if err != nil { t.Fatalf("NewAddress: %s", err) } clientHeader := ClientMixHeader{ SenderMinDelay: 10, SenderMaxDelay: 30, Token: []byte("Example token"), } encMessage, nextaddress, err := clientHeader.NewRelayMessage(NymAddress, testMessage) if err != nil { t.Fatalf("NewRelayMessage: %s", err) } if nextaddress != mixAddress { t.Error("Bad NextHop") } receiveData, err := ReceiveMessage(kl.GetPrivateKey, encMessage) if err != nil { t.Fatalf("ReceiveMessage: %s", err) } if len(receiveData.UniqueTest) != 2 { t.Error("SingleUse nymaddress, exactly two uniquetests necessary") } if !bytes.Equal(receiveData.Message, testMessage) { t.Error("Messages dont match") } if !bytes.Equal(receiveData.MixHeader.Token, clientHeader.Token) { t.Error("Tokens dont match") } if receiveData.MixHeader.SenderMaxDelay != clientHeader.SenderMaxDelay { t.Error("Max delay does not match") } if receiveData.MixHeader.SenderMinDelay != clientHeader.SenderMinDelay { t.Error("Min delay does not match") } newMessage, nextaddress, err := receiveData.Send() if err != nil { t.Fatalf("Send-Along: %s", err) } if nextaddress != "*****@*****.**" { t.Error("Bad address expansion") } decMessage, nym, err := ReceiveFromMix(addressTemplate, []byte(recAddress), newMessage) if err != nil { t.Fatalf("ReceiveFromMix: %s", err) } if !bytes.Equal(nym, pseudoHash[:]) { t.Error("Nyms do not match") } if !bytes.Equal(decMessage, testMessage) { t.Error("Message decryption failed") } }
// SignNonce signs the current time as nonce and returns it. func (msg *Message) SignNonce() (nonce uint64, signature string) { nonce = uint64(times.Now()) signature = base64.Encode(msg.UIDContent.SIGKEY.ed25519Key.Sign(encode.ToByte8(nonce))) return }
// Package mixaddr implements key handling functions for mixes and mix clients. package mixaddr import ( "crypto" _ "crypto/sha256" // import sha256 "encoding/binary" "encoding/json" "math/rand" "github.com/agl/ed25519" "github.com/mutecomm/mute/util/times" ) var timeNow = func() int64 { return times.Now() } // Address contains a mix address. type Address struct { Pubkey []byte // The mix public key Expire int64 // Time the key expires Address string // The address where the mix listens TokenKey []byte // The token key of that mix } // AddressStatement contains a statement by a mix concerning its addresses. type AddressStatement struct { Addresses AddressList Signature []byte PublicKey []byte }