Firmador 1.4.0 publicado

Se acaba de publicar la nueva versión de este firmador digital de documentos para Costa Rica. La principal novedad es la implementación de firma visible en documentos PDF.

La firma visible es como se conoce popularmente a la apariencia de la firma. Se trata una representación visual dentro el documento como las firmas manuscritas creadas por personas y que están vinculadas a una firma digital. Esta representación visual está recogida en la especificación técnica que se utiliza en documentos PDF firmados digitalmente acorde con la política de formato oficial de Costa Rica.

El propósito de esta representación visual de las firmas es orientar a las personas que reciban un documento, sobre todo a las que no han recibido capacitación, para tener información dentro del documento que indica que contiene una firma digital. Esta representación muestra el nombre de la persona que firma, la fecha declarada de la firma y otros atributos.

La implementación se ha realizado gracias a la versión en desarrollo de la librería DSS, que es la implementación de referencia que permite aplicar firma AdES, financiada por la Comisión Europea. A partir de la versión 5.5 implementan una característica que permite utilizar texto plano, permitiendo que la firma sea más accesible mediante lectores de pantalla y que el tamaño del fichero no sea significativamente mayor. En versiones anteriores se generaba una imagen de píxeles a partir del texto.

Para ubicar la firma visible, tan solo hay que abrir un documento PDF a firmar para luego, en la pestaña Firmar, arrastrar el rectángulo “Firma visible” a la ubicación adecuada de la página deseada y finalmente hacer clic sobre el botón “Firmar documento”.

Firmador es software libre y se puede descargar desde el sitio web firmador.app para GNU/Linux, macOS y Windows.

Sitios web rápidos sin sacrificar seguridad

En estas fechas, ya son mayoría los sitios web que utilizan conexión segura con TLS, existiendo certificados gratuitos como los de Let’s Encrypt y los de Buypass.

Sin embargo, la seguridad de los sitios es algo más que proteger la comunicación entre el cliente y el servidor. El mantenimiento preventivo del software que se utiliza para la gestión del contenido del sitio debe ser riguroso, ya que es habitual descubrir vulnerabilidades de vez en cuando.

De estas vulnerabilidades, hay unas en particular que suelen suceder con mucha frecuencia pero no se le da tanta importancia como pueden ser las inyecciones de SQL. Lograr manipular el contenido de un sitio a partir de otro para extraer información o manipular formularios pueden ser dañinos si se realizan correctamente, como pueden ser los de tipo XSS y CSRF.

Por ejemplo, el código JavaScript adicional que viene incluido con el marco de trabajo Bootstrap ha tenido numerosas correcciones para mitigar ataques XSS en los últimos años, a pesar de que la cantidad de JavaScript que contiene es relativamente pequeña. Si miramos otras librerías JavaScript más grandes, el riesgo es posiblemente mayor.

Afortunadamente existen mecanismos para mitigar este tipo de ataques, sin embargo no son todavía muchos sitios web los que aplican estas medidas, ya que puede requerir modificar gran cantidad de código del lado del cliente (HTML, CSS y JavaScript) para que sea compatible con este tipo de prevención de ataques. Los navegadores web modernos permiten evitarlo, pero hay que indicarlo explícitamente por motivos de compatibilidad con el sitio.

Existen diversas propuestas para mitigar los ataques XSS mediante cabeceras de seguridad mediante protocolo HTTP. Por ejemplo, el observatorio web de Mozilla permite analizar qué cabeceras se pueden utilizar y si están utilizándose para mitigar potenciales ataques. Una de las más importantes es Content Security Policy, que puede evitar inyecciones de scripts si estos no vienen definidos en el documento previamente. Es decir, se puede evitar inyectar por ejemplo JavaScript si no viene de una fuente autorizada. Hay unas cuantas cabeceras más que permiten otro tipo de técnicas como clickjacking y otro tipo de ataques. En ese sitio web viene una descripción de cada uno.

Otra medida que puede emplearse en los navegadores modernos es el uso de cookies tipo SameSite. Por ejemplo, si se utilizan cookies de sesión, a partir de PHP 7.3 se puede definir que estas sean de este tipo para mitigar ataques CSRF en formularios sin necesidad de tener que rotar un token como era la mitigación del problema hasta ahora.

Es conveniente mencionar que algunas de estas cabeceras tienen bastantes años de existir, por lo que no debería ser un pretexto no implementarlas y hacer uso de tecnología web que no arrastre demasiada deuda técnica como para que impida hacer uso de las mismas, sobre todo en nuevos proyectos.

La velocidad no se sacrifica

Puede parecer que utilizar medidas como esta impediría aprovechar las supuestas ventajas de emplear redes de entrega de contenidos (CDN), que al menos parece que permiten acelerar el tiempo de carga.

En las cabeceras que cargan scripts que son de otros dominios, puede resultar un riesgo, en caso de que servicios de terceros se comprometan, de servir código que pudiera ser maligno. Y como no es la primera vez que sucede, existen soluciones como agregar una suma de comprobación (hash) o agregar nonces para evitar cargar scripts que hayan sido modificados. Tener que manejar estos aspectos podría complicar todavía más el desarrollo web.

Pero sobre el uso de servicios de terceros y CDN en general, habría que reflexionar por qué comenzaron a utilizarse. Hasta hace unos años, el protocolo HTTP/1.1 tenía limitaciones para cargar múltiples recursos a la vez, ya que cada petición utilizaba una conexión TCP. Aunque el HTTP pipelining permitió mitigar el problema, no era la mejor solución porque también estaba limitada a un número de conexiones TCP. Sin embargo, hoy en día hay una mucho mejor, especialmente desde el momento en el que las conexiones seguras entraron en escena.

Muchas personas pueden reconocen que tener que usar conexión HTTPS segura con TLS (HTTPS) es para evitar que aparezcan mensajes en los navegadores que su formulario o su dirección es insegura, pero HTTPS también es necesario para utilizar cada vez más características del navegador, como por ejemplo acceso a la geolocalización o incluso algunos dominios de primer nivel como los .app o .dev que cualquiera puede registrar, el navegador exige comunicación HTTPS de forma estricta.

Existe una nueva especificación llamada HTTP/2 que permite resolver de golpe todas las limitaciones de HTTP/1.1. Se utiliza una única conexión TCP para la transmisión de los datos. Hace unos cuantos años que servidores web como Apache HTTPd soportan esta tecnología. La mayoría de navegadores modernos han decidido que para poder disfrutar de HTTP/2 se requiere HTTPS.

Volviendo al tema de los CDN, una de las características de estos servicios es que han sido de los primeros en ofrecer HTTP/2 pero por una buena razón: el contenido se sirve mucho más rápido y por tanto aparenta competir mejor que si se sirve desde el propio sitio web, ya que todavía hay mucha gente que no ha considerado en servir sus sitios web con HTTP/2. En tiempos de HTTP/1.1 mejoraban el rendimiento, incluso sin que estos usaran HTTP/2, pero ya no es así.

Si un sitio web decide usar HTTP/2 para servir la información, podría incluso ser más rápido que utilizando los CDN gracias a esto. El motivo es porque los CDN por HTTP/2 requieren usar HTTPS, lo que supone una negociación TLS completa, aparte del tiempo de resolución de cada uno de los nombres de dominio. Aunque existen técnicas como DNS prefecthing, el conjunto de negociaciones va a ser más costoso que realizarlo desde un mismo sitio, salvo excepciones en sitios web que sean realmente muy grandes donde distribuir la carga merezca la pena, aunque sea por unos pocos milisegundos. Si a esto le sumamos el tiempo ahorrado en configurar la seguridad del sitio para mitigar ataques, creo que es un aspecto relevante a tener en cuenta.

Otra de las características de HTTP/2 además de dejar bastante obsoletos los CDN, también deja obsoletos los empaquetadores de recursos (JavaScript, CSS). Estos empaquetadores, como pueden ser Webpack y otros, complican y ralentizan el despliegue, además de tener que administrar una configuración monstruosa y también requiere trabajo adicional de descarga y de velocidad si hay que depurar errores. Además, evitan que el cache de los navegadores sea útil si hay cambios en los mismos, ya que habría que volver a descargar un enorme paquete si cambia una sola línea de un script, mientras que disponibles de forma individual no lo requeriría.

HTTP/2 permite también utilizar un mecanismo llamado server PUSH para enviar al navegador contenidos antes de que se los pida. Esto permite acelerar en algunos sitios web el tiempo carga de forma muy significativa. Con HTTP/1.1 lo más parecido era el preload en etiquetas link, pero tenía que descargarse primero el documento HTML para poder saber que se tenían que descargar, perdiendo un ciclo valioso que se multiplica en conexiones con latencia elevada. En el caso de Costa Rica hay mucho tráfico que viene desde fuera incluso tráfico local rebotado con latencia significativa, por lo que reducir los round trips puede reducir varias veces el tiempo de carga en estos casos. Con PUSH puede enviarse la información a Early Hints, que se sirven incluso antes de comenzar a transmitir el documento solicitado (antes del HTTP 200).

Es conveniente servir con compresión (aunque teniendo cuidado con ataques tipo CRIME). Mucha gente utiliza solamente compresión GZIP, sin embargo también existe Brotli, que permite ahorrar un porcentaje significativo de tráfico en las descargas y por tanto cargar más rápidamente. Otras formas de ahorro de ancho de banda en la conexión segura inicial es utilizar certificados de curva elíptica (ECC), soportado por todos los navegadores modernos y permitiendo descargar certificados más pequeños, además pueden aliviar la carga del servidor al cifrar la información sin necesidad de aceleración por hardware. Utilizar versiones del protocolo TLS más modernas (1.3) también permiten utilizar cifrados más eficientes y seguros. Por compatibilidad con sistemas antiguos se pueden ofrecer ambos certificados (ECC + RSA).

Otro aspecto que implica una dependencia de terceros es la consulta de estado de revocación del certificado TLS. Esta consulta se realiza a los servidores OCSP de la autoridad de certificación, que podría tener momentos en los que funcionara más lento de lo habitual (como le podría suceder a un CDN), además de que implicaría una consulta adicional. Adicionalmente, las autoridades de certificación sabrían cuánto tráfico tendría tu sitio web y de dónde provienen sus visitantes, por lo que también, como en el caso de los CDN, tiene implicaciones de privacidad. Para mitigarlo existe el grapado OCSP, que es un mecanismo por el cual el estado de revocación se envía directamente desde el sitio web sin depender del tercero. Este grapado es un mecanismo que queda guardado en memoria cache del servidor web y contiene una consulta firmada digitalmente con sello de tiempo que garantiza que el estado de revocación del certificado era válido, teniendo un tiempo de vida relativamente corto, por lo que es el servidor web el que va renovando y cacheando estas consultas. Con esto se mejora también muy ligeramente el tiempo de negociación de la conexión HTTPS.

Recomendaciones

En resumen, algunas recomendaciones para el desarrollo web moderno, logrando seguridad, velocidad y un desarrollo más eficiente:

  • No utilizar servicios CDN si no es necesario.
  • Utilizar cabeceras de seguridad (CSP, HSTS y demás).
  • Utilizar grapado OCSP.
  • Utilizar cookies SameSite (si el sitio usa cookies).
  • Utilizar HTTP/2.
  • Utilizar server PUSH (si es con Early Hints, mejor).
  • Utilizar compresión Brotli.
  • Utilizar TLS 1.3.
  • Utilizar certificados ECC (o dual ECC + RSA).

Este sitio web hace uso de todas estas características y probablemente se note en el tiempo inicial de carga, tanto en computadoras de escritorio como en dispositivos móviles en redes fijas y celulares. Recomiendo utilizar Apache HTTPd porque es el primer servidor HTTP en cumplir al 100% con la especificación HTTP/2 (y no, no es más lento que nginx, esto lo explicaré en otro artículo de blog).

Follow this quality checklist before an audit

At Zeppelin we help protect the core infrastructure of open and decentralized applications. I'm part of the Research team, which is in charge of conducting security audits. We review tons of lines of code written by very smart developers for projects that will shake the foundations of our society.

Finding security vulnerabilities in this futuristic cypherpunk environment is super challenging and fun, but we have already covered those topics elsewhere. I think that security actually starts in a pretty boring and traditional place, full of the wisdom that our elders have collected through millennia of developing software in community. Standing on their shoulders, I want to share our checklist for basic quality measures that your next awesome project should consider before you hand it over for an external audit.

✔️ Choose a free software license

Closed code is inherently insecure. If people who use your project can't inspect it, study it, hack it, and experiment on it, there's no way it can be trusted. If you hold abusive control over your users, nothing prevents you (or anyone more powerful than you) from making them vulnerable.

Take a look at the Free Software Definition, and begin with choosing the license that best suits your needs.

This is a good moment to introduce our first wise elder! Richard Stallman 😜, who hacked copyright laws, started the free software movement, and wrote the above definition.

Richard Stallman

Richard Stallman in costume as St. IGNUcius (Monastir, Tunisia, 2012. Image taken from Wikipedia)

✔️ Build your core team of maintainers

When your project succeeds, hundreds of external contributors will surely be supporting it. But in order to get to that point, you'll need to bootstrap with a strong and diverse team of core maintainers. They'll take care of the bulk of the work, the fun and the boring parts, proposing and reviewing the code of your shared project. Together, you all need to have strong knowledge of all points on this checklist. Look not only for technical knowledge, but also for a knack for cat-herding and a healthy work style—because, well, things will get complicated.

Pay attention to your bus factor: make sure your team members are sharing their expertise, the lessons learned, and their responsibilities, while at the same time constantly mentoring new people that could potentially join the core team.

And somebody will have to lead and orchestrate in order to get value out of the eternal tendency toward chaos. Let me introduce you to our second magician, Camille Fournier, who wrote THE book on technical management, The Manager's Path.

Camille Fournier

Camille Fournier (Image taken from her website)

✔️ Write clean code

The only valid measurement of code quality is WTFs per minute. This point must be simple. If things get overly complicated or weird, you're doing it wrong. Go for a walk and try again with fresh eyes.

But don't get me wrong: no interesting software project is simple. Add the complexity dimensions of decentralization, transparency, cryptography, and all these shiny ideas that are keeping us so busy these days. It's complicated by design. But with the correct abstractions, a well thought-out model, and proper encapsulation, you can start building the bank-killer app one line at a time. And each of those lines must be clean and readable.

I'm not a spectacular programmer, I was just lucky to find Uncle Bob Martin's book Clean Code at the right moment and to have read a never-ending stream of very, very ugly code.

Robert C. Martin

Robert Cecil Martin (Image taken from Wikipedia)

Once all core maintainers reach common ground on this topic, you should enforce a consistent code style by running a linter on every new line of code that's added. The particular rules aren't as important as following them strictly is, but if you can sacrifice your peculiar preferences to be consistent with the rest of the world, your contributors will appreciate it a lot.

I also practice slow-food... er, slow programming. Take your time, enjoy the journey to mastering this craft, and when you've built something you can proudly set free, let the masses read it and judge it.

✔️ Write unit tests

Write unit tests. Tons of them. 100% coverage. This might sound extreme, but hey, your code is now playing directly with somebody else's money. If you forget, or just get lazy and don't write a test for that super obvious line of code, you might be leaving an open door for an exploit later in the game that will make your project crash, and all this magic internet money will disappear in no time. It has happened.

I feel immediately more secure when I do test-driven development. At least give an honest try to writing the tests first, and get into a cycle of red-green-refactor. There are other techniques that can achieve the same result, but I suggest starting there and then deviating if you find good reasons to do so. Never worked this way? Read Test Driven Development: By Example by Kent Beck. It's a quick read that will help you avoid the temptation of just jumping into code without thinking it through.

Then, even if you design for testability, you'll find many scenarios that are hard to test. Gerard Meszaros provides all the answers in xUnit Test Patterns. This book is huge, so I recommend choosing a designated test expert on your team.

Kent Beck Gerard Meszaros

Left: Kent Beck speaking in 2001 (Image taken from Wikipedia) Right: Gerard Meszaros (Image taken from Twitter)

Finally, make sure to run your unit tests on every single pull request, and make sure they're all green before merging the changes. In addition, you can set up a test coverage report to ensure that test coverage never goes down.

✔️ Test early, test often, test agile

Now that you have your first layer of tests covered with tons of unit tests, what comes next is...more tests! You need to test the integration between all of your components, then go one level higher to test your application from the point of view of a real user, and then go even higher to test the interactions with other systems end-to-end.

To me, this is the biggest challenge, and designing a good process that keeps many bugs out of your system can be as difficult as designing the system itself. Iterate, automate as much as possible, share the load of manual testing...and let your community help.

We'll talk later about community, but I think this is the reason for publishing your code as early as possible: you can get help from early adopters and enthusiasts to validate your system, not only for correctness but also to verify that you're focusing on the right user stories and that you're tackling a real problem with a user-friendly solution.

A lot has been written about iterative development processes that deliver functionalities in progressive sprints and milestones. I found Mike Cohn's Succeeding with Agile: Software Development Using Scrum a good place to start, but keep in mind that any methodology will have to be adjusted to your team, your users, and your context. There are a lot fewer resources focused on the quality and testing part; that's why I was so happy when I read Agile Testing by Lisa Crispin and Janet Gregory, which is full of good ideas and advice. But let me stress again: nothing you read will perfectly fit your project, so take your time to design the testing process with as much love and care as you use when designing the system's architecture.

Mike Cohn Lisa Crispin and Janet Gregory

Left: Mike Cohn in 2013 (Image taken from Wikipedia) Right: Right: Lisa Crispin and Janet Gregory (Image taken from their website)

While there's still some debate about the perfect moment for auditing a project (i.e, before or after the code is published), I think audits should be performed when there's a release candidate ready to be deployed to mainnet, after you have performed extensive alpha and beta testing. I see room for auditing before the code has been published, but in this case, the audit would be more related to checking that the development process will lead to a high-quality, properly tested release candidate and validating the bases of your project than to performing a deep and thorough inspection of the codebase.

However, this doesn’t mean that you have to wait until the end of a long development phase to prepare for a release and audit. Once you start writing and testing clean code in incremental iterations, it becomes easier to think about your complex system. Many smaller independent parts will start to pop up, which can be extracted, generalized, and packaged for reuse, reducing anxiety for developers and auditors. These packages are the focus of ZeppelinOS for this year, to know more take a look at the State of EVM Packages.

✔️ Write documentation

This is my least favorite part, by far. So let's keep it simple, starting at the beginning: the README, the most important file of your repository. And yet, it's usually either empty or bloated, outdated, and ugly. Ideally, as it's the first thing developers and potential contributors will read, it should work as a clear, straightforward index of your project.

It's best not to get creative here. Just follow this simple specification that works for all cases, proposed by Richard Littauer in Standard Readme. Do not forget to include a specific section in the main README that states how people should disclose any security vulnerabilities found in your project.

Richard Littauer

Richard Littauer (Image taken from Twitter)

Next come the docstrings, the documentation inside your code files. We hit an apparent conflict here, since in theory, if your code is clean, it will not require documentation. However, note that we are no longer designing standalone systems that work as a black box. We are building protocols for decentralized applications, and your code will be called by all sorts of external agents. So by all means, document every function that's part of the contract's public API, following the NatSpec format.

Which brings me to the next point. I highly recommend that you document the specification of your protocol—that's how others will know what to call and what to expect. But more related to the topic at hand, in an audit, we check that the implemented code works as intended by the specification. That's why this document is a must: without it, auditors will just guess at your intentions, which might result in some issues getting missed because they're completely consistent within the system but take it to a state that you want to avoid.

Finally, there's the user documentation. For high-quality systems, writing the user documentation should be mostly painless. The moment things get cumbersome while documenting, consider re-evaluating your user stories, and don't be afraid to go back to iterate on them.

✔️ Check your dependencies

Your project builds on top of many, many others. It will probably depend at least on the Ethereum protocol and its network of nodes, and on Solidity, a bunch of Ethereum Improvement Proposals and their implementation, libraries for testing and UI, and maybe hundreds of other small projects. Even if yours is secure, you need to check how healthy your dependencies are, since they can easily become the source of vulnerabilities.

Earlier, I mentioned that your team should have strong and diverse knowledge. That includes knowledge of all the projects that surround you. You should be able to write idiomatic code following the best practices of the language, to identify and avoid known issues, always keeping an eye on new CVEs that may directly (or indirectly, through third-party dependencies) affect your project. Moreover, try to participate in the communities around your dependencies, as it's an excellent way to see firsthand how safe and trustworthy they are. You should also consider actively participating in those communities, to gain some karma that will surely come in handy later when you need new features and bug fixes.

Moreover, don't forget to pay attention to your dependencies' finances. When making your project's budget, take into account a share for your dependencies, as they may need it in order to remain actively maintained. There's a very nice project called OpenCollective, led by Pia Mancini, which is making it extremely easy to transparently support the organizations and developers you depend on.

Pia Mancini

Pia Mancini (Image taken from her website)

And, of course, with ZeppelinOS, we're building a platform that will let you vouch for the security of a package. It's in beta testing, so expect exciting news very soon.

Specific to Ethereum and Solidity, the community is collecting the lessons learned (usually in a painful way). You can learn a lot about interesting and tricky vulnerabilities playing the Ethernaut capture-the-flag game. We've published many of our past audits with descriptions of the issues found, recommendations, and usually a link to the patch that fixes them. All of our learnings from audits are distilled into the OpenZeppelin package, which you should definitely add to your list of dependencies—if you're not one of the thousands that already did. The Smart Contracts Weakness Registry maintained by the Mythril team is also a great resource for learning from the experience of others.

Whatever approach you take, remember that as the Ethereum space is very young and unexplored, we're learning many things as we go, so always proceed with caution.

✔️ Build your community

This is a complement to the first point: code without a community is insecure. The community gives you eyes to monitor the project, hands to test it in a real environment, support to survive challenging problems, and resilience to adjust to the unexpected. No amount of money, experience, or knowledge can substitute for this.

Once you publish the code, you can get started engaging your community. If your project is interesting, they will come, and this is where the cat-herding abilities of your team will shine. However, you definitely need to set up proper and fluent communication channels, invest in some marketing, and hire a bold community manager with a plan to disentangle and wisely leverage all the opportunities your community brings. I can't recommend highly enough the writings and videos by Jono Bacon, who has covered all the topics you can imagine about community management.

Jono Bacon

Jono Bacon in 2014 (Image taken from Flickr)

You should be thoughtful and caring with your community. A small step that goes a long way is to adopt and enforce a code of conduct so you can all feel safe. Then, write some contribution guidelines to make sure that all of their enthusiasm can be put to good use and they don't get lost. Lastly, think about setting up a bug bounty program that will encourage your community to watch out for vulnerabilities in the wild, providing hackers with enough incentives to disclose security issues in a responsible way.


tldr:

✅ Choose a free software license.

✅ Build a strong and diverse team of core maintainers.

✅️ Increase your bus factor: share knowledge and responsibilities.

✅ Choose a good leader.

✅️ Write clean code.

✅️ Enforce a consistent code style.

✅️ Ensure 100% unit test coverage.

✅️ Enforce green tests on all your pull requests.

✅️ Design your iterative development and testing process.

✅️ Publish your code.

✅️ Write a good README.

✅️ Document the functions of your public API.

✅️ Document your protocol.

✅️ Write the end-user documentation.

✅️ Make sure that your dependencies can be trusted.

✅️ Review known issues and keep an eye out for new ones.

✅️ Use OpenZeppelin, the community-vetted standard for smart contract development.

✅️ Build and care for your community.


Ready to hire an auditing team?

That's us! :) The Zeppelin team can help you assess the quality of your project and processes. We'll take a deep and thorough dive into your code, with years of experience hacking, researching, and developing on blockchains, plus a little touch of Latin American fire, to give you and your users all the confidence you need to continue building the core systems of this new decentralized, global, and open economy.

We're available for auditing services, so check out this information about security audits.

Thanks to Martín Abbatemarco for editing this post, to the Zeppelin team for the continuous experimentation and feedback, and to our customers for trusting us and helping us better understand what makes a free software project awesome.


Be part of our community

La obsolescencia de Java 8

El lenguaje de programación Java se había diseñado para ser un lenguaje que funcionara sin tener que crear código específico para cada sistema donde se ejecutaba. También tenía algo que trataba de destacar frente a otros, que una vez “compilado” podía usarse el mismo “binario” en otras plataformas.

Sin embargo, los planes para este lenguaje cambiaron hace tiempo por diversos motivos, entre otros porque hay sistemas donde no se permite la ejecución de código privilegiado si no se tiene autorización del fabricante, como es el caso de Apple en su sistema operativo macOS.

En la actualidad los propios autores de Java invitan a distribuir la máquina virtual con el propio programa creado en este para que pueda ejecutarse. Esto desvirtúa la utilidad con la que fue diseñado, no teniendo mayores ventajas con respecto a otros lenguajes de programación que podrían considerarse más eficientes.

Hay diversos motivos por los que distribuir programas sin el entorno de ejecución de Java y su máquina virtual han quedado relegados a nichos muy particulares (por ejemplo, servlets de contenedores EE, applets de hardware empotrado y Android) y fuera del software tradicional de escritorio. Por ejemplo, para ejecutar programas en macOS sin bloqueos de seguridad por no estar firmados, siendo obligatorio si el programa se pretende distribuir en la App Store.

A partir versión Java 11 se ha eliminado la tecnología Web Start del entorno de ejecución. Tampoco hay un instalador para usuarios finales, por lo que Java 8 es el último que se ofrece en el sitio web java.com, como parte de esta transición. Una salida que tienen los distribuidores de software desarrollado en Java para ambientes de escritorio pasa por incluir un entorno de ejecución OpenJDK. En una entrada anterior de este blog ya se mencionó esta necesidad.

Cabe mencionar que existe software de escritorio muy dependiente de Java, como es el caso de la firma de documentos PDF, donde las mejores librerías para manipular documentos con este tipo de elementos están programadas en Java. La implementación de referencia del estándar PAdES (DSS) utiliza este lenguaje, ya que librerías como iText/OpenPDF y Apache PDFBox siguen siendo las mejores para este propósito.

Herramientas implementadas en Java como el Firmador de documentos que hemos realizado utilizan todavía Java para toda la interfaz. Incluso está disponible una versión Web Start de Firmador (requiere tener Java 8 instalado o bien OpenJDK con Icedtea-web), demostrando de la mejor forma una tecnología obsoleta. Hay planes de crear una versión de Firmador que utilice Java solamente para la parte que sea necesaria. El resto utilizaría otro lenguaje de programación más portable y eficiente.

Cabe mencionar que para utilizar la obsoleta tecnología Web Start se ha requerido firmar el código con un certificado digital específico que tiene un costo anual significativo, sin embargo ya era necesario hacerse uno para crear ejecutables sin que aparezca el fatídico mensaje de “Windows protegió su PC”, por lo que la inversión estaba pensada para este caso. Para el caso de macOS también hay que costear aparte otro certificado oneroso para distribuir software.

En cuanto al sector público, los firmadores ya distribuían el entorno de ejecución de Java con sus propios instaladores, por lo que ya están preparados para el fin de Java 8 en los próximos meses.

Cómo instalar Firma Digital de Costa Rica en GNU/Linux Fedora 30

Esta guía documenta cómo instalar el controlador de la tarjeta de Firma Digital de Costa Rica y la jerarquía de certificados del Banco Central (SINPE) y del MICITT en el sistema operativo Fedora Workstation 30.

Esta guía de instalación tiene los siguientes propósitos:

  • Configurar de la forma más sencilla y adecuada el sistema para que funcione con la mayor cantidad de programas.
  • Lograr que funcione para todos los usuarios del sistema, incluyendo los nuevos usuarios creados tras las instalación.
  • Aislar la librería de Firma Digital en una “caja de arena” (sandbox) para que funcione con múltiples usuarios del sistema simultáneamente (soluciona un defecto en la librería al crear ficheros temporales).

Instalación de las dependencias

  • Instalar el soporte CCID de PC/SC para que reconozca el lector de tarjetas e IcedTea-Web para poder cargar algunos lanzadores que usan Java Web Start (los navegadores ya no soportan applets java, ya no es posible usar el firmador de la CCSS) y OpenJFX si pretende usarse algún firmador que lo use (NexU, por ejemplo).
    sudo dnf -y install pcsc-lite icedtea-web java-1.8.0-openjdk-openjfx

Descarga del “instalador”

  • Descargar el “instalador” en el desplegable llamado “Usuarios Linux” en la página de descarga de instaladores del sitio web de Soporte Firma Digital de Costa Rica, introduciendo el número de serie de la tarjeta y aceptando las condiciones.
  • Descomprimir el archivo zip descargado con unzip, en el momento de escribir esta documentación se llama sfd_ClientesLinux_Rev09.zip. Se creará una carpeta llamada Firma Digital. Se asume que el archivo zip se ha descargado en la carpeta Descargas:
    cd ~/Descargas/
    
    unzip sfd_ClientesLinux_Rev09.zip
    

Instalación de los certificados

Es necesario agregar a la lista de confianza la jerarquía de certificados del SINPE y del MICITT. En teoría solamente sería necesario instalar los certificados raíz del MICITT pero en la práctica hay algunas aplicaciones que necesitan los certificados intermedios del SINPE para completar la cadena a la hora de validar. Para ello, un conjunto de comandos:

  • Copiar los certificados:
    sudo cp ~/Descargas/Firma\ Digital/Certificados/* /usr/share/pki/ca-trust-source/anchors/
    
  • Regenerar los archivos de certificados para todas las aplicaciones:
    sudo update-ca-trust
    

Instalación del módulo PKCS#11

Aunque hay un módulo en el directorio Librerías, no es la versión más reciente y tiene varios defectos de enlazado. La versión distribuida en el paquete PinTool es más reciente y funciona correctamente en todos los programas probados. En el siguiente proceso se extrae y se instala conservando la fecha original de la librería.

  • Instalar el módulo PKCS#11 privativo en /usr/lib64/:
    cd ~/Descargas/Firma\ Digital/PinTool/IDProtect\ PINTool\ 6.41.01/RPM/
    
    rpm2cpio idprotectclient-641.01-0.x86_64.rpm | cpio -dim ./usr/lib/x64-athena/libASEP11.so
    
    sudo cp -p usr/lib/x64-athena/libASEP11.so /usr/lib64/
    
    sudo mkdir -p /usr/lib/x64-athena/
    
    sudo ln -s /usr/lib64/libASEP11.so /usr/lib/x64-athena/
    
  • Permitir temporalmente al usuario local cargar aplicaciones gráficas con sudo (para gedit):
    xhost si:localuser:root
    
  • Crear el fichero /etc/Athena/IDPClientDB.xml y abrirlo para edición:
    sudo mkdir /etc/Athena/
    
    sudo gedit /etc/Athena/IDPClientDB.xml
    
  • En la ventana del editor de textos gedit, pegar el siguiente texto, guardar y cerrar el editor:
    <?xml version="1.0" encoding="utf-8" ?>
    <IDProtect>
     <TokenLibs>
      <IDProtect>
       <Cards>
        <IDProtectXF>
         <ATR type='hexBinary'>3BDC00FF8091FE1FC38073C821106600000000000000</ATR>
         <ATRMask type='hexBinary'>FFFF00FFF0FFFFFFFFFFFFFFFFF0FF00000000000000</ATRMask>
        </IDProtectXF>
       </Cards>
      </IDProtect>
     </TokenLibs>
    </IDProtect>
    
  • Crear un fichero llamado /usr/share/p11-kit/modules/firma-digital.module y abrirlo para edición:
    sudo gedit /usr/share/p11-kit/modules/firma-digital.module
    
  • En la ventana del editor de textos gedit, pegar el siguiente texto, guardar y cerrar el editor:
    remote: |bwrap --unshare-all --dir /tmp --ro-bind /etc/Athena /etc/Athena --proc /proc --dev /dev --ro-bind /usr /usr --symlink /usr/lib64 /lib64 --ro-bind /var/run/pcscd /var/run/pcscd p11-kit remote /usr/lib64/libASEP11.so
    

Eso es todo. Es necesario reiniciar Firefox y cualquier otra aplicación que use certificados para que se apliquen los cambios.

Quizás resulte interesante utilizar la herramienta Firmador, software libre para firmar documentos.

Road to #MozillaActivate, El Salvador 2018

Holi,

No se ustedes, pero de tanto estar viajando no me ha quedado demasiado tiempo para hacer tutoriales, pero me encanta documentar las cosas asi que esta vez vamos a hablar sobre la fundación Mozilla y porque fue que pare una semana en El Salvador. Bienvenidos.

Antecedentes ( esto ya parece un informe jajaja, pero vamos a hacerlo bonito).

El año pasado para el encuentro Centroamericano de Software Libre, Costa Rica 2017 hubo un evento alterno llamado #mozillaActivate, resulta que en el mismo encuentro hubo gente de #mozillaCentroamerica invitando a mas gente a unirse al movimiento de una internet libre, respetuosa con la privacidad y los derechos ( sí sé que suena medio raro,  pero lo que mozilla incentiva es que tengamos una internet libre y que todos seamos tratados por igual) a mi me parece excelente muchas cosas que esta haciendo Mozilla hasta que me dieron en el kokoro con algo llamado Web of things, que es una solución para el internet de las cosas preparada por Mozilla que realmente tiene un muy muy buen punto a su favor, Es realmente sencillo crear soluciones con su propuesta.
El contacto directo con Mozilla Centroamérica fue MoziKarlita, que amablemente nos invito a ser parte de Mozilla Centroamérica y pues con Lexo, dijimos esta bien.

Preparación del evento

Ponernos de acuerdo fue lento, tedioso y complicado.
Lo sé son palabras duras para un equipo que ya había trabajado junto, en este caso nosotros como integrantes nuevos de Mozilla Centroamérica y primeros miembros de Mozilla Guatemala fue un poco confuso saber como ayudar, ellos tenían sus métodos para hacer las cosas y yo y mis manías por andar mandando no se sintieron bien.

Realmente de lo único que puedo quejarme fue de que entre todo dejamos muchas cosas para el ultimo minuto, como yo por ejemplo perdiendo mi tarjeta del banco sin haber comprado los boletos de ida y vuelta a El Salvador, los que me siguen en Instagram, facebook y Twitter (@yeffrimic) se dieron cuenta de que mi mente andaba en otro lado y pues aquí oficialmente me disculpo, La cague jajaja.

La parte mas complicada de todo fue el hecho de que nadie quiso tomar la batuta de líder al principio  y se tuvieron que hacer malabares para que mozilla nos autorizara el evento y nos patrocinara. Al final y lo que importa fue que Mozilla nos aprobó el patrocinio (gracias David) y pues bueno ya teníamos todo preparado, charlas, presentaciones, lugar para dar las charlas asi que yeii, ya había viaje confirmado para El Salvador, Mozilla Activate y ECSL alla vamos.

Nos vamos a San Salvador, Gracias Mozilla

20180710_083538Él es Lexo, vive a 12 horas de la Ciudad de Guatemala y como a 24 de San Salvador.

Bueno al final llegamos a San Salvador, salimos mas o menos a las 7 am y llegamos al medio día, listos para descansar y preparar todo para el día D

Día de exposiciones

Dejo la hermosa agenda aqui y dare mis impresiones de todos.

https://docs.google.com/document/d/1v9SlhDQ9EHm0Tdn14UlzivmkibtT08yIvotK7XAawcI/edit?usp=sharing

Todos y cada uno de los que están en Mozilla CentroAmerica como representantes o asistieron como conferencistas al Mozilla Activate son unos putos cracks.

Empezando con Aaron y su increible manera de exponer porque Mozilla y no solo firefox sino todo lo que representa la fundación es de las mejores cosas en internet hoy en dia.

photo5059894245955053519

 

Roni y su dominio con los temas de privacidad en la red

photo5059856768070428666

no hablemos de Lexo, Carcamo con Rust que los vi por allí haciendo travesuras con uno de los lenguajes mas nuevos y potentes del momento.

photo5059856768070428659

 

photo5059856768070428660

Me impresiono bastante lo que puede hacer Firefox con web VR a cargo de David

photo5059894245955053522

 

Jorge estuvo hablando sobre programacion de videojuegos pero murphy fue su enemigo mortal no pudiendo proyectar porque el adaptador que tenía no funcionaba 😦
photo5059856768070428656
aqui esta con lexo tratando de solucionarlo, no se para que usan mac jajaja

moziKarlita hablando sobre la comunidad de mozilla y como ser parte de ella tambien alentó a muchos jovenes que estaban presentes.

photo5059856768070428664

 

y yo merengues hablando sobre lo que me encanta Internet de las cosas con al go llamado Mozilla IOT, y su web de las cosas, adjunto la presentación para que le echen un ojo, como he dicho antes esta es una excelente iniciativa de parte de Mozilla y todos los voluntarios para el internet de las cosas

photo5059856768070428668

 

Bueno, después de organizar, moverse y el calor de San Salvador cada uno fue cayendo a lo largo de la semana dormido por el cansancio unos en el ECSL y otros en el dia social y yo que siempre andaba con sueño.

photo5059894245955053517

Al final fue una experiencia increible hablandole a poco mas de 100 patojos( jovenes ) acerca de las bondades de fundación mozilla el proximo año será en Guatemala asi que quedan todos invitados a asistir.  No les conté muchas cosas que sucedieron para que el proximo año nos acompañen en Guatemala jajaja.

Con esto termino el articulo del dia de hoy pronto mas acerca de las microfaventuras .

Recuerden, solo necesitan una excusa para cambiar el mundo.

 

 

Guías de instalación de Firma Digital en GNU/Linux actualizadas

Se han actualizado las guías de instalación de Firma Digital de Costa Rica para GNU/Linux para Ubuntu y Fedora. Los cambios amplían la cantidad de software soportado, mayor estabilidad y otras ventajas.

Aislamiento de la librería en caja de arena

Una de las mejoras comunes en ambos sistemas permiten el aislamiento de la librería privativa en una “caja de arena” (sandbox). El propósito de este aislamiento es evitar caídas de los programas cuando dos usuarios distintos del mismo sistema tratan de acceder a la tarjeta. Esto es debido a que la librería libASEP11.so genera unos temporales en el directorio /tmp/ con un usuario, pero cuando intenta crearlos desde otro usuario diferente, la librería genera un error de segmentación que se propaga a la aplicación que la está utilizando.

Para solucionar el problema se utiliza un sistema de caja de arena que puede lanzarse sin privilegios administrativos mediante la herramienta bubblewrap, que permite montar en un espacio de nombres vacío del espacio de usuario la librería, por lo que en el caso de que dos usuarios del sistema utilicen la librería, la ruta /tmp/ estará aislada en ambos casos, no existiendo en el sistema de ficheros físico, evitando el problema mencionado.

Otra ventaja que se obtiene con este aislamiento es que la librería no genera el directorio oculto ~/.ase/ en los directorios de los usuarios, que llega a suponer una molestia cuando se generan búsquedas, ya que el directorio lo genera con permisos que impiden su acceso por defecto. Por otra parte, al tratarse de software privativo y no poder auditar el código fuente, el aislamiento mejora ligeramente la seguridad sobre lo que pueda realizar esta librería.

Otra característica que permite resolver este defecto es poder utilizar la tarjeta de Firma Digital para iniciar sesión con el PIN de la tarjeta de Firma Digital, desde la ventana de selección de usuario (gdm, GNOME Display Manager) si se configura localmente con algún mecanismo tipo pam_pkcs11. Antes no se podía realizar porque el plug-in gsd-smartcard de GNOME Settings Daemon, encargado de comunicarse con la tarjeta, se ejecuta con otro usuario distinto al de la sesión (en este caso, gdm). Antes de esta solución, cuando un usuario inicia sesión en el sistema, ese servicio quedaba activo con los ficheros generados en /tmp/ y provocaba que cualquier proceso que utilizara Firma Digital en la sesión de usuario se cerrara automáticamente, provocando gran inestabilidad.

El método que se ha emplado para resolverlo ha sido mediante la característica remote de p11-kit. P11-kit es parte del proyecto p11-glue, cuyo propósito es actuar de “pegamento” para consolidar todas las herramientas criptográficas del sistema y permitir estandarizar el acceso a servicios con dispositivos PKCS#11 de forma unificada. En la actualidad dispone de integración con características PKCS#11 de GnuTLS, NSS, OpenSSL, OpenSC, Java, y otros, así como la confianza de las autoridades de certificación (CA).

Hasta ahora se estaba utilizando p11-kit con un módulo que hacía referencia a una librería local (libASEP11.so). Sin embargo, p11-kit permite cargar módulos de forma remota, que puede resultar interesante para utilizar un dispositivo criptográfico existente en otra computadora, si bien en esta solución no se ejecuta nada remoto sino que sigue en local. El parámetro remote permite lanzar un comando personalizado que en este caso invoca el ejecutable brwap de bubblewrap, aislando la librería en esta caja de arena.

Gracias a esta mejora, en próximas entradas de blog explicaría cómo iniciar sesión en el sistema mediante Firma Digital y cómo bloquear la pantalla (sesión) extrayendo la tarjeta del lector.

Soporte de NSS (Chromium, Evolution, Acceso a llaveros) en Ubuntu

Se ha actualizado la guía de Ubuntu para incorporar un reemplazo de la librería NSS genérica del sistema (NSS es la librería de servicios de seguridad de Mozilla), utilizada (además de Firefox y Thunderbird) por el navegador Chromium, cliente de correo Evolution o el acceso a llaveros, para poder utilizar Firma Digital desde ellos. Esto ya era posible con la guía de Fedora, pero no en Ubuntu hasta ahora.

Integración mejorada en Fedora

Fedora, así como Red Hat, ha sido siempre la distribución GNU/Linux que desde mi punto de vista se ha esforzado más en integrar los sistemas criptográficos, utilizados en sector público y corporativo. En la última actualización que se incluye a partir de Fedora 29 completan la consolidación para poder cargar el módulo p11-kit-proxy desde la configuración de política de NSS para poder cargar módulos de terceros sin tener que realizar enlaces simbólicos como hasta ahora.

Fedora ya llevaba tiempo reemplazando libnssckbi.so (librería de módulos de seguridad de NSS) con p11-kit-trust por defecto, algo que permite unificar la confianza en los certificados de las CA de forma centralizada. También está unificada la configuración de cifrados utilizados en TLS a nivel de todo el sistema, para prevenir brechas de seguridad por configuraciones débiles. En este aspecto es indiscutiblemente la distribución mejor preparada, así como los aportes con los que se han beneficiado otras distribuciones, ya que se esfuerzan en que estas mejoras se incorporen en las versiones oficiales del software (upstream).

En una próxima entrada de blog mostraré cómo iniciar sesión localmente (sin sssd, usando pam_pkcs11 con mapeo local, sin LDAP) con la tarjeta de Firma Digital.

Cómo instalar Firma Digital de Costa Rica en GNU/Linux Ubuntu 18.04, 19.04 y Debian 9

Esta guía documenta cómo instalar el controlador de la tarjeta de Firma Digital de Costa Rica y la jerarquía de certificados del Banco Central (SINPE) y del MICITT en los sistemas operativos Ubuntu 18.04 LTS, Ubuntu 19.04 y Debian 9.

Esta guía de instalación tiene los siguientes propósitos:

  • Configurar de la forma más sencilla y adecuada el sistema para que funcione con la mayor cantidad de programas.
  • Lograr que funcione para todos los usuarios del sistema, incluyendo los nuevos usuarios creados tras las instalación.
  • Aislar la librería de Firma Digital en una “caja de arena” (sandbox) para que funcione con múltiples usuarios del sistema simultáneamente (soluciona un defecto en la librería al crear ficheros temporales). Esta característica no está disponible en Debian 9.

Instalación de las dependencias

  • Instalar el soporte CCID de PC/SC para que reconozca el lector de tarjetas e IcedTea-Web para poder cargar algunos lanzadores que usan Java Web Start (los navegadores ya no soportan applets Java, ya no es posible usar el firmador de la CCSS) y OpenJFX si pretende usarse algún firmador que lo use (NexU, por ejemplo). Bubblewrap es la herramienta para aislar la librería en la caja de arena. Binutils y sudo no vienen instalados en Debian por defecto.
    sudo apt -y install pcscd bubblewrap icedtea-netx openjfx binutils sudo
    

En el caso de Debian, para poder usar los comandos con sudo, ejecutar como root usermod -a -G sudo nombredeusuario reemplazando nombredeusuario por el nombre de usuario que se desee usar con sudo y reiniciar para aplicar cambios. En Ubuntu no es necesario este paso.

Descarga del “instalador”

  • Descargar el “instalador” en el desplegable llamado “Usuarios Linux” en la página de descarga de instaladores del sitio web de Soporte Firma Digital de Costa Rica, introduciendo el número de serie de la tarjeta y aceptando las condiciones.
  • Descomprimir el archivo zip descargado con unzip, en el momento de escribir esta documentación se llama sfd_ClientesLinux_Rev09.zip. Se creará una carpeta llamada Firma Digital. Se asume que el archivo zip se ha descargado en la carpeta Descargas:
    cd ~/Descargas/
    
    unzip sfd_ClientesLinux_Rev09.zip
    

Instalación de los certificados

Es necesario agregar a la lista de confianza la jerarquía de certificados del SINPE y del MICITT. En teoría solamente sería necesario instalar los certificados raíz del MICITT pero en la práctica hay algunas aplicaciones que necesitan los certificados intermedios del SINPE para completar la cadena a la hora de validar. El último instalador también incluye una CA del BCCR, probablemente para el certificado de código de su propio firmador (que en teoría tampoco debería ser necesario si el sistema operativo está correctamente actualizado). Para ello, un conjunto de comandos:

  • Copiar los certificados:
    sudo cp ~/Descargas/Firma\ Digital/Certificados/* /usr/local/share/ca-certificates/
    
    sudo rename.ul -- .cer .crt /usr/local/share/ca-certificates/*.cer
    
    for file in /usr/local/share/ca-certificates/*.crt; do sudo openssl x509 -inform DER -in "$file" -out "$file.tmp"; done 2>/dev/null
    
    sudo find /usr/local/share/ca-certificates/ -type f -empty -delete
    
    sudo rename.ul -- .tmp '' /usr/local/share/ca-certificates/*.tmp
    
  • Regenerar los archivos de certificados para todas las aplicaciones:
    sudo update-ca-certificates --fresh
    

Instalación del módulo PKCS#11

Aunque hay un módulo en el directorio Librerías, no es la versión más reciente y tiene varios defectos de enlazado. La versión distribuida en el paquete PinTool es más reciente y funciona correctamente en todos los programas probados. En el siguiente proceso se extrae y se instala conservando la fecha original de la librería.

  • Instalar el módulo PKCS#11 privativo en /usr/lib/x86_64-linux-gnu/:
    cd ~/Descargas/Firma\ Digital/PinTool/IDProtect\ PINTool\ 6.41.01/DEB/
    
    ar p idprotectclient_641.01-0_amd64.deb data.tar.gz | tar zx ./usr/lib/x64-athena/libASEP11.so
    
    sudo cp -p usr/lib/x64-athena/libASEP11.so /usr/lib/x86_64-linux-gnu/
    
  • Crear los siguientes enlaces simbólicos (necesarios para que funcionen algunos programas):
    sudo ln -s /usr/lib/x86_64-linux-gnu/libASEP11.so /usr/lib/
    
    sudo mkdir -p /usr/lib/x64-athena/
    
    sudo ln -s /usr/lib/x86_64-linux-gnu/libASEP11.so /usr/lib/x64-athena/
    
  • Crear el fichero /etc/Athena/IDPClientDB.xml y abrirlo para edición:
    sudo mkdir /etc/Athena/
    
    sudo gedit /etc/Athena/IDPClientDB.xml
    
  • En la ventana del editor de textos gedit, pegar el siguiente texto, guardar y cerrar el editor:
    <?xml version="1.0" encoding="utf-8" ?>
    <IDProtect>
     <TokenLibs>
      <IDProtect>
       <Cards>
        <IDProtectXF>
         <ATR type='hexBinary'>3BDC00FF8091FE1FC38073C821106600000000000000</ATR>
         <ATRMask type='hexBinary'>FFFF00FFF0FFFFFFFFFFFFFFFFF0FF00000000000000</ATRMask>
        </IDProtectXF>
       </Cards>
      </IDProtect>
     </TokenLibs>
    </IDProtect>
    
  • Crear un fichero llamado /usr/share/p11-kit/modules/firma-digital.module y abrirlo para edición:
    sudo gedit /usr/share/p11-kit/modules/firma-digital.module
    
  • En la ventana del editor de textos gedit, pegar el siguiente texto, guardar y cerrar el editor:
    remote: |bwrap --unshare-all --dir /tmp --ro-bind /etc/Athena /etc/Athena --proc /proc --dev /dev --ro-bind /usr /usr --ro-bind /lib /lib --ro-bind /lib64 /lib64 --ro-bind /var/run/pcscd /var/run/pcscd p11-kit remote /usr/lib/x86_64-linux-gnu/libASEP11.so
    

    Solamente para Debian 9: la línea anterior no funciona porque incluye una versión demasiado antigua de p11-kit. En su lugar debe usarse esta otra línea: module: /usr/lib/x86_64-linux-gnu/libASEP11.so.

  • Crear un fichero llamado /usr/local/sbin/update-p11-kit-symlinks y abrirlo para edición:
    sudo gedit /usr/local/sbin/update-p11-kit-symlinks
    
  • En la ventana del editor de textos gedit, pegar el siguiente texto, guardar y cerrar el editor:
    #!/bin/sh
    
    FIREFOX_LIB=/usr/lib/firefox/libnssckbi.so
    FIREFOX_ESR_LIB=/usr/lib/firefox-esr/libnssckbi.so
    THUNDERBIRD_LIB=/usr/lib/thunderbird/libnssckbi.so
    NSS_LIB=/usr/lib/x86_64-linux-gnu/nss/libnssckbi.so
    
    if [ -e "$FIREFOX_LIB" ]
    then
        if ! [ -L "$FIREFOX_LIB" ]
        then
            echo "Firefox libnssckbi.so is not a symlink. Fixing..."
            mv -f "$FIREFOX_LIB" "$FIREFOX_LIB".bak
            ln -s /usr/lib/x86_64-linux-gnu/p11-kit-proxy.so "$FIREFOX_LIB"
        fi
    fi
    
    if [ -e "$FIREFOX_ESR_LIB" ]
    then
        if ! [ -L "$FIREFOX_ESR_LIB" ]
        then
            echo "Firefox ESR libnssckbi.so is not a symlink. Fixing..."
            mv -f "$FIREFOX_ESR_LIB" "$FIREFOX_ESR_LIB".bak
            ln -s /usr/lib/x86_64-linux-gnu/p11-kit-proxy.so "$FIREFOX_ESR_LIB"
        fi
    fi
    
    if [ -e "$THUNDERBIRD_LIB" ]
    then
        if ! [ -L "$THUNDERBIRD_LIB" ]
        then
            echo "Thunderbird libnssckbi.so is not a symlink. Fixing..."
            mv -f "$THUNDERBIRD_LIB" "$THUNDERBIRD_LIB".bak
            ln -s /usr/lib/x86_64-linux-gnu/p11-kit-proxy.so "$THUNDERBIRD_LIB"
        fi
    fi
    
    if [ -e "$NSS_LIB" ]
    then
        if ! [ -L "$NSS_LIB" ]
        then
            echo "NSS libnssckbi.so is not a symlink. Fixing..."
            mv -f "$NSS_LIB" "$NSS_LIB".bak
            ln -s /usr/lib/x86_64-linux-gnu/p11-kit-proxy.so "$NSS_LIB"
        fi
    fi
    
  • Agregar el atributo de ejecutable al script:
    sudo chmod +x /usr/local/sbin/update-p11-kit-symlinks
    
  • Crear un fichero llamado /etc/systemd/system/p11-kit-proxy-updater.service y abrirlo para edición:
    sudo gedit /etc/systemd/system/p11-kit-proxy-updater.service 
    
  • En la ventana del editor de textos gedit, pegar el siguiente texto, guardar y cerrar el editor:
    [Unit]
    Description=mantenimiento de enlaces a p11-kit-proxy
    
    [Service]
    Type=oneshot
    ExecStart=/usr/local/sbin/update-p11-kit-symlinks
    
    [Install]
    WantedBy=multi-user.target
    
  • Activar el servicio al arranque y ejecutarlo una primera vez para comprobar que funciona:
    sudo systemctl enable --now p11-kit-proxy-updater.service
    

Solamente para Ubuntu 18.10 y posteriores: A partir de esta versión hay que modificar el fichero /usr/share/p11-kit/modules/p11-kit-trust.module y eliminar o desactivar la última línea agregando un “#” al inicio de esa línea.

sudo gedit /usr/share/p11-kit/modules/p11-kit-trust.module

La última línea quedaría como sigue, el resto no hay que modificarlo:

#disable-in: p11-kit-proxy

Eso es todo. Es necesario reiniciar Firefox y cualquier otra aplicación que use certificados para que se apliquen los cambios. Si se ha insertado el lector y la tarjeta al lector, estas aplicaciones preguntarán por el PIN en páginas donde se solicite autenticación (por ejemplo en el sitio web de Internet Banking del Banco Nacional), lo que indicará que se la instalación ha sido exitosa.

Si el componente de firma del Banco Central está instalado debería funcionar para poder realizar la prueba de firma. El sitio web de Soporte Firma Digital podría usar todavía la prueba de Java y no funciona con los navegadores modernos. En su lugar podría usarse la prueba con el firmador BCCR desde la página de Firma Digital de verificación de certificados (requiere instalar los certificados para poder entrar).

Quizás resulte interesante utilizar la herramienta Firmador, software libre para firmar documentos.

Firmador digital de documentos para Costa Rica

Firmador es un pequeño programa de escritorio para firmar documentos que cumplan la Política de Formatos Oficiales de los Documentos Electrónicos Firmados Digitalmente publicada por el MICITT.

Esta herramienta se ha diseñado para ser simple, fácil de usar y que funcione en múltiples sistemas operativos. La descarga es relativamente ligera y requiere tener instalado Java 8 y los controladores de Soporte Firma Digital.

Por ahora firma documentos PDF. En próximas versiones el programa soportará otros formatos de documento electrónico oficial y otras mejoras.

El programa es software libre y abierto a la colaboración de cualquier persona interesada para mejorar su código o utilizarlo para cualquier propósito.

Firmador tiene su propio sitio web: https://firmador.app

On crowdsales and multiple inheritance

On 2017 we saw a mind-blowing number of crowdsales and ICOs running in the Ethereum blockchain. They have proven to be a powerful tool to collect the funds required to start a project, and they are one of the most common uses for smart contracts right now. The Zeppelin team has been very involved in this topic, auditing many crowdsale contracts, and supporting OpenZeppelin, the most popular framework to build these crowdsales. What we found was a lot of contracts repeating the same basic concepts, with very similar code, and common vulnerabilities.

Earlier this year, part of the team took the task to redesign our base Crowdsale contract in order to support a lot of new crowdsale flavors out of the box and to make the experience of building and publishing your own crowdsale more clear and secure. The idea is to make audits less necessary, with an architecture that is modular, that encourages reuse and that will be collectively reviewed. These new contracts were added to OpenZeppelin version 1.7.0, and since the release they have been widely used by our community with great success. So, this is a good moment to show off :)

Let's start with a dive into the source code of the Crowdsale base contract. The first thing you will notice is a lot of comments, guiding you through the details of the OpenZeppelin crowdsale architecture. They explain that some functions are the core of the architecture and should not be overriden, like buyTokens. Some others like _preValidatePurchase can be overriden to implement the requirements of your crowdsale, but that extra behavior should be concatenated with the one of the parent by calling super, to preserve the validations from the base contract. Some functions like _postValidatePurchase can be just added as hooks in other parts of the crowdsale's lifecycle.

Building on top of this base, we now provide some contracts for common crowdsale scenarios involving distribution, emission, price, and validation.

So, let's say that you want to set a goal for your crowdsale and if it's not met by the time the sale finishes, you want to refund all your investors. For that, you can use the RefundableCrowdsale contract, which overrides the base _forwardFunds behavior to send the funds to a fancy RefundVault while the crowdsale is in progress, instead of sending them directly to the wallet of the crowdsale owner.

Another common scenario is when you want the tokens to be minted when they are purchased. For that, take a look at the MintedCrowdsale contract, which overrides the simple _deliverTokens behavior of the base class to call instead the mint function of an ERC20 Mintable token.

What if we want to do something more interesting with the price of the tokens? The base Crowdsale contract defines a constant rate between tokens and wei, but if we override _getTokenAmount, we could do something like increasing the price as the closing time of the crowdsale approaches. That's exactly what the IncreasingPriceCrowdsale contract does.

To get started developing and deploying a crowdsale using the OpenZeppelin framework, Gustavo Guimaraes published a nice guide where you will see in action a crowdsale that is timed and minted.

These are just a few examples. I invite you to explore the OpenZeppelin crowdsale contracts to see all the new flavors that you can easily use to fund your cool idea; and take a look at the SampleCrowdsale contract, a more complex scenario that comes with full test coverage. If you like OpenZeppelin, remember that you are welcome into our vibrating community to help us adding new contracts or improving the existing ones.

On the repo you will also find that all these contracts are very well tested. And as we have seen, the new architecture is clearer and safer, with each contract explaining the functions that you can or can't override, and how to do it. However, you should be extra careful when combining them. It's not the same to have three contracts with one condition than to have one contract with three conditions. The combination increases the attack surface, so you need to have a good idea of what you want to achieve, and know the implementation details of the tools you are using.

Before you go ahead and deploy a complex crowdsale that combines some of our contracts, I would like to spend some time going deep into how Solidity works when you combine contracts through multiple inheritance, like Gustavo did in his guide to make a contract that inherits from TimedCrowdsale and from MintedCrowdsale.

Multiple inheritance is hard, and it can get very confusing if you abuse it. Some languages don't support it at all; but it is becoming a very common pattern on Solidity.

The problem, from the point of view of the programmer, is to understand the order of the calls when a contract has multiple parents. Let's say we have a base contract A, with a function named f:

contract A {
  function f() {
    somethingA();
  }
}

Then we have two contracts B and C, both inherit from A and override f:

contract B is A {
  function f() {
    somethingB();
    super.f();
  }
}

contract C is A {
  function f() {
    somethingC();
    super.f();
  }
}

And finaly we have a contract D, which inherits from B and C, and overrides f too:

contract D is B, C {
  function f() {
    somethingD();
    super.f();
  }
}

What happens when you call D.f?

This is called the diamond problem, because we end up with a diamond-shaped inheritance diagram:

Diamond inheritance problem

(the image is from wikipedia)

To solve it, Solidity uses C3 linearization, also called Method Resolution Order (MRO). This means that it will linearize the inheritance graph. If D is defined as:

contract D is B, C {}

then D.f will call:

somethingD();
somethingC();
somethingB();
somethingA();

When D inherits from B, C, the linearization results in D→ C→ B→ A. This means that super on D calls C. And you might be a little surprised by the fact that calling super on C will result on a call to B instead of A, even though C doesn't inherit from B. Finally, super on B will call A.

If D is instead defined as:

contract D is C, B {}

then D.f will call:

somethingD();
somethingB();
somethingC();
somethingA();

When D inherits from C, B, the linearization results in D→ B→ C→ A.

Notice here that the order in which you declare the parent contracts matters a lot. If the inheritance graph is not too complex, it will be easy to see that the order of calls will follow the order in which the parents were declared, right to left. If your inheritance is more complicated than this and the hierarchy is not very clear, you should probably stop using multiple inheritance and look for an alternate solution.

I recommend you to read the wikipedia pages of Multiple inheritance and C3 linearization, and the Solidity docs about multiple inheritance. You will find in there a complete explanation of the C3 algorithm, and an example with a more complicated inheritance graph.

To better understand how this can impact your crowdsales, take a look at the case that Philip Daian brilliantly explains on his blog post Solidity anti-patterns: Fun with inheritance DAG abuse. There, he presents a Crowdsale contract that needs "to have a whitelist pool of preferred investors able to buy in the pre-sale [...], along with a hard cap of the number of [...] tokens that can be distributed." On his first (deliberately) faulty implementation, he ends up with a crowdsale that checks:

((withinPeriod && nonZeroPurchase) && withinCap) || (whitelist[msg.sender] && !hasEnded())

Pay close attention to the resulting condition, and notice that if a whitelisted investor buys tokens before the crowdsale has ended, she will be able to bypass the hard cap, and buy as many tokens as she wants.

By just inverting the order on which the parents are defined, he fixes the contract which will now check for:

(withinPeriod && nonZeroPurchase || (whitelist[msg.sender] && !hasEnded())) && withinCap

Now, if the purchase attempt goes above the cap, the transaction will be reverted even if the sender is whitelisted.

There are some simple cases, where the order of the conditions is not important. By now, you should have started to suspect that the contract above became complicated because of the || (or) condition. Things are a lot easier when all our conditions are merged with && (and), because in that case the order of the conditions doesn't alter the result.

Our new architecture was crafted for using require instead of returning booleans, which works nicely to combine and conditions, and to revert the transaction when one fails. Let's say that we have a crowdsale that should only allow whitelisted investors to buy tokens while the sale is open and the cap has not been reached. In this case, the condition to check would be (in pseudocode):

require(hasStarted() && !hasEnded())
require(isInWhiteList(msg.sender))
require(isWithinCap(msg.value))

Our contract would be as simple as:

pragma solidity ^0.4.18;

import "zeppelin-solidity/contracts/crowdsale/validation/TimedCrowdsale.sol";
import "zeppelin-solidity/contracts/crowdsale/validation/WhitelistedCrowdsale.sol";
import "zeppelin-solidity/contracts/crowdsale/validation/CappedCrowdsale.sol";

contract WhitelistedTimedCappedCrowdsale is TimedCrowdsale, WhitelistedCrowdsale, CappedCrowdsale {

  function WhitelistedTimedCappedCrowdsale(
    uint256 _rate,
    address _wallet,
    ERC20 _token,
    uint256 _openingTime,
    uint256 _closingTime,
    uint256 _cap
  )
    public
    Crowdsale(_rate, _wallet, _token)
    TimedCrowdsale(_openingTime, _closingTime)
    CappedCrowdsale(_cap)
    {
    }

}

It doesn't matter how you order the parents, all the conditions will be checked always. But take this with a grain of salt. All the conditions will be checked, but the order will be different. This can have different side-effects on Solidity, as some paths will execute statements that other paths won't, and it could lead an attacker to find a specific path that is vulnerable. Also, if your parent contracts are not super clear, they might be hiding an || condition in a few hard-to-read code statements.

It's very easy to think that the parent contracts will just be magically merged into something that will make sense for our use case, or to make a mistake when we linearize them in our mind. Every use case will be different, so our framework can't save you from the work of organizing your contracts' hierarchy. You must analyze the linearization of the inheritance graph to get a clear view of the functions that will be called and their order, and always always add a full suite of automated tests for your final crowdsale contract to make sure that it enforces all the conditions.

To finish, I wanted to show you my repo where I will be doing experiments with crowdsales and their tests: https://github.com/elopio/zeppelin-crowdsales

Take a look at my PreSaleWithCapCrowdsale contract. You will see that I preferred to be explicit about the conditions instead of using super:

function _preValidatePurchase(address _beneficiary, uint256 _weiAmount) internal {
  require(_beneficiary != address(0));
  require(_weiAmount != 0);
  require(block.timestamp >= openingTime || whitelist[_beneficiary]);
  require(block.timestamp <= closingTime);
  require(weiRaised.add(_weiAmount) <= cap);
}

I encourage you to join me on these experiments, to try different combinations of crowdsales and to play switching the order of the inheritance graph. We will learn more about the resulting code that Solidity compiles, we will improve our mental picture of the execution stack, and we will practice writing tests that fully cover all the possible paths. If you have questions, find errors on the implementations in OpenZeppelin, or find an alternative implementation that will make it easier to develop crowdsales on top of our contracts, please let us know by sending a message to the slack channel. I am elopio in there.

A relevant experiment here is to use composition over inheritance. In OpenZeppelin we couldn't implement an architecture based on composition because of the high gas costs implied, especially during deployment. That is one of the reasons we are now hard at work on zeppelin_os, which minimizes deployment costs by helping you use libraries that are already on-chain. Expect exciting news very soon!

Thanks a lot to Ale and Alejo, who worked on these new contracts and helped me to understand them. <3