/* * encrypt a file using public key cryptography * authenticated secret key version */ static void pubencrypt(const char *pubkeyfile, const char *ident, const char *seckeyfile, const char *msgfile, const char *encfile) { char myident[IDENTLEN]; struct encmsg encmsg; struct pubkey pubkey; struct seckey seckey; uint8_t *msg; unsigned long long msglen; kdf_allowstdin allowstdin = { strcmp(msgfile, "-") != 0 }; getpubkey(pubkeyfile, ident, &pubkey); getseckey(seckeyfile, &seckey, myident, allowstdin); msg = readall(msgfile, &msglen); memcpy(encmsg.encalg, ENCALG, 2); memcpy(encmsg.pubfingerprint, pubkey.fingerprint, FPLEN); memcpy(encmsg.secfingerprint, seckey.fingerprint, FPLEN); pubencryptmsg(msg, msglen, encmsg.box, pubkey.enckey, seckey.enckey); explicit_bzero(&seckey, sizeof(seckey)); writeencfile(encfile, &encmsg, sizeof(encmsg), myident, msg, msglen); xfree(msg, msglen); }
/* * encrypt a file using public key cryptography * ephemeral key version that discards sender key pair */ static void ekpubencrypt(const char *pubkeyfile, const char *ident, const char *msgfile, const char *encfile) { struct ekcmsg ekcmsg; struct pubkey pubkey; uint8_t *msg; unsigned long long msglen; uint8_t enckey[ENCSECRETBYTES]; getpubkey(pubkeyfile, ident, &pubkey); crypto_box_keypair(ekcmsg.pubkey, enckey); msg = readall(msgfile, &msglen); memcpy(ekcmsg.ekcalg, EKCALG, 2); memcpy(ekcmsg.pubfingerprint, pubkey.fingerprint, FPLEN); pubencryptmsg(msg, msglen, ekcmsg.box, pubkey.enckey, enckey); explicit_bzero(&enckey, sizeof(enckey)); writeencfile(encfile, &ekcmsg, sizeof(ekcmsg), "<ephemeral>", msg, msglen); xfree(msg, msglen); }
char *getpubkey_func(char *sender,int32_t valid,cJSON **objs,int32_t numobjs,char *origargstr) { char NXTACCTSECRET[512],addr[256],*retstr = 0; copy_cJSON(addr,objs[1]); copy_cJSON(NXTACCTSECRET,objs[2]); if ( sender[0] != 0 && valid != 0 && addr[0] != 0 ) retstr = getpubkey(sender,NXTACCTSECRET,addr); else retstr = clonestr("{\"result\":\"invalid getpubkey request\"}"); return(retstr); }
/* * message followed by signature in one file */ static void verifyembedded(const char *pubkeyfile, const char *sigfile, int quiet) { char ident[IDENTLEN]; struct sig sig; struct pubkey pubkey; uint8_t *msg; unsigned long long msglen; uint8_t *msgdata; unsigned long long msgdatalen; char *begin, *end; const char *beginreopmsg = "-----BEGIN REOP SIGNED MESSAGE-----\n"; const char *beginreopsig = "-----BEGIN REOP SIGNATURE-----\n"; const char *endreopmsg = "-----END REOP SIGNED MESSAGE-----\n"; msgdata = readall(sigfile, &msgdatalen); if (strncmp(msgdata, beginreopmsg, strlen(beginreopmsg)) != 0) goto fail; begin = msgdata + 36; if (!(end = strstr(begin, beginreopsig))) goto fail; *end = 0; msg = begin; msglen = end - begin; begin = end + 31; if (!(end = strstr(begin, endreopmsg))) goto fail; *end = 0; begin = readident(begin, ident); if (b64_pton(begin, (void *)&sig, sizeof(sig)) != sizeof(sig)) goto fail; getpubkey(pubkeyfile, ident, &pubkey); verifymsg(&pubkey, msg, msglen, &sig, quiet); free(msgdata); return; fail: errx(1, "invalid signature: %s", sigfile); }
/* * simple case, detached signature */ static void verifysimple(const char *pubkeyfile, const char *msgfile, const char *sigfile, int quiet) { char ident[IDENTLEN]; struct sig sig; struct pubkey pubkey; unsigned long long msglen; uint8_t *msg; msg = readall(msgfile, &msglen); readkeyfile(sigfile, &sig, sizeof(sig), ident); getpubkey(pubkeyfile, ident, &pubkey); verifymsg(&pubkey, msg, msglen, &sig, quiet); free(msg); }
void NodeConnection::Listener() { try { while(this->Socket != SOCKET_ERROR) { Packet packet; packet.getCommand(this->Socket); //printf("%s\n", packet.command); //this printf are not really thread save, and they are only needed for debug if (!strcmp(packet.command, "pong")) //just a keep alive { packet.sendData(this->Socket); //resending it }else if(!strcmp(packet.command,"version")) { packet_version version(packet); this->Version = version.version; }else if(!strcmp(packet.command,"verack")) { packet_verack verack(packet); verack.sendData(this->Socket); //empty addr for now packet_addr addr; addr.addr_list.clear(); addr.encodeData(); addr.setChecksum_Lenght_Magic(); addr.sendData(this->Socket); //empty inv for now, this should be the whole list of object hash bool finished = false; vector<sTag> inventory; std::shared_lock<std::shared_timed_mutex> mlock(bitmrc->sharedObj.mutex_); for (int i = 0; i < bitmrc->sharedObj.Dim; i++) { hash_table<ustring>::linked_node * cur = bitmrc->sharedObj.Table[i]; while (cur != NULL) { sTag hash; memcpy(hash.ch, cur->hash.c_str(), 32); inventory.push_back(hash); cur = cur->next; } } mlock.unlock(); unsigned int i = 0; while (!finished) { packet_inv inv; while (i < 50000 && i < inventory.size()) { inv.inventory.push_back(inventory[i]); i++; } inv.encodeData(); inv.setChecksum_Lenght_Magic(); inv.sendData(this->Socket); if (i == inventory.size()) finished = true; } this->state = 2; }else if(!strcmp(packet.command,"addr")) { packet_addr addr(packet); for(unsigned int i=0;i<addr.addr_list.size();i++) { if(addr.addr_list[i].IPv6_4[11] == 0xff && addr.addr_list[i].IPv6_4[10] == 0xff) { char buf[40]; sprintf(buf,"%i.%i.%i.%i", addr.addr_list[i].IPv6_4[12], addr.addr_list[i].IPv6_4[13], addr.addr_list[i].IPv6_4[14], addr.addr_list[i].IPv6_4[15]); string ip(buf); //printf("%s\n",buf); sprintf(buf, "%i", addr.addr_list[i].port); string port(buf); NodeConnection *tmp_node= new NodeConnection(ip,port, this->bitmrc); this->bitmrc->connectNode(tmp_node); } } }else if(!strcmp(packet.command,"inv")) { packet_inv inv(packet); packet_getdata needed; for (unsigned int i = 0; i < inv.inventory.size(); i++) { ustring tag; for (int j = 0; j < 32; j++) { tag += inv.inventory[i].ch[j]; } if (this->bitmrc->sharedObj.searchByHash(tag).empty()) { needed.inventory.push_back(inv.inventory[i]); } } if (!needed.inventory.empty()) { needed.encodeData(); needed.setChecksum_Lenght_Magic(); Packets.push(needed); } }else if(!strcmp(packet.command,"getdata")) { packet_getdata getdata(packet); for (unsigned int i = 0; i < getdata.inventory.size(); i++) { ustring tag; for (int j = 0; j < 32; j++) { tag += getdata.inventory[i].ch[j]; } ustring ObjPayload = this->bitmrc->sharedObj.searchByHash(tag); if (!ObjPayload.empty()) { object obj; memset(obj.command, 0x00, sizeof obj.command); strncpy(obj.command, "object", 7); obj.message_payload = ObjPayload; obj.setChecksum_Lenght_Magic(); Packets.push(obj); } } }else if(!strcmp(packet.command,"object")) { object obj(packet); bool check = checkPow(obj.message_payload, obj.Time); //if not ignore if (check) { ustring invHash = this->bitmrc->inventoryHash(obj.message_payload); int present = this->bitmrc->sharedObj.insert(obj.message_payload, invHash); sTag tag; memcpy(tag.ch, invHash.c_str(), 32); this->bitmrc->new_inv.push(tag); if (obj.objectType == type_getpubkey) { packet_getpubkey getpubkey(obj); std::shared_lock<std::shared_timed_mutex> mlock(this->bitmrc->mutex_priv); for (unsigned int i = 0; i < this->bitmrc->PrivAddresses.size(); i++) { ustring tag = this->bitmrc->PrivAddresses[i].getTag(); if (getpubkey.tag == tag) { if(this->bitmrc->PrivAddresses[i].getLastPubKeyRequest() + 60 * 60 * 24 * 4 < time(NULL)) this->bitmrc->sendObj(this->bitmrc->PrivAddresses[i].encodePubKey(),true); //else //printf("PubKey already shared recently"); } } mlock.unlock(); } else if (obj.objectType == type_pubkey) { packet_pubkey pubkey(obj); std::shared_lock<std::shared_timed_mutex> mlock(this->bitmrc->mutex_pub); for (unsigned int i = 0; i < this->bitmrc->PubAddresses.size(); i++) { if (!this->bitmrc->PubAddresses[i].waitingPubKey()) continue; ustring tag = this->bitmrc->PubAddresses[i].getTag(); if (pubkey.tag == tag) { this->bitmrc->PubAddresses[i].decodeFromObj(pubkey); } } mlock.unlock(); } else if (obj.objectType == type_msg) { packet_msg msg(obj); if (this->bitmrc->decryptMsg(msg)) //it takes like 1-4 milliseconds { //printf("Message accepted\n"); } } else if (obj.objectType == type_broadcast) { packet_broadcast broadcast(obj); if (this->bitmrc->decryptMsg(broadcast)) { //printf("broadcast decrypted\n"); } } } } } }catch(int e) { switch(e) { case CONNECTION_CLOSED: case CONNECTION_ERROR: this->Close(); return; } } }
/* * decrypt a file, either public key or symmetric based on header */ static void decrypt(const char *pubkeyfile, const char *seckeyfile, const char *msgfile, const char *encfile) { char ident[IDENTLEN]; uint8_t *encdata; unsigned long long encdatalen; uint8_t *msg; unsigned long long msglen; union { uint8_t alg[2]; struct symmsg symmsg; struct encmsg encmsg; struct ekcmsg ekcmsg; } hdr; struct pubkey pubkey; struct seckey seckey; uint8_t symkey[SYMKEYBYTES]; char *begin, *end; int fd, rounds, rv; const char *beginreopmsg = "-----BEGIN REOP ENCRYPTED MESSAGE-----\n"; const char *beginreopdata = "-----BEGIN REOP ENCRYPTED MESSAGE DATA-----\n"; const char *endreopmsg = "-----END REOP ENCRYPTED MESSAGE-----\n"; encdata = readall(encfile, &encdatalen); if (strncmp(encdata, beginreopmsg, strlen(beginreopmsg)) != 0) goto fail; begin = readident(encdata + 39, ident); if (!(end = strstr(begin, beginreopdata))) goto fail; *end = 0; if ((rv = b64_pton(begin, (void *)&hdr, sizeof(hdr))) == -1) goto fail; begin = end + 44; if (!(end = strstr(begin, endreopmsg))) goto fail; *end = 0; msglen = (strlen(begin) + 3) / 4 * 3 + 1; msg = xmalloc(msglen); msglen = b64_pton(begin, msg, msglen); if (msglen == -1) goto fail; if (memcmp(hdr.alg, SYMALG, 2) == 0) { kdf_allowstdin allowstdin = { strcmp(encfile, "-") != 0 }; kdf_confirm confirm = { 0 }; if (rv != sizeof(hdr.symmsg)) goto fail; if (memcmp(hdr.symmsg.kdfalg, KDFALG, 2) != 0) errx(1, "unsupported KDF"); rounds = ntohl(hdr.symmsg.kdfrounds); kdf(hdr.symmsg.salt, sizeof(hdr.symmsg.salt), rounds, allowstdin, confirm, symkey, sizeof(symkey)); symdecryptmsg(msg, msglen, hdr.symmsg.box, symkey); explicit_bzero(symkey, sizeof(symkey)); } else if (memcmp(hdr.alg, ENCALG, 2) == 0) { kdf_allowstdin allowstdin = { strcmp(msgfile, "-") != 0 }; if (rv != sizeof(hdr.encmsg)) goto fail; getpubkey(pubkeyfile, ident, &pubkey); getseckey(seckeyfile, &seckey, NULL, allowstdin); /* pub/sec pairs work both ways */ if (memcmp(hdr.encmsg.pubfingerprint, pubkey.fingerprint, FPLEN) == 0) { if (memcmp(hdr.encmsg.secfingerprint, seckey.fingerprint, FPLEN) != 0) goto fpfail; } else if (memcmp(hdr.encmsg.pubfingerprint, seckey.fingerprint, FPLEN) != 0 || memcmp(hdr.encmsg.pubfingerprint, seckey.fingerprint, FPLEN) != 0) goto fpfail; pubdecryptmsg(msg, msglen, hdr.encmsg.box, pubkey.enckey, seckey.enckey); explicit_bzero(&seckey, sizeof(seckey)); } else if (memcmp(hdr.alg, EKCALG, 2) == 0) { kdf_allowstdin allowstdin = { strcmp(msgfile, "-") != 0 }; if (rv != sizeof(hdr.ekcmsg)) goto fail; getseckey(seckeyfile, &seckey, NULL, allowstdin); if (memcmp(hdr.ekcmsg.pubfingerprint, seckey.fingerprint, FPLEN) != 0) goto fpfail; pubdecryptmsg(msg, msglen, hdr.ekcmsg.box, hdr.ekcmsg.pubkey, seckey.enckey); explicit_bzero(&seckey, sizeof(seckey)); } fd = xopen(msgfile, O_CREAT|O_TRUNC|O_NOFOLLOW|O_WRONLY, 0666); writeall(fd, msg, msglen, msgfile); close(fd); xfree(msg, msglen); return; fail: errx(1, "invalid encrypted message: %s", encfile); fpfail: errx(1, "fingerprint mismatch"); }