コード例 #1
0
ファイル: keyinit.go プロジェクト: JonathanLogan/mute
// 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
}
コード例 #2
0
ファイル: privkey_test.go プロジェクト: JonathanLogan/mute
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")
		}
	}
}
コード例 #3
0
ファイル: keydb_test.go プロジェクト: JonathanLogan/mute
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")
	}
}
コード例 #4
0
ファイル: keydb_test.go プロジェクト: JonathanLogan/mute
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")
	}
}
コード例 #5
0
ファイル: walletauth_test.go プロジェクト: JonathanLogan/mute
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")
	}
}
コード例 #6
0
ファイル: store.go プロジェクト: JonathanLogan/mute
// 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
}
コード例 #7
0
ファイル: generator.go プロジェクト: JonathanLogan/mute
// 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
}
コード例 #8
0
ファイル: keyinit_test.go プロジェクト: JonathanLogan/mute
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")
	}
}
コード例 #9
0
ファイル: store.go プロジェクト: JonathanLogan/mute
// 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)
}
コード例 #10
0
ファイル: signedmap.go プロジェクト: JonathanLogan/mute
// 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()
}
コード例 #11
0
ファイル: keyentry_test.go プロジェクト: JonathanLogan/mute
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")
	}
}
コード例 #12
0
ファイル: generator.go プロジェクト: JonathanLogan/mute
// 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
}
コード例 #13
0
ファイル: keyinit.go プロジェクト: JonathanLogan/mute
// 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
}
コード例 #14
0
ファイル: addr.go プロジェクト: JonathanLogan/mute
// 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
}
コード例 #15
0
ファイル: msg_test.go プロジェクト: JonathanLogan/mute
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
}
コード例 #16
0
ファイル: store.go プロジェクト: JonathanLogan/mute
// 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
}
コード例 #17
0
ファイル: store.go プロジェクト: JonathanLogan/mute
// 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
}
コード例 #18
0
ファイル: nyms_test.go プロジェクト: JonathanLogan/mute
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")
	}
}
コード例 #19
0
ファイル: upkeep.go プロジェクト: JonathanLogan/mute
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
}
コード例 #20
0
ファイル: signedmap.go プロジェクト: JonathanLogan/mute
// 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
}
コード例 #21
0
ファイル: memstore_test.go プロジェクト: JonathanLogan/mute
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")
	}
}
コード例 #22
0
ファイル: keyinit_test.go プロジェクト: JonathanLogan/mute
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")
	}
}
コード例 #23
0
ファイル: verify.go プロジェクト: JonathanLogan/mute
// 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
}
コード例 #24
0
ファイル: keys.go プロジェクト: JonathanLogan/mute
// 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
}
コード例 #25
0
ファイル: generator.go プロジェクト: JonathanLogan/mute
// 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
}
コード例 #26
0
ファイル: upkeep.go プロジェクト: JonathanLogan/mute
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
}
コード例 #27
0
ファイル: client.go プロジェクト: JonathanLogan/mute
// 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
}
コード例 #28
0
ファイル: clientmix_test.go プロジェクト: JonathanLogan/mute
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")
	}
}
コード例 #29
0
ファイル: uid.go プロジェクト: JonathanLogan/mute
// 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
}
コード例 #30
0
ファイル: addrlist.go プロジェクト: JonathanLogan/mute
// 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
}