ZeroNet Blogs

Static ZeroNet blogs mirror

Me he dado a la tarea de echarle un vistazo a la documentacion (bastante desordenada) sobre este proyecto y aqui te dejo mis impresiones.



No lo he probado, ni lo hare mientras no haya documentacion minima satisfactoria para el usario.


Esta muy claro, que el proyecto se encuentra en una etapa de desarrollo muy inicial, ya que la informacion que entrega la propia pagina es bastante tecnica y la primera impresion que me entrego fue: "mmm... esto no parece muy facil de llevar a la practica".


Al sumergirme en las diferentes secciones encontre muchisima documentacion, pero no muy ordenada y bastante difusa para poder seguir algun hilo conductor.


Cuando intente seguir los pasos de instalacion... me quede solo hasta la primera ejecucion... ya que ni siquiera se explica con meridiana claridad como continuar, es decir, por ejemplo: comenzar a crear archivos, subirlos a la red, configurar algun proxy, si existe o no algun interface web/grafico de usuario, etc.


Tampoco la ayuda que da el comando ayuda mucho a despejar dudas.


$ ipfs --help
 ipfs - global p2p merkle-dag filesystem
OPTIONS:
 -c, --config string
     - Path to the configuration file to use
 -D, --debug  bool
     - Operate in debug mode
 --help bool
     - Show the full command help text
 -h bool
     - Show a short version of the command help text
 -L, --local bool
    - Run the command locally, instead of using the daemon
 --api string
    - Use a specific API instance (defaults to /ip4/127.0.0.1/tcp/5001)


Y lo mas importante para mi, en ninguna parte se hace mencion si hay intensiones de soportar nativamente alguna forma de proteccion a la identidad y a los canales de comunicacion que usamos. Incluso por el contrario se hace incapie en que nuestros datos son transparentes... lamentablemente ya ni recuerdo en que capitulo o link lo encontre.


Veamos que nos trae el futuro.


ZeroNet博客体验记录

- Posted in NEXT by with comments

终于在ZeroNet上有自己的博客了,而且创建过程非常方便。虽然撰写的过程是用修改的方式来完成的,但是比Twister好的地方是可以修改。 ZeroNet的使用过程还是比较简单的,不需要同步下载区块数据,运行客户端自动打开浏览器,有升级的话也是自动升级,已经将使用的门槛降到最低了。 ZeroNet的发布速度也是不错的,稳定性也很好(至少到目前为止客户端还没因出错强制退出的);只可惜目前的用户数量以及内容还不够丰富,玩家不够多就不够好玩-_-b 不过相信ZeroNet持续开发,会有越来越多的人留在ZeroNet上的。

ZeroNet的最新功能

- Posted in NEXT by with comments

试试之后竟然创建了属于自己的去中心化的博客了ˉ_(ツ)_/ˉ

Si nos vamos a la pagina de ZeroPolls nos encontramos con el siguiente aviso:

Votes are tied to your ZeroID, they are pseudonymous, not anonymous. With a little bit of work someone can find out what you (your ZeroID) voted for


Traducido, siginifica mas o menos:

Tu voto esta asociado a tu ZeroID, que no es anonimo, y por lo tanto cualquiera puede descubrir que has votado

Y si lo pensamos un poco mas detenidamente eso implica que todos tus mensajes emitidos en cualquiera de las paginas de Zeronet estan asociadas a ese ZeroID... entonces saca tus propias conclusiones.

Yo al menos ya venia sospechando algo, pero de alguna forma lo venia omitiendo de forma inconciente.

Muchos pensaran, que son exageraciones, que estoy delirando, que la cuestion no es para nada grave... pero justamente de esto se trata este blog... nuestra seguridad, nuestra privacidad, en definitiva, la proteccion de nuestra identidad y nuestros movimientos en la red.

Bitcoin probablemente salto a la fama (si mal no recuerdo) entre los meses de diciembre de 2012 y mayo de 2013. Meses en los que su valor llego a cambiar de 0,95 USD a mas de 700 USD por unidad.

Para muchos significo el despegue definitivo, para otros una oportunidad de obtener utilidades muy rapidas. Tambien muchos consiguieron salvar sus fortunas al moverlas rapidamente de zonas controladas a otras mas "libres"... y no faltaron los que se arruinaron.


Medidas de Seguridad Basicas

  1. Evitar instalar Bitcoin en una maquina con Windows
  2. Evitar usar monederos online
  3. Hacer respaldos del monedero en algun dispositivo externo
  4. Aprender un poco de GnuPG/PGP
  5. Proteger nuestra identidad en las transacciones

Instalar Bitcoin en Linux

Si, una medidad de seguridad muy eficaz es instalar y usar cualquier aplicacion sensible a la seguridad en Linux. Recuerdese solo un detalle no poco importante:

Todas las claves de todo tipo, en las ultimas versiones de Windows, son automaticamente enviadas, sin informar al usuario, a la central de Microsoft

Y si a esto se suman las recientes escaramuzas entre la empresa Apple y algunos gobiernos locales de su pais de origen, que le estan exigiendo abrir nuevas puertas de acceso a los datos personales de sus usuarios, no esta quedando sistema comercial confiable.

Con buscar un poco en la prensa se podra comprobar que casi ninguna aplicacion comercial dedicada a la seguridad que sea realmente muy confiable.

Siempre usar un monedero local

El abrir un monedero en internet y guardar nuestros bitcoins ahi implica que estamos confiando en que ese servicio nunca hara mal uso de nuestros fondos.

Ya en el pasado ha sucedido que servicios en linea han desaparecido o se han declarado en quiebra sin responder en parte o en la totalidad de los recursos que los usuarios habian depositado en sus servidores.

Aconsejo retirar y guardar los fondos siempre que se pueda en monederos locales.

Respaldar es una de las mejores medidas

Tomese en cuenta que el monedero es necesario solo para operaciones de transferencia a terceros, de lo contrario no es necesario ni siquiera dejarlo guardado en nuestra computadora.

Todas las consultas que queramos hacer a nuestro saldo o a los movimientos de nuestra cartera, se pueden realizar directamente en cualquier blockchain.

GnuPG, la llave a nuestros secretos

GnuPG es probablemente la herramienta mas segura, que nos permite usar casi todos los algoritmos de cifrado, es decir, GnuPG no es un algoritmo en si, sino que simplemente nos ayuda a interactuar con ellos.

GnuPG trabaja basicamente con el concepto de cifrado asimetrico, en donde cada parte crea y administra 2 llaves: Una privada (secreta), otra publica (para compartir con todos) y una clave de paso o apertura.

El procedimiento es simple: Alicia le entrega su llave publica a Pedro y este le envia la suya a Alicia. Si Alicia quiere enviarle un archivo y/o mensaje cifrado a Pedro necesitara justamente esa llave Publica (de Pedro) para identificar al destinatario unico. Cuando Pedro recibe el mensaje de Alicia solo lo podra abrir usando su propia llave Privada mas la clave de paso.

_Las llaves Publica y Privada son, por asi decirlo, 2 partes de una misma superllave que solo se abre con una clave de paso_

Deberiamos usar GnuPG para todas nuestras comunicaciones e intercambio de datos que hagamos con todos nuestros contactos. Es una necesidad proteger nuestra privacidad, es decir, que nadie mas pueda conocer el contenido de lo que conversamos o lo que intercambiamos.

GnuPG deberia ser el estandar en todas las comunicaiones, incluyendo tambien al P2P.

Problemas de privacidad e identidad

OK, este punto no tiene directa relacion con la seguridad de nuestros fondos, pero de forma indirecta tambien deseamos que nuestras transacciones queden en el anonimato... al fin y al cabo a nadie le gusta que por culpa de una compra mal hecha quedemos marcados por el fisco o la policia.

Bitcoin tiene la facultad de funcionar y hacer transacciones a traves de Tor y esto no deberiamos olvidar nunca, es decir, deberiamos configurar nuestro cliente de Bitcoin para que todas las transacciones se realicen a traves de la onion. Esta funcion no tiene ninguna desventaja.

Cada transaccion deja rastros que permiten a los expertos poder reconstruir el origen y el destino geograficos de los mismos.

Con la ayuda de la cebolla, algunos de estos rastros simplemente desaparecen.

Conclusion

Estoy convencido que Bitcoin posee todas las caracteristicas necesarias para imponerse en la economia, solo que no me gustan las razones que algunos arguyen para intentar imponerlo.

Si vamos a tener que convivir con el, entonces sera necesario aprender a como cuidarlo y no dejar que nadie, ni nada nos pueda robar.

En proximas entregas intentare esclarecer un poco mas algunos puntos para ayudar a trabajar con Bitcoin y GnuPG de forma facil, tanto desde la linea de comandos como con la ayuda de algun asistente grafico.

Changelog, July 25, 2015

- Posted in ZeroBlog by with comments

  • Rev 324
    • Cleanup peers if not found in last 4 hours on tracker or via PEX
    • Experimental option to download to temporary files instead of memory
    • Experimental option to stream downloads out of msgpack context
    • Don't reopen OpenSSL lib on every 5 min
    • Peer getFile benchmark option
    • Fix UiPassword plugin cleanup bug

ZeroTalk

  • Domain changed to the brand-new, ZeroID based and cloning supported version
  • Sticky topic support

ZeroBlog

  • Fixed latest chrome display flickers

ZeroChat


重发:中国人历史观的几个笑柄


由于写史的原因,常与国人谈论历史,当然免不了争得面红耳赤的时候。一开始还以为是国人接收的历史信息出了问题,久而久之,发现问题并不仅仅在于信息的吸收,而是在于思维方式本身出了问题,今晚闲暇,特下笔谈谈这个问题,提醒一下,所谓诤友,知无不言,希望能使国人开窍一些,聪明一点,别再自欺欺人。


笑柄一:“我可以反帝,你不能独立”


中国有不少所谓的文化人、历史爱好者,每当谈起外蒙古独立这段历史,往往不约而同地发表这么两点看法:1、国民政府无能,丢掉了外蒙古;2、新中国太反动了,竟然支持外蒙古独立。

这些所谓“文化人”,在说这些话的时候,显然有一个假设的前提:外蒙古自古以来属于中国,外蒙古人民独立是非法的。

事实上呢?——事实上,外蒙古在明朝乃至以前,都不是中国人的地盘,外蒙古在清朝初年归顺了大清帝国,是慑于大清帝国的武力,1912年大清帝国通过《清帝退位诏书》、将外蒙古“转让”给中华民国,这件事并没有征得外蒙古人民的同意,外蒙古人民显然是有权不接受的。换句话说,外蒙古人民有权独立。掷地有声。

中国近代史的一个主旋律是:反帝救国,独立自主。中国人要反对殖民,要争取独立,对不对?很对。但是一谈到外蒙古人民要争取独立,我们的“爱国”青年立马就翻脸了,为什么翻脸呢?因为我们的“爱国”青年认为:只有我们中国人才可以独立,你们外蒙古人也想独立?啊呸,做梦吧你。

我可以反帝,你不能独立。州官可以放火,百姓不能点灯——这就是某些“爱国”历史爱好者的嘴脸。

外蒙古人从前是外蒙古人,后来是清国人,但是他们从来就不是中国人,他们也有权选择不做中国人——中国人民有权争取独立,外蒙古人民也有权争取独立,大家都是人,人人平等。我可以反帝,你不能独立,这是双重标准、强盗逻辑,这个问题必须要清醒对待,否则中国人一不小心就会沦为自己一直批判的帝国主义,某些“爱国”文化人,有空不妨照照镜子,看看镜子里面的那个人,像不像当年的日本鬼子?大家都是扩张主义者。五十步笑一百步,仅此而已。

笑柄二:“我可以杀出去,你不能打进来”

鸦片战争研究难免谈到一个问题:林则徐的禁烟举措有没有失当之处?但是谈到这里,往往有“爱国”历史爱好者跳出来,作义愤填膺状,抗议道:“这有什么好谈的?英国人派兵杀到我国境内,就是它不对,任何理由它都不能杀进来,一杀进来,它就是侵略者”——每当这些声音出现,一些学养不够的人往往被压得大气不敢出——无论任何原因,A国都不能出兵B国,否则A国就是侵略者。但是当你反驳他:“按照你的道理,1979年中国出兵越南,请问中国是不是侵略者”?这个时候,他往往急得大汗淋漓,无话可说,手足无措,热锅蚂蚁,丑态百出。

可见,这种“爱国”的论调,只是听起来似乎对,实际上是错的。因为如果无论任何原因,A国都不能出兵B国,否则A国就是侵略者。那么很显然,中国在历史上,也曾经当过N次的“侵略者”,1918年,北洋政府出兵俄国,打到了别人的国土上,是不是侵略?1950年,王师跨过鸭绿江,造成人家民族分裂,这又是什么?1979年,自卫反击,打到了越南的首都周边,这又叫什么呢?不要忘记,1950年、1979年两次出兵境外,国际上是一片谴责之声。不信?查资料去吧。

你知道吗?1992年中韩建交,中国第一任驻韩大使在汉城举办记者招待会,立马遭到了韩国记者的刁难——韩国记者要求中国大使对1950年的“侵韩行为”进行道歉——试问在韩国人的眼中,1950年中国的行为是什么性质?

1979年我军杀进越南的国土时,三大注意,八项纪律,帮越南老百姓挑水割禾,换来了什么?换来的是越南老百姓的冷枪。为什么呢?因为在越南人的眼中,我们就是“侵略者”。看看当年越南政府是怎样宣传“中国侵略者”的:

“北寇(中国)妄图侵占邻邦的领土,以遂其称霸亚洲的狂妄野心,(越共)党中央和政府号召全体军民再次奋起反抗外族侵略”

看清楚了吧,在1979年的时候,我们中国人是“北寇”,我们被越南人视为侵略者,不为什么,因为我们杀进了别人的国土。

中国在近代史上,的确主要是扮演了一个受害者的角色,但是在历史的某些时刻,我们同时也扮演过加害者的角色,只是你不了解、不承认、不敢去面对罢了。我们在谈论历史的时候,大可以谴责帝国主义侵略者,但是“A国出兵B国就是侵略”这种话语是不能成立的,因为我们也曾经出兵他国、揍过人家,这种石头搬起来,一不小心就砸了自己的脚趾头——我不是叫你不说话,我是教你说话放聪明点,这个世界上,其实谁都不干净,千万不要以为别人都是豺狼、而唯独自己是个天使。

笑柄三:“你的也是我的,自古以来都是我的”

中国的“爱国”文化人,每当谈到领土问题,最常用的一句就是——“自古以来属于中国”——什么叫做“自古”?要多“古”才算“古”?而“中国”这个概念又是什么时候出现的?“中国”概念的涵义是动态的还是静态的?其实,这里面大有文章。

我举台湾岛做例子吧。我们的“爱国”青年最喜欢说:“台湾岛自古以来属于中国”,问题是——这是一句谎言——台湾岛自古以来并不属于中国,据说三国时期孙权的部队到达过台湾,但这并不能证明台湾属于中国——马可波罗还到达过中国呢,这能证明中国属于意大利么?

此外,明朝时期设置的“澎湖巡检司”也仅仅覆盖了澎湖列岛,并未能覆盖台湾本岛,中国人在台湾岛上实施有效统治,其实是从康熙年间才开始的,在此之前,中国人并未管治过台湾岛。

怎么回事呢?原来,台湾岛在历史上原本是属于原住民的地盘,岛上曾经有原住民建立过“大肚王国”之类的部落国家,后来是荷兰殖民者来了,设置了荷兰殖民政府,再后来才是郑成功武力打败了荷兰人、从荷兰人手中抢到了台湾,再后来,才是大清国打败了郑氏王朝、才正式将台湾岛并入中国版图的。

换句话说,台湾岛并不是“自古以来属于中国”,而是中国人自己动手打来的,甚至说难听点,是抢来的——如果非要说台湾岛自古以来属于谁的话,那么它首先自古以来属于岛上的原住民,其次才属于荷兰人,再其次才轮到中国人。

台湾岛的历史其实是一个很好的例子,它说明了一个很明确但是又很残酷的历史事实:这个世界上,没有任何一块地盘是自古以来属于哪个国家,中国人的地盘和世界上其他民族的地盘一样,都是自己打来的,中国人在历史上为了扩张自己的地盘,不断地发动战争,不断地灭亡别人的国家,例如什么大理国、南越国、准噶尔汗国、中山国、巴国……这个被中国人灭掉的国家名单,还很长很长——中国人就是在不断的武力扩张中、逐渐壮大自己的生存空间。因此,我们的“爱国”文化人,千万不要以为别人都是豺狼、唯独自己是个天使,这个世界上一切的民族和国家,在本质上都是自私的——中国人并不能例外。话很赤裸,但是很真实。

没有什么“自古以来”,人类生存的地盘,在历史上一直处于一个变动的状态,今天是你的,明天是我的,任何一个地盘的变更历史,都是有迹可寻的,“自古以来”并不是什么真理,而是流氓的避难所,仅此罢了。

笑柄四:“我可以欺负你,你不能欺负我”

中国的近代史教育奉旨向孩子们灌输这么一个观念:中国在近代史上,是一个爱好和平的国家,同时也是一个受人欺负的国家。

今天,请容我讲一句真话:事实上从清末开始,中国已经走上了帝国主义道路,之所以没走成,仅仅是因为内乱,因为不争气,实际上清末已经开始在走帝国主义的霸道之路了,我举几个事例:

事例一:1882年的时候,大清帝国发现自己的属国朝鲜的日本人越来越多,大清帝国感觉到自己在朝鲜的优越地位将来可能要受到日本帝国的挑战,为了加强对朝鲜的控制,大清帝国要求朝鲜签署了不平等条约《中朝商民水陸貿易章程》,里面约定了中国人在朝鲜享有治外法权,紧接着,大清帝国又要求在朝鲜设立清国租界,一连设立了好几个清租界:仁川清租界、釜山清租界、元山清租界等。与此同时,大清帝国还在朝鲜加强了驻兵。治外法权,租界,驻兵…….这些都是所谓“帝国主义”的典型行为。千万不要告诉我,大清的这个行为和英帝国主义、日本帝国主义有什么本质的区别。

事例二:1911年,墨西哥爆发排华事件,清廷立马电令大清海军“海圻号”向墨西哥进发、保护清国侨民,在大清帝国枪炮的威慑之下,墨西哥政府选择妥协、向清国道歉赔偿。看,自己的侨民在别人的国土上受欺负,立马派军队前去威吓别人,这是什么行为?这是典型的帝国主义行为。千万不要告诉我,大清帝国的这个行为和英帝国主义、日本帝国主义有什么本质的区别。

事例三:1917年俄国爆发了十月革命,建立了“苏维埃俄国”,西方帝国主义列强决定出兵干涉,1918年,中华民国北洋政府派兵、参加了帝国主义出兵俄国境内、武装干涉苏维埃俄国的军事行动,这个事件在历史上叫做“西伯利亚干涉”——你没有看错,中国曾经派兵到俄国境内、武装干涉俄国的内政,这是历史事实,白纸黑字记录的历史事实,只不过是被淡忘了。出兵他国,干涉别国内政,这也是典型的帝国主义行为,不要告诉我不是。

还有一个更众所周知的历史事件:甲午战争。与我们的认知不同,甲午战争其实并不是一场保家卫国的战争,而是大清帝国和日本帝国为了争夺朝鲜控制权而爆发的战争,至少在朝鲜人民的眼中,甲午战争不过是清帝国主义和日本帝国主义之间狗咬狗的战争而已。日本控制朝鲜不对,但大清帝国控制朝鲜就对吗?换位思考,想想便知。再告诉你一个鲜为人知的事实:甲午战争爆发时,你知道当时国际上的舆论偏向谁吗?答案令你大跌眼镜:当时国际上的舆论是倾向日本,当时西洋人多数认为大清帝国无理。没想到吧。

这一类的事例,还可以列举很多。我们从这些事例可以看出来,在当年帝国主义的潮流中,清末民初的中国政府,已经加入了帝国主义的阵营、并且正在走帝国主义的道路,帝国主义在中国所干的那些欺负人的事情,晚清政府、北洋政府都已经开始干了,并且还干的相当出彩——历史告诉我们:中国人并不是吃素的,千万不要以为中国人是一副祥林嫂的窝囊样,中国人并不是不想走帝国主义道路,只是由于内乱没走成而已,在历史上,哪怕是在近代史上,中国人欺负别人的历史事实,不是没有,只是你不知道。

笑柄五:“我总是对的,但不知道为什么”

我曾经在深圳的出租汽车里与司机谈到钓鱼岛问题,司机说钓鱼岛是中国的,要杀光小日本。我半开玩笑似地问他:为什么钓鱼岛是中国的?那司机被我一问,停顿了一下,答:当然是中国的,还用问么?我继续追问他:我还真不知道,愿意请教,洗耳恭听。司机沉默了好久,才蹦出了一句:我也不知道为什么,总之就是我们的。

事过多年,每当想起这个深圳司机,我仍然有一种想笑的感觉。这个司机其实并不是一个特例,想当年砸车的“爱国”青年们,你要问他“为什么钓鱼岛属于中国”,我想他们99%的人都答不上来,先把车砸了再说,别问我为什么。

你相信你钱包里的钱属于你,为什么?因为那是你刚刚发的工资。你相信你的房子属于你,那是因为房子是你出钱买的。你相信你的配偶属于你,那是因为你和她有结婚证。你相信任何一个事物属于你,你必然能说出它的理由,如果你不能说出个理由,那么说明你并不确定它属于你。而如果你不知道一个事物为什么属于你,但言行上又坚决声明它属于你,那么说明你的思想出了问题——这是病,得治。

一百年前女孩子缠足,旁人问她为什么缠足,她说不知道,因为旁人都说缠足是对的,所以我也觉得它是对的。七十八年前日本人民列队欢送乡间子弟出征支那,你问他们为什么,他们也不知道,他们只知道“为国打仗就是对的”——这些都是病,得治。

稍有理智的人都应该知道:如果你不知道钓鱼岛为什么属于中国,那么你就应该闭嘴。而如果你真的忧国忧民,那么你应该立马搜集关于钓鱼岛的历史材料,正反双方的观点和证据都要了解清楚了,确信“钓鱼岛属于中国”了,到了那个时候,你再四处高唱“钓鱼岛属于中国”,没有任何问题。问题是当你不了解钓鱼岛历史的时候,却还要振振有词地声称“钓鱼岛属于中国”,但当别人问你为什么,而你又答不上来,这个时候在别人的眼中,你已经退化为一只猴子了。

一个合格的人,首先应该是一个诚实的人、一个正直的人。任何一件事,你知道就是知道,不知道就是不知道。一个东西,属于你就是属于你,不属于你就是不属于你,而当你不确定一个东西属不属于你,你最合适的答案是:我不知道。而你既然不知道,又要斩钉截铁地说它属于你,这个时候,你从精神上已经沦为了一名盗匪。


En mi deambular por las redes invisibles he tenido la oportunidad de probar muchas herramientas de mensajeria y algunas de ellas son: TorChat, Ricochet, Tox, I2PTalk, I2PMessenger.


TorChat & Ricochet

Ambas herramientas se han desarrollado basandose en el mismo concepto: Usar la red Tor para comunicar a los nodos.

Al ejecutar por primera vez el cliente de mensajeria (TorChat o Ricochet), se iniciara un core Tor local especialmente configurado para crear una direccion .onion que a la vez sera nuestra direccion de contacto.

En TorChat nuestra direccion de contacto es la primera parte de direccion.onion mientras que en Ricochet sera ricochet:direccion.

Al final toda la comunicacion entre clientes se realizara dentro de Tor, es decir, de forma anonima y descentralizada.

Al no depender de servidor alguno, cada cliente es responsable por la supervivencia de la red.

TOX

TOX es una red de mensajeria P2P descentralizada que se centra en la privacidad, es decir, en proteger de miradas indiscretas los canales de comunicacion y sus contenidos.

Por otra parte, configurando TOX para usar Tor puede llegar a conseguirse mantener anonimo, es decir, proteger la identidad de cada uno de los nodos que toman parte en las conversaciones.

Al ejecutarse por primera vez, la aplicacion nos generara una direccion de largo 32 caracteres.

A diferencia de los anteriores clientes, este soporta videoconferencia y salas de chat para varios participantes. Obviamente se debe usar con mucho cuidado, ya que la falta de soporte completo para la proteccion de la identidad de los nodos participantes puede convertirnos en potenciales objetivos de criminales y/o la policia.

I2PTalk & I2PMessenger

  • Ambos clientes, al igual que en el caso de Ricochet y TorChat, son muy similares entre si.

  • Ambos clientes necesitan de un nodo I2P instalado y en ejecucion.

  • Ambos clientes son descentralizados, anonimos y privados, es decir, no dependen de servidor alguno y protegen tanto las comunicaciones entre clientes como la identidad de los participantes.

  • En ambos se genera un ID unico, pero podemos agregarle un nick que ayudara a otros poder encontrarnos, siempre y cuando nos mantengamos en linea.

  • Ambos soportan transferencia de archivos.

  • I2PTalk esta escrito en .NET, pero se deja ejecutar en Linux con ayuda de Mono.

  • I2PMessenger esta escrito en QT.

  • Ambos proyectos han dejado de generar actualizaciones y se consideran suficientemente maduros.

Conclusion

En la actualidad existen suficientes alternativas para la mensajeria instantanea descentralizada... solo hay que comenzar a usarlas activamente.

Ojala en el futuro todas pudieran interactuar entre si, para facilitar la integracion, sin perder proteccion.

In part1 we created a ZeroNet site with some simple ZeroFrame API call.

We going to extend it to accept, store and query messages using a SQLite database and use ZeroID to identify user names.

The final page and source code is available at https://www.zerogate.tk/1AvF5TpcaamRNtqvN1cnDEWzNmUtD47Npg


Adding ZeroID user selector

Add a new link to index.html that will allow us to select the ZeroID identity we want to use:

<html>
<body>
<a href="#Select+user" id="select_user" onclick='return Page.selectUser()'>Select user</a>:
<input type="text" id="message"><input type="button" id="send" value="Send!"/>
<ul id="messages">
 <li>Welcome to ZeroChat!</li>
</ul>
<script type="text/javascript" src="js/all.js" async></script>
</body>
</html>

To make it work add a function to js/ZeroChat.coffee that displays the certificate selection dialog to user:

    selectUser: =>
        Page.cmd "certSelect", [["zeroid.bit"]]
        return false

As parameter you should include the accepted certificate provider names. (zeroid.bit here)

If you hit a refresh and click on "Select user", then you should see the dialog, but nothing changes when you select your zeroid certificate.

Display user's current ZeroID account

When something is changed that affects the site (new content arrived, user changed, etc.) a websocket event will be pushed to your browser. (the format is same as you query setSiteInfo command)

To handle this event add this function:

    route: (cmd, message) ->
        if cmd == "setSiteInfo"
            if message.params.cert_user_id
                document.getElementById("select_user").innerHTML = message.params.cert_user_id
            else
                document.getElementById("select_user").innerHTML = "Select user"
            @site_info = message.params  # Save site info data to allow access it later

This code will real-time update the user's currently selected user name.

To also update the user name on page load modify the onOpenWebsocket function:

    onOpenWebsocket: (e) =>
        @cmd "serverInfo", {}, (server_info) =>
            @addLine "serverInfo response: <pre>" + JSON.stringify(server_info,null,2) + "</pre>"
        @cmd "siteInfo", {}, (site_info) =>
            @addLine "siteInfo response: <pre>" + JSON.stringify(site_info,null,2) + "</pre>"
            # Update currently selected username
            if site_info.cert_user_id
                document.getElementById("select_user").innerHTML = site_info.cert_user_id
            @site_info = site_info  # Save site info data to allow access it later

Setting user content permissions

To allow users to post on our site we have to define the rules of the third-party content.

Create a data/users directory and create a data/users/content.json file in it:

{
  "files": {},
  "ignore": ".*",
  "modified": 0.0,
  "signs": {},
  "user_contents": {
    "cert_signers": {
      "zeroid.bit": [ "1iD5ZQJMNXu43w1qLB8sfdHVKppVMduGz" ]
    },
    "permission_rules": {
      ".*": {
        "files_allowed": "data.json",
        "max_size": 10000
      },
      "bitmsg/.*@zeroid.bit": { "max_size": 15000 }
    },
    "permissions": {
      "bad@zeroid.bit": false,
      "nofish@zeroid.bit": { "max_size": 100000 }
    }
  }
}
  • "ignore": ".*",: When the site owner signing this content.json don't add any file to it, they will be signed by the users.
  • cert_signers: We accept *@zeroid.bit users and they have to come with a cert that is has to signed by 1iD5ZQJMNXu43w1qLB8sfdHVKppVMduGz address.
  • permission_rules: We give 10kbytes of space to every user (15kb if registered using bitmessage)
  • permissions: Per-user permissions: ban bad@zeroid.bit user and allow 100k storage to nofish@zeroid.bit user. ( it's me :) )

After we saved this file we have to modify our root content.json to also ignore files in this directory and load the file containing the rules:

  ...
  "ignore": "data/.*",
  "includes": {
    "data/users/content.json": {
      "signers": [],
      "signers_required": 1
    }
  },
  ...

Note: You can give moderation permissions to other users by adding addresses to "signers" list.

Now we have to sign the data/users/content.json file using the following command: zeronet.py siteSign [siteaddress] --inner_path data/users/content.json

Adding messages to our json file

When hitting the Send button we going to add the message to our data.json file, sign it, then publish it to other users.

  • First add the onclick="return Page.sendMessage()" event listener to Send input button html tag.

  • Then create a new function in ZeroChat.coffee:

    sendMessage: =>
        if not Page.site_info.cert_user_id  # No account selected, display error
            Page.cmd "wrapperNotification", ["info", "Please, select your account."]
            return false

        inner_path = "data/users/#{@site_info.auth_address}/data.json"  # This is our data file

        # Load our current messages
        @cmd "fileGet", {"inner_path": inner_path, "required": false}, (data) =>
            if data  # Parse if already exits
                data = JSON.parse(data)
            else  # Not exits yet, use default data
                data = { "message": [] }

            # Add the message to data
            data.message.push({
                "body": document.getElementById("message").value,
                "date_added": (+new Date)
            })

            # Encode data array to utf8 json text
            json_raw = unescape(encodeURIComponent(JSON.stringify(data, undefined, '\t')))

            # Write file to disk
            @cmd "fileWrite", [inner_path, btoa(json_raw)], (res) =>
                if res == "ok"
                    # Publish the file to other users
                    @cmd "sitePublish", {"inner_path": inner_path}, (res) =>
                        document.getElementById("message").value = ""  # Reset the message input
                else
                    @cmd "wrapperNotification", ["error", "File write error: #{res}"]

        return false
  • After this is done type something to the message input and press the Send! button! You should see the message in the data/users/[your auth address]/data.json file.

Creating database

Now we can save and publish our messages to other users, let's display it in our application! The best way to do this is map all data.json files to an SQL database.

The ZeroNet automatically do this for you, all you need is a dbschema.json file in your site's directory that describe your table structure:

{
    "db_name": "ZeroChat",
    "db_file": "data/zerochat.db",
    "version": 2,
    "maps": {
        "users/.+/data.json": {
            "to_table": [ "message" ]
        },
        "users/.+/content.json": {
            "to_keyvalue": [ "cert_user_id" ]
        }
    },
    "tables": {
        "message": {
            "cols": [
                ["body", "TEXT"],
                ["date_added", "INTEGER"],
                ["json_id", "INTEGER REFERENCES json (json_id)"]
            ],
            "indexes": ["CREATE UNIQUE INDEX message_key ON message(json_id, date_added)"],
            "schema_changed": 1
        }
    }
}
  • "db_name": "ZeroChat": Used only for debugging
  • "db_file": "data/zerochat.db": The SQLite database file will be stored here
  • "version": 2: Define the json table structure, version 2 is better suited to ZeroID based sites. More info in the reference docs.
  • "maps": {: Describe the json files -> table conversion
  • "users/.+/data.json": { "to_table": [ "message" ] }: Put the data from every user data.json file message node to message table.
  • "users/.+/content.json": { "to_keyvalue": [ "cert_user_id" ] }: Store the user's authentication id in simple key/value structure.
  • "tables": {: Describe the table and indexing structure.
  • ["json_id", "INTEGER REFERENCES json (json_id)"]: Every table should contain a json_id column, it defines the source file path.
  • "schema_changed": 1: Increment this when you change the table structure, so the peers can drop the table and re-create it from the json files.

Tip: For the best performance always create an index for json_id column in your tables, because when new file arrives the data will be updated based on this column.

Execute zeronet.py dbRebuild [your site address] command to generate database from current files.

The data/zerochat.db SQLite file will be created, to browse these files I recommend using SQLiteStudio (it's free and opensource)

At this point you have to restart your ZeroNet client to detect and manage your site's newly created database.

Displaying messages

As the messages are now it the SQL database we can query them using the dbQuery command:

    loadMessages: ->
        @cmd "dbQuery", ["SELECT * FROM message ORDER BY date_added"], (messages) =>
            document.getElementById("messages").innerHTML = ""  # Always start with empty messages
            for message in messages
                @addLine message.body

Add the @loadMessages() line to onOpenWebsocket function, then reload the page and you should see the messages you typed in.

To make it "real time" and display new messages immediately as they come in you have to add the @loadMessages() to the route part:

    route: (cmd, message) ->
        if cmd == "setSiteInfo"
            if message.params.cert_user_id
                document.getElementById("select_user").innerHTML = message.params.cert_user_id
            else
                document.getElementById("select_user").innerHTML = "Select user"
            @site_info = message.params  # Save site info data to allow access it later

            # Reload messages if new file arrives
            if message.params.event[0] == "file_done"
                @loadMessages()

And also reload the data when we submit a new message:

    sendMessage: =>
        ...
            # Write file to disk
            @cmd "fileWrite", [inner_path, btoa(json_raw)], (res) =>
                @loadMessages()
                ...
        ...

That's it! Now the messages are updated in real-time! You can try it by opening an another browser window and enter a messages there.

Displaying ZeroID usernames

To display the sender user name we have to create a more complex SQL query, because the user names are stored in content.json file and the messages are in data.json.

+ we will also escape the incoming messages to disallow html codes.

    loadMessages: ->
        query = """
            SELECT message.*, keyvalue.value AS cert_user_id FROM message
            LEFT JOIN json AS data_json USING (json_id)
            LEFT JOIN json AS content_json ON (
                data_json.directory = content_json.directory AND content_json.file_name = 'content.json'
            )
            LEFT JOIN keyvalue ON (keyvalue.key = 'cert_user_id' AND keyvalue.json_id = content_json.json_id)
            ORDER BY date_added
        """
        @cmd "dbQuery", [query], (messages) =>
            document.getElementById("messages").innerHTML = ""  # Always start with empty messages
            for message in messages
                body = message.body.replace(/</g, "&lt;").replace(/>/g, "&gt;")  # Escape html tags in body
                @addLine "<b>#{message.cert_user_id}</b>: #{body}"

Final touches

  • We can remove the site siteInfo and serverInfo debug messages:
    onOpenWebsocket: (e) =>
        @cmd "siteInfo", {}, (site_info) =>
            # Update currently selected username
            if site_info.cert_user_id
                document.getElementById("select_user").innerHTML = site_info.cert_user_id
            @site_info = site_info  # Save site info data to allow access it later
        @loadMessages()
  • Send messages by hitting Enter:
<input type="text" id="message" onkeypress="if (event.keyCode == 13) Page.sendMessage()">
  • And add some CSS style to make it look better
<style>
* { font-family: monospace; line-height: 1.5em; font-size: 13px; vertical-align: middle; }
body { background-color: white; }
input#message { padding: 5px; width: 50%; height: 34px; }
input#send { height: 34px; margin-left: -2px; }
ul { padding: 0px; }
li { list-style-type: none; border-top: 1px solid #eee; padding: 5px 0px; }
li:nth-child(odd) { background-color: #F9FAFD; }
li b { color: #3F51B5; }
</style> 
  • After you edited any file never forget to sign and publish the modifications!
zeronet.py siteSign [your site address] --publish

Congratulations! Now you have a server-less, pure P2P, SQL backed chat application! :)