// Create tries to create an encrypted database with the given passphrase and // iter many KDF iterations. Thereby, dbname is the prefix of the following // two database files which will be created and must not exist already: // // dbname.db // dbname.key // // The SQL database is initialized with the statements given in createStmts. // In case of error (for example, the database files do exist already or // cannot be created) an error is returned. func Create(dbname string, passphrase []byte, iter int, createStmts []string) error { dbfile := dbname + DBSuffix keyfile := dbname + KeySuffix // make sure files do not exist already if _, err := os.Stat(dbfile); err == nil { return log.Errorf("encdb: dbfile '%s' exists already", dbfile) } if _, err := os.Stat(keyfile); err == nil { return log.Errorf("encdb: dbfile '%s' exists already", keyfile) } // create keyfile key, err := generateKeyfile(keyfile, passphrase, iter) if err != nil { return err } // create DB dbfile += fmt.Sprintf("?_pragma_key=x'%s'&_pragma_cipher_page_size=4096", hex.EncodeToString(key)) db, err := sql.Open("sqlite3", dbfile) if err != nil { return log.Error(err) } defer db.Close() _, err = db.Exec("PRAGMA auto_vacuum = full;") if err != nil { return log.Error(err) } return createTables(db, createStmts) }
func checkDelayArgs(c *cli.Context) error { if !c.Bool("nodelaycheck") { if c.Int("mindelay") < def.MinMinDelay { return log.Errorf("--mindelay must be at least %d", def.MinMinDelay) } if c.Int("maxdelay") < def.MinMaxDelay { return log.Errorf("--maxdelay must be at least %d", def.MinMaxDelay) } if c.Int("mindelay") >= c.Int("maxdelay") { return log.Error("--mindelay must be strictly smaller than --maxdelay") } } return nil }
func readInnerHeader(r io.Reader) (*innerHeader, error) { var ih innerHeader // read Type if err := binary.Read(r, binary.BigEndian, &ih.Type); err != nil { return nil, err } // check Type if ih.Type != paddingType && ih.Type != dataType && ih.Type != dataType|signType && ih.Type != signatureType { return nil, log.Errorf("msg: invalid inner header type %d", ih.Type) } // read Plen if err := binary.Read(r, binary.BigEndian, &ih.PLen); err != nil { return nil, log.Error(err) } // read More if err := binary.Read(r, binary.BigEndian, &ih.More); err != nil { return nil, log.Error(err) } // read Skip if err := binary.Read(r, binary.BigEndian, &ih.Skip); err != nil { return nil, log.Error(err) } // read content ih.content = make([]byte, ih.PLen) if _, err := io.ReadFull(r, ih.content); err != nil { return nil, log.Error(err) } return &ih, nil }
func parseFDOption(c *cli.Context, name string) ( fd uintptr, fp *os.File, err error, ) { fs := c.GlobalString(name) switch fs { case "stdin": fd = uintptr(syscall.Stdin) fp = os.Stdin case "stdout": fd = uintptr(syscall.Stdout) fp = os.Stdout case "stderr": fd = uintptr(syscall.Stderr) fp = os.Stderr default: i, err := strconv.Atoi(fs) if err != nil { return 0, nil, log.Errorf("cannot parse --%s %s: argument must be \"stdin\", "+ "\"stdout\", \"stderr\" or an integer (a file descriptor)", name, fs) } fd = uintptr(i) fp = os.NewFile(fd, name) } return }
func mutecryptDeleteUID(c *cli.Context, id string, passphrase []byte) error { args := []string{ "--homedir", c.GlobalString("homedir"), "--loglevel", c.GlobalString("loglevel"), "--logdir", c.GlobalString("logdir"), "uid", "delete", "--id", id, "--force", } cmd := exec.Command("mutecrypt", args...) var errbuf bytes.Buffer cmd.Stderr = &errbuf ppR, ppW, err := os.Pipe() if err != nil { return err } defer ppR.Close() ppW.Write(passphrase) ppW.Close() cmd.ExtraFiles = append(cmd.ExtraFiles, ppR) if err := cmd.Run(); err != nil { return log.Errorf("%s: %s", err, strings.TrimSpace(errbuf.String())) } return nil }
func readOuterHeader(r io.Reader) (*outerHeader, error) { var oh outerHeader // read Type if err := binary.Read(r, binary.BigEndian, &oh.Type); err != nil { return nil, log.Error(err) } // check Type if oh.Type != preHeaderPacket && oh.Type != encryptedHeader && oh.Type != cryptoSetup && oh.Type != hmacPacket && oh.Type != encryptedPacket { return nil, log.Errorf("msg: invalid outer header type %d", oh.Type) } // read Plen if err := binary.Read(r, binary.BigEndian, &oh.PLen); err != nil { return nil, log.Error(err) } // read PacketCount if err := binary.Read(r, binary.BigEndian, &oh.PacketCount); err != nil { return nil, log.Error(err) } // read inner packet oh.inner = make([]byte, oh.PLen) if _, err := io.ReadFull(r, oh.inner); err != nil { return nil, log.Error(err) } return &oh, nil }
// ReadKeyfile reads a randomly generated and encrypted AES-256 key from the // file with the given filename and returns it in unencrypted form. // The key is protected by a passphrase, which is processed by PBKDF2 to // derive the AES-256 key to decrypt the generated key. func ReadKeyfile(filename string, passphrase []byte) (key []byte, err error) { // open keyfile keyfile, err := os.Open(filename) if err != nil { return nil, log.Error(err) } defer keyfile.Close() // read iter and convert to int var biter = make([]byte, 8) if _, err := keyfile.Read(biter); err != nil { return nil, log.Error(err) } uiter := encode.ToUint64(biter) if uiter > 2147483647 { return nil, log.Errorf("encdb: ReadKeyfile: invalid iter value") } iter := int(uiter) // read salt var salt = make([]byte, 32) if _, err := keyfile.Read(salt); err != nil { return nil, log.Error(err) } // read encrypted key var encKey = make([]byte, 16+32) if _, err := keyfile.Read(encKey); err != nil { return nil, log.Error(err) } // compute derived key from passphrase dk := pbkdf2.Key([]byte(passphrase), salt, iter, 32, sha256.New) // decrypt key return cipher.AES256CBCDecrypt([]byte(dk), encKey), nil }
func (ce *CryptEngine) verifyServerSig( uid *uid.Message, msgReply *uid.MessageReply, position uint64, ) error { // For the first keyserver message we do not need to verify the server signature if uid.Localpart() == "keyserver" && uid.UIDContent.MSGCOUNT == 0 { return nil } // Get keyserver UID srvUID, _, found, err := ce.keyDB.GetPublicUID("keyserver@"+uid.Domain(), position) if err != nil { return err } if !found { return log.Errorf("cryptengine: no keyserver signature key found for domain '%s'", uid.Domain()) } // Verify server signature if err := msgReply.VerifySrvSig(uid, srvUID.UIDContent.SIGKEY.PUBKEY); err != nil { return log.Error(err) } return nil }
// ECDH computes a Diffie-Hellman (DH) key exchange over the elliptic curve (EC) // curve25519. If ownPublicKey is given it is used to check for the key // reflection attack. Otherwise it is derived from privateKey. func ECDH(privateKey, peersPublicKey, ownPublicKey *[32]byte) (*[32]byte, error) { var ( sharedKey [32]byte pubKey []byte ) // check mandatory key length if privateKey == nil { return nil, log.Error("cipher: curve25519.ECDH(): privateKey == nil") } if peersPublicKey == nil { return nil, log.Error("cipher: curve25519.ECDH(): peersPublicKey == nil") } // check for key reflection attack if ownPublicKey != nil { pubKey = ownPublicKey[:] } else { var publicKey [32]byte curve25519.ScalarBaseMult(&publicKey, privateKey) pubKey = publicKey[:] } if bytes.Equal(pubKey, peersPublicKey[:]) { return nil, log.Errorf("cipher: curve25519.ECDH(): publicKey == peersPublicKey") } // perform Diffie-Hellman key exchange curve25519.ScalarMult(&sharedKey, privateKey, peersPublicKey) return &sharedKey, nil }
func mutecryptHashchainValidate( c *cli.Context, domain, host string, passphrase []byte, ) error { args := []string{ "--homedir", c.GlobalString("homedir"), "--loglevel", c.GlobalString("loglevel"), "--logdir", c.GlobalString("logdir"), } if host != "" { args = append(args, "--keyhost", host, "--keyport", ":8080") // TODO: remove keyport hack! } args = append(args, "hashchain", "validate", "--domain", domain, ) cmd := exec.Command("mutecrypt", args...) var errbuf bytes.Buffer cmd.Stderr = &errbuf ppR, ppW, err := os.Pipe() if err != nil { return err } defer ppR.Close() ppW.Write(passphrase) ppW.Close() cmd.ExtraFiles = append(cmd.ExtraFiles, ppR) if err := cmd.Run(); err != nil { return log.Errorf("%s: %s", err, strings.TrimSpace(errbuf.String())) } return nil }
// SetPrivateKey sets the private key of curve25519Key to key. // SetPrivateKey returns an error, if len(key) != 32. func (c *Curve25519Key) SetPrivateKey(key []byte) error { if len(key) != 32 { return log.Errorf("cipher: Curve25519Key.SetPrivateKey(): len(key) = %d != 32", len(key)) } c.privateKey = new([32]byte) copy(c.privateKey[:], key) return nil }
// Check that the content of the UID message is consistent with it's version. func (msg *Message) Check() error { // we only support version 1.0 at this stage if msg.UIDContent.VERSION != "1.0" { return log.Errorf("uid: unknown UIDContent.VERSION: %s", msg.UIDContent.VERSION) } // generic checks optional := Optional.String() if msg.UIDContent.PREFERENCES.FORWARDSEC != optional { if msg.UIDContent.MIXADDRESS != "" { return log.Errorf("uid: MIXADDRESS must be null, if FORWARDSEC is not %q", optional) } if msg.UIDContent.NYMADDRESS != "" { return log.Errorf("uid: NYMADDRESS must be null, if FORWARDSEC is not %q", optional) } } if err := identity.IsMapped(msg.UIDContent.IDENTITY); err != nil { return log.Error(err) } // check SIGKEY if msg.UIDContent.SIGKEY.CIPHERSUITE != DefaultCiphersuite { return log.Error("uid: UIDContent.SIGKEY.CIPHERSUITE != DefaultCiphersuite") } if msg.UIDContent.SIGKEY.FUNCTION != "ED25519" { return log.Error("uid: UIDContent.SIGKEY.FUNCTION != \"ED25519\"") } // make sure LASTENTRY is parseable for a non-keyserver localpart. // For keyservers the LASTENTRY can be empty, iff this is the first entry // in the hashchain. lp, _, _ := identity.Split(msg.UIDContent.IDENTITY) if lp != "keyserver" { _, _, _, _, _, _, err := hashchain.SplitEntry(msg.UIDContent.LASTENTRY) if err != nil { return err } } // make sure ESCROWSIGNATURE and USERSIGNATURE are not set at the same time if msg.ESCROWSIGNATURE != "" && msg.USERSIGNATURE != "" { return log.Error("uid: USERSIGNATURE and ESCROWSIGNATURE cannot be set at the same time") } // version 1.0 specific checks return msg.checkV1_0() }
func (ce *CryptEngine) fetchKeyInit(pseudonym string) error { // map pseudonym id, domain, err := identity.MapPlus(pseudonym) if err != nil { return err } // get corresponding public ID msg, _, found, err := ce.keyDB.GetPublicUID(id, math.MaxInt64) // TODO: use simpler API if err != nil { return err } if !found { return log.Errorf("not UID for '%s' found", id) } // get SIGKEYHASH sigKeyHash, err := msg.SigKeyHash() if err != nil { return err } // get JSON-RPC client and capabilities client, _, err := ce.cache.Get(domain, ce.keydPort, ce.keydHost, ce.homedir, "KeyInitRepository.FetchKeyInit") if err != nil { return err } // call server content := make(map[string]interface{}) content["SigKeyHash"] = sigKeyHash reply, err := client.JSONRPCRequest("KeyInitRepository.FetchKeyInit", content) if err != nil { return err } rep, ok := reply["KeyInit"].(string) if !ok { return log.Errorf("cryptengine: could not fetch key init for '%s'", sigKeyHash) } ki, err := uid.NewJSONKeyInit([]byte(rep)) if err != nil { return err } // store public key init message if err := ce.keyDB.AddPublicKeyInit(ki); err != nil { return err } return nil }
// SetPrivateKey sets the private key of naclbox to key. // SetPrivateKey returns an error, if len(key) != 32. func (naClBoxKey *NaClBoxKey) SetPrivateKey(key []byte) error { if len(key) != 32 { return log.Errorf("cipher: NaClBoxKey.SetPrivateKey(): len(key) != 32") } naClBoxKey.privateKey = new([32]byte) copy(naClBoxKey.privateKey[:], key) return nil }
// encrypt reads data from r, encrypts it for identity to (with identity from // as sender), and writes it to w. func (ce *CryptEngine) encrypt( w io.Writer, from, to string, sign bool, nymAddress string, r io.Reader, statusfp *os.File, ) error { // map pseudonyms fromID, fromDomain, err := identity.MapPlus(from) if err != nil { return err } toID, err := identity.Map(to) if err != nil { return err } // get fromUID from keyDB fromUID, _, err := ce.keyDB.GetPrivateUID(fromID, true) if err != nil { return err } // get toUID from keyDB toUID, _, found, err := ce.keyDB.GetPublicUID(toID, math.MaxInt64) // TODO: use simpler API if err != nil { return err } if !found { return log.Errorf("not UID for '%s' found", toID) } // encrypt message senderLastKeychainHash, err := ce.keyDB.GetLastHashChainEntry(fromDomain) if err != nil { return err } var privateSigKey *[64]byte if sign { privateSigKey = fromUID.PrivateSigKey64() } args := &msg.EncryptArgs{ Writer: w, From: fromUID, To: toUID, NymAddress: nymAddress, SenderLastKeychainHash: senderLastKeychainHash, PrivateSigKey: privateSigKey, Reader: r, Rand: cipher.RandReader, KeyStore: ce, } nymAddress, err = msg.Encrypt(args) if err != nil { return err } // show nymaddress on status-fd fmt.Fprintf(statusfp, "NYMADDRESS:\t%s\n", nymAddress) return nil }
func (ce *CryptEngine) decrypt(w io.Writer, r io.Reader, statusfp *os.File) error { // retrieve all possible recipient identities from keyDB identities, err := ce.getRecipientIdentities() if err != nil { return err } // read pre-header r = base64.NewDecoder(r) version, preHeader, err := msg.ReadFirstOuterHeader(r) if err != nil { return err } // check version if version > msg.Version { return log.Errorf("cryptengine: newer message version, please update software") } if version < msg.Version { return log.Errorf("cryptengine: outdated message version, cannot process") } // decrypt message var senderID string var sig string args := &msg.DecryptArgs{ Writer: w, Identities: identities, PreHeader: preHeader, Reader: r, Rand: cipher.RandReader, KeyStore: ce, } senderID, sig, err = msg.Decrypt(args) if err != nil { // TODO: handle msg.ErrStatusError, should trigger a subsequent // encrypted message with StatusError return err } fmt.Fprintf(statusfp, "SENDERIDENTITY:\t%s\n", senderID) if sig != "" { fmt.Fprintf(statusfp, "SIGNATURE:\t%s\n", sig) } return nil }
// SetPrivateKey sets the private key of ed25519Key to key. // SetPrivateKey returns an error, if len(key) != ed25519.PrivateKeySize. func (ed25519Key *Ed25519Key) SetPrivateKey(key []byte) error { if len(key) != ed25519.PrivateKeySize { return log.Errorf("cipher: Ed25519Key.SetPrivateKey(): len(key) = %d != %d = ed25519.PrivateKeySize", len(key), ed25519.PrivateKeySize) } ed25519Key.privateKey = new([ed25519.PrivateKeySize]byte) copy(ed25519Key.privateKey[:], key) return nil }
func createTables(db *sql.DB, createStmts []string) error { for _, stmt := range createStmts { _, err := db.Exec(stmt) if err != nil { return log.Errorf("encdb: %q: %s", err, stmt) } } return nil }
// Check that the content of KeyInit is consistent with it's version. func (ki *KeyInit) Check() error { // we only support version 1.0 at this stage if ki.Contents.VERSION != "1.0" { return log.Errorf("uid: unknown ki.Contents.VERSION: %s", ki.Contents.VERSION) } // version 1.0 specific checks return ki.checkV1_0() }
// writeKeyFile writes a key file with the given filename that contains the // supplied key in AES-256 encrypted form. func writeKeyfile(filename string, passphrase []byte, iter int, key []byte) error { // make sure keyfile does not exist already if _, err := os.Stat(filename); err == nil { return log.Errorf("encdb: keyfile '%s' exists already", filename) } // convert iter to uint64 var uiter uint64 if iter < 0 || iter > 2147483647 { return log.Errorf("encdb: writeKeyfile: invalid iter value") } uiter = uint64(iter) // check keylength if len(key) != 32 { return log.Errorf("encdb: writeKeyfile: len(key) != 32") } // create keyfile keyfile, err := os.Create(filename) if err != nil { return log.Error(err) } defer keyfile.Close() // generate salt var salt = make([]byte, 32) if _, err := io.ReadFull(cipher.RandReader, salt); err != nil { return err } // compute derived key from passphrase dk := pbkdf2.Key(passphrase, salt, iter, 32, sha256.New) // compute AES-256 encrypted key (with IV) encKey := cipher.AES256CBCEncrypt([]byte(dk), key, cipher.RandReader) // write number of iterations if _, err := keyfile.Write(encode.ToByte8(uiter)); err != nil { return err } // write salt if _, err := keyfile.Write(salt); err != nil { return err } // write IV and AES-256 encrypted key if _, err := keyfile.Write(encKey); err != nil { return err } return nil }
func readPreHeader(r io.Reader) (*preHeader, error) { var ph preHeader // read version if err := binary.Read(r, binary.BigEndian, &ph.Version); err != nil { return nil, log.Error(err) } if ph.Version != Version { return nil, log.Errorf("msg: invalid message version %d", ph.Version) } //log.Debugf("ph.Version: %d", ph.Version) // read length of ciphersuite if err := binary.Read(r, binary.BigEndian, &ph.LengthCiphersuite); err != nil { return nil, log.Error(err) } if ph.LengthCiphersuite != uint16(len(DefaultCiphersuite)) { return nil, log.Errorf("msg: invalid ciphersuite length %d", ph.LengthCiphersuite) } //log.Debugf("ph.LengthCiphersuite: %d", ph.LengthCiphersuite) // read ciphersuite p := make([]byte, ph.LengthCiphersuite) if _, err := io.ReadFull(r, p); err != nil { return nil, log.Error(err) } ph.Ciphersuite = string(p) if ph.Ciphersuite != DefaultCiphersuite { return nil, log.Errorf("msg: invalid ciphersuite '%s'", ph.Ciphersuite) } //log.Debugf("ph.Ciphersuite: %s", ph.Ciphersuite) // read length sender header pub if err := binary.Read(r, binary.BigEndian, &ph.LengthSenderHeaderPub); err != nil { return nil, log.Error(err) } //log.Debugf("ph.LengthSenderHeaderPub: %d", ph.LengthSenderHeaderPub) ph.SenderHeaderPub = make([]byte, ph.LengthSenderHeaderPub) if _, err := io.ReadFull(r, ph.SenderHeaderPub); err != nil { return nil, log.Error(err) } //log.Debugf("ph.SenderHeaderPub: %s", base64.Encode(ph.SenderHeaderPub)) return &ph, nil }
// loop runs the crypt engine in a loop and reads commands from the file // descriptor command-fd. func (ce *CryptEngine) loop(c *cli.Context) { if len(c.Args()) > 0 { ce.err = fmt.Errorf("cryptengine: unknown command '%s', try 'help'", strings.Join(c.Args(), " ")) return } log.Info("cryptengine: starting") // run command(s) log.Infof("read commands from fd %d", ce.fileTable.CommandFD) scanner := bufio.NewScanner(ce.fileTable.CommandFP) for scanner.Scan() { args := []string{ce.app.Name} line := scanner.Text() if line == "" { log.Infof("read empty line") continue } log.Infof("read: %s", line) args = append(args, strings.Fields(line)...) if err := ce.app.Run(args); err != nil { // command execution failed -> issue status and continue log.Infof("command execution failed (app): %s", err) fmt.Fprintln(ce.fileTable.StatusFP, err) continue } if ce.err != nil { if ce.err == errExit { // exit requested -> return log.Info("cryptengine: stopping (exit requested)") fmt.Fprintln(ce.fileTable.StatusFP, "QUITTING") ce.err = nil return } // command execution failed -> issue status and continue log.Infof("command execution failed (cmd): %s", ce.err) fmt.Fprintln(ce.fileTable.StatusFP, ce.err) ce.err = nil } else { log.Info("command successful") } fmt.Fprintln(ce.fileTable.StatusFP, "READY.") } if err := scanner.Err(); err != nil { ce.err = log.Errorf("cryptengine: %s", err) } log.Info("cryptengine: stopping (error)") return }
// Verify KeyEntry messages in header. func (h *header) verify() error { // check h.SenderSessionPub if err := h.SenderSessionPub.Verify(); err != nil { return err } if h.SenderSessionPub.FUNCTION != "ECDHE25519" { return log.Errorf("msg: wrong uid.SenderSessionPub.FUNCTION: %s", h.SenderSessionPub.FUNCTION) } // check h.SenderIdentityPub if err := h.SenderIdentityPub.Verify(); err != nil { return err } if h.SenderIdentityPub.FUNCTION != "ECDHE25519" { return log.Errorf("msg: wrong uid.SenderIdentityPub.FUNCTION: %s", h.SenderIdentityPub.FUNCTION) } // check h.NextSenderSessionPub if h.NextSenderSessionPub != nil { if err := h.NextSenderSessionPub.Verify(); err != nil { return err } if h.NextSenderSessionPub.FUNCTION != "ECDHE25519" { return log.Errorf("msg: wrong uid.NextSenderSessionPub.FUNCTION: %s", h.SenderSessionPub.FUNCTION) } } // check h.NextRecipientSessionPubSeen if h.NextRecipientSessionPubSeen != nil { if err := h.NextRecipientSessionPubSeen.Verify(); err != nil { return err } if h.NextRecipientSessionPubSeen.FUNCTION != "ECDHE25519" { return log.Errorf("msg: wrong uid.NextRecipientSessionPubSeen.FUNCTION: %s", h.NextRecipientSessionPubSeen.FUNCTION) } } return nil }
func muteprotoDeliver( c *cli.Context, envelope string, ) (resend bool, err error) { args := []string{ "--homedir", c.GlobalString("homedir"), "--loglevel", c.GlobalString("loglevel"), "--logdir", c.GlobalString("logdir"), "deliver", } cmd := exec.Command("muteproto", args...) stdin, err := cmd.StdinPipe() if err != nil { return false, err } var errbuf bytes.Buffer cmd.Stderr = &errbuf if err := cmd.Start(); err != nil { return false, err } if _, err := io.WriteString(stdin, envelope); err != nil { return false, err } stdin.Close() if err := cmd.Wait(); err != nil { return false, log.Errorf("%s: %s", err, strings.TrimSpace(errbuf.String())) } if len(errbuf.String()) > 0 { errstr := strings.TrimSpace(errbuf.String()) if !strings.HasPrefix(errstr, "RESEND:\t") { return false, log.Errorf("ctrlengine: muteproto status output not parsable: %s", errstr) } log.Warn(errstr) resend = true } return }
// GetMessageKey implements corresponding method for msg.KeyStore interface. func (ce *CryptEngine) GetMessageKey( sessionKey string, sender bool, msgIndex uint64, ) (*[64]byte, error) { key, err := ce.keyDB.GetMessageKey(sessionKey, sender, msgIndex) if err != nil { return nil, err } // decode key var messageKey [64]byte k, err := base64.Decode(key) if err != nil { return nil, log.Errorf("cryptengine: cannot decode key for %s", sessionKey) } if copy(messageKey[:], k) != 64 { return nil, log.Errorf("cryptengine: key for %s has wrong length", sessionKey) } return &messageKey, nil }
// SplitEntry splits a base64 encoded key hashchain entry. Specification: // https://github.com/mutecomm/mute/blob/master/doc/keyserver.md#key-hashchain-operation func SplitEntry(entry string) (hash, typ, nonce, hashID, crUID, uidIndex []byte, err error) { e, err := base64.Decode(entry) if err != nil { return nil, nil, nil, nil, nil, nil, log.Error(err) } if len(e) != EntryByteLen { return nil, nil, nil, nil, nil, nil, log.Errorf("hashchain: entry '%s' does not have byte length %d (but %d)", entry, EntryByteLen, len(e)) } // HASH(entry[n]) | TYPE | NONCE | HashID | CrUID | UIDIndex hash = e[:32] typ = e[32:33] nonce = e[33:41] hashID = e[41:73] crUID = e[73:121] uidIndex = e[121:] // check type if !bytes.Equal(typ, Type) { return nil, nil, nil, nil, nil, nil, log.Errorf("hashchain: wrong type 0x%x (should be 0x%x)", typ, Type) } return }
// GetLastHashChainEntry returns the last hash chain entry for the given domain. func (keyDB *KeyDB) GetLastHashChainEntry(domain string) (string, error) { dmn := identity.MapDomain(domain) pos, found, err := keyDB.GetLastHashChainPos(dmn) if err != nil { return "", err } if !found { return "", log.Errorf("keydb: no entry found for domain '%s'", dmn) } entry, err := keyDB.GetHashChainEntry(dmn, pos) if err != nil { return "", err } return entry, nil }
// DelNym deletes the nym mappedID and all associated contacts and messages! func (msgDB *MsgDB) DelNym(mappedID string) error { if err := identity.IsMapped(mappedID); err != nil { return log.Error(err) } unmappedID, _, err := msgDB.GetNym(mappedID) if err != nil { return err } if unmappedID == "" { return log.Errorf("msgdb: nym %s unkown", mappedID) } if _, err := msgDB.delNymQuery.Exec(mappedID); err != nil { return log.Error(err) } return nil }
// GetChainKey implements corresponding method for msg.KeyStore interface. func (ce *CryptEngine) GetChainKey(sessionKey string) (*[32]byte, error) { _, chainKey, _, err := ce.keyDB.GetSession(sessionKey) if err != nil { return nil, err } // decode chain key var key [32]byte k, err := base64.Decode(chainKey) if err != nil { return nil, log.Error("cryptengine: cannot decode chain key") } if copy(key[:], k) != 32 { return nil, log.Errorf("cryptengine: chain key has wrong length") } return &key, nil }
// GetRootKeyHash implements corresponding method for msg.KeyStore interface. func (ce *CryptEngine) GetRootKeyHash(sessionKey string) (*[64]byte, error) { rootKeyHash, _, _, err := ce.keyDB.GetSession(sessionKey) if err != nil { return nil, err } // decode root key hash var hash [64]byte k, err := base64.Decode(rootKeyHash) if err != nil { return nil, log.Error("cryptengine: cannot decode root key hash") } if copy(hash[:], k) != 64 { return nil, log.Errorf("cryptengine: root key hash has wrong length") } return &hash, nil }