// we use PBKDF2 + SHA3 to derive a key out of the entropy with a crypto/rand salt // TODO: implement fortuna to feed the PRNG func CTADD_Handler(acMessageCtReq *AcCipherTextMessageRequest) (acMsgResponse *AcCipherTextMessageResponse, err error) { var responseType AcCipherTextMessageResponseAcCTRespMsgType responseType = AcCipherTextMessageResponse_CTR_ADD reqChan := acMessageCtReq.GetChannel() reqNick := acMessageCtReq.GetNick() reqServ := acMessageCtReq.GetServer() reqBlob := acMessageCtReq.GetBlob() acutl.DebugLog.Printf("(CALL) CTADD %s/%s from %s:'%s' (%s)\n", reqChan, reqServ, reqNick, reqBlob) if len(reqChan) == 0 || len(reqNick) == 0 || len(reqServ) == 0 { retErr := &acutl.AcError{Value: -1, Msg: "CTADD_Handler().args(channel|serv|mynick): 0 bytes", Err: nil} acMsgResponse = &AcCipherTextMessageResponse{ Type: &responseType, Bada: proto.Bool(false), ErrorCode: proto.Int32(-1), } acutl.DebugLog.Printf("(RET[!]) CTADD -> (-1) ! %s\n", retErr.Error()) return acMsgResponse, retErr } // lets derive the key. // randsalt := rand.Read() // func (skgen ACSecretKeyGen) Init(input []byte, channel []byte, nick []byte, serv []byte) { skgen := new(ackp.SecretKeyGen) err = skgen.Init([]byte(reqBlob), []byte(reqChan), []byte(reqNick), []byte(reqServ)) if err != nil { retErr := &acutl.AcError{Value: -2, Msg: "CTADD_Handler(): SK generator fail!", Err: err} acMsgResponse = &AcCipherTextMessageResponse{ Type: &responseType, Bada: proto.Bool(false), ErrorCode: proto.Int32(-2), } acutl.DebugLog.Printf("(RET[!]) CTADD -> (-2) ! %s\n", retErr.Error()) return acMsgResponse, retErr } // XXX TODO: handle error or remove it... acctx, _ := ackp.CreateACContext([]byte(reqChan), 0) key := make([]byte, 32) io.ReadFull(skgen, key) newRnd := make([]byte, len(key)) _, err = rand.Read(newRnd) if err != nil { retErr := &acutl.AcError{Value: -3, Msg: "CTADD_Handler(): randomness fail!", Err: err} acMsgResponse = &AcCipherTextMessageResponse{ Type: &responseType, Bada: proto.Bool(false), ErrorCode: proto.Int32(-3), } return acMsgResponse, retErr } acctx.SetKey(key) // XOR the key... acctx.RndKey(newRnd) ackp.ACmap.SetSKMapEntry(reqServ, reqChan, acctx) ackp.ACmap.SetRDMapEntry(reqServ, reqChan, newRnd) acMsgResponse = &AcCipherTextMessageResponse{ Type: &responseType, Bada: proto.Bool(true), ErrorCode: proto.Int32(0), //Blob: []byte("OK"), Blob: [][]byte{[]byte("OK")}, // this is an array of []byte } acutl.DebugLog.Printf("(RET) CTADD -> (0) ! %s/%s key added (entropy: '%s')\n", reqServ, reqChan, reqBlob) return acMsgResponse, nil }
func OpenKXMessageNACL(peerPubkey, myPrivkey *[32]byte, cmsg, channel, myNick, peerNick []byte) (context *ackp.SecKey, SecRnd []byte, err error) { // check that we are indeed if peerPubkey == nil || myPrivkey == nil { //return nil, acprotoError(-1, "OpenKXMessage().invalidPubPrivKeys(): ", err) return nil, nil, &acutl.AcError{Value: -1, Msg: "OpenKXMessageNACL().invalidPubPrivKeys(): ", Err: err} } b64, err := acutl.B64DecodeData(cmsg) if err != nil { return nil, nil, &acutl.AcError{Value: -2, Msg: "OpenKXMessageNACL(): ", Err: err} } cnonce, myHdr, ciphertext, err := unpackMessageKX(b64) if err != nil { return nil, nil, &acutl.AcError{Value: -3, Msg: "OpenKXMessageNACL(): ", Err: err} } // XXX TODO: exact opposite of the one in CreateKXMessage kx_channel := IsChannelOrPriv(channel, peerNick, myNick) // XXX TODO: we should add the header like <ackx:peerNick> to avoid replay from // other nickname on the channel... nonce building! _, noncebyte, err := BuildNonceKX(cnonce, kx_channel, peerNick, myNick, myHdr) if err != nil { return nil, nil, &acutl.AcError{Value: -4, Msg: "OpenKXMessageNACL(): ", Err: err} } packed, ok := box.Open(nil, ciphertext, noncebyte, peerPubkey, myPrivkey) if ok == false { return nil, nil, &acutl.AcError{Value: -5, Msg: "OpenKXMessageNACL().BoxOpen(): ", Err: nil} } out, err := acutl.DecompressData(packed) if err != nil { return nil, nil, &acutl.AcError{Value: -6, Msg: "OpenKXMessageNACL(): ", Err: err} } //fmt.Fprintf(os.Stderr, "OPEN KX KEY: %s\n", hex.EncodeToString(out)) // XXX TODO are we at the end of the nonce value.. context, err = ackp.CreateACContext(channel, cnonce+1) if err != nil { return nil, nil, &acutl.AcError{Value: -7, Msg: "OpenKXMessage().CreateACContext(): ", Err: err} } // XXX TODO // get RANDOMNESS bytes, return the random bytes newRnd, err := acutl.GetRandomBytes(context.GetKeyLen()) if err != nil { return nil, nil, &acutl.AcError{Value: -8, Msg: "OpenKXMessage() no randomness to protect the key in memory: ", Err: err} } /* newRnd := make([]byte, len(context.key)) _, err = rand.Read(newRnd) */ // XXX TODO: check the extracted buffer size... to sure we're not copying // too much into a restricted buffer... //copy(context.key[:], out) context.SetKey(out) // Xor the key now.. context.RndKey(newRnd) // increase nonce based on the message nonce value context.IncNonce(cnonce) return context, newRnd, nil }