
Prueba de concepto que demuestra un ataque de canal lateral mediante análisis de potencia contra una implementación vulnerable de RSA en Arduino (Atmega328P), con configuración de hardware detallada y metodología de medición.
Recientemente, observé gente implementando criptografía para Arduino por sí mismos, como se indica en este tema en StackOverflow:
https://stackoverflow.com/questions/39189065/rsa-encryption-decryption-functions-for-arduino
Se pueden encontrar varios por internet, algunos por cierto están en bibliotecas bien conocidas.
Decidí hacer esta pequeña PoC (Prueba de concepto) para mostrar por qué es importante no solo no inventar tu propio algoritmo criptográfico, sino también utilizar una implementación robusta de dichos algoritmos.
Esta PoC realiza un ataque de canal lateral (ataque de análisis de potencia) contra una mala implementación de una rutina auxiliar utilizada en la implementación de RSA (exponenciación rápida).
Un ataque de canal lateral es un método para comprometer un sistema criptográfico explotando la fuga de información indirecta en lugar de atacar directamente el algoritmo o protocolo criptográfico en sí.
Este tipo de fuga puede originarse de diversas fuentes como información de tiempos, consumo de potencia, emisiones electromagnéticas o incluso sonido.
Tales ataques pueden ser muy efectivos para comprometer sistemas criptográficos como RSA sin requerir que el atacante resuelva los problemas matemáticos subyacentes que garantizan la seguridad del esquema criptográfico (Kocher, Jaffe, & Jun, 1999).
Este documento realizará un ataque de análisis de potencia sobre una vulnerabilidad conocida en una implementación del algoritmo RSA en un firmware para Arduino (Atmega328P).
Nota: Lo hice rápido, por favor perdón por los errores ortográficos/gramaticales que eventualmente encontrarás.
Los ataques de análisis de potencia implican medir el consumo de potencia de un dispositivo durante operaciones criptográficas.
El Análisis Diferencial de Potencia (DPA) implica el análisis estadístico de patrones de consumo de potencia a través de múltiples operaciones criptográficas para extraer secretos, siendo más sofisticado que el Análisis Simple de Potencia (SPA), que correlaciona directamente las fluctuaciones de potencia con operaciones criptográficas específicas para deducir secretos.
El Análisis Diferencial de Potencia (DPA) y el Análisis Simple de Potencia (SPA) pueden usarse para extraer claves privadas analizando patrones en el consumo de potencia durante los cómputos RSA.
Estos ataques pueden revelar la clave privada identificando patrones de uso de potencia distintivos asociados con diferentes bits de la clave (Kocher, Jaffe, & Jun, 1999).
RSA (Rivest-Shamir-Adleman) es un algoritmo de cifrado de clave pública ampliamente utilizado, nombrado en honor a sus inventores: Ron Rivest, Adi Shamir y Leonard Adleman, quienes lo introdujeron en 1977 (Paar & Pelzl, 2010).
Sigue siendo uno de los métodos más seguros para transmitir datos de forma segura a través de internet.
Uno de los fundamentos de la seguridad de RSA reside en la dificultad de factorizar números compuestos grandes en sus factores primos (Menezes, van Oorschot, & Vanstone, 1996).
Este problema, conocido como el problema de factorización, implica encontrar los números primos que multiplicados forman un número grande dado.
El cifrado RSA se basa en la suposición de que este problema de factorización es computacionalmente lo suficientemente difícil como para hacer poco práctico romper el cifrado factorizando el módulo en sus factores primos (Menezes, van Oorschot, & Vanstone, 1996).
La Figura 1 ilustra el proceso de cifrado y descifrado RSA utilizando un ejemplo simple.

Figura 1 - Ejemplo de RSA.
Tenga en cuenta que en este caso, 3 y 33 son públicos. El número 7 en el ejemplo es la clave privada.
La función Phi (N), la función totiente de Euler, calcula todos los números coprimos en el intervalo de 1 a 33.
El valor 33 se obtiene de la multiplicación de P y Q; en este caso, 11 multiplicado por 3.
El resultado de la función Phi se obtiene multiplicando (P - 1) por (Q - 1); en este caso, 10 multiplicado por 2.
La operación e<sup>-1</sup> mod 20 denota la operación de inverso modular (Menezes, van Oorschot, & Vanstone, 1996).
Nota: Si desea profundizar en RSA, lo cual no es necesario para entender este documento. Hay una introducción rápida a estas operaciones básicas de teoría de números dentro de este repositorio en el archivo number_theory.md. La explicación puede mejorar su comprensión de las operaciones RSA.
El experimento utilizó un osciloscopio DS1102 (presentado en la Figura 2) fabricado por Rigol.
El manual del osciloscopio se puede encontrar en las referencias (RIGOL Technologies, Inc., 2017).
También se utilizó una fuente de alimentación genérica (presentada en la Figura 3).

Figura 2 - Osciloscopio utilizado en el experimento.

Figura 3 - Fuente de alimentación utilizada en el experimento.
La Ley de Ohm es un principio fundamental en el campo de la ingeniería eléctrica y la física.
Establece que la corriente que fluye a través de un conductor entre dos puntos es directamente proporcional al voltaje a través de los dos puntos e inversamente proporcional a la resistencia entre ellos (Boylestad, 2015).
La Figura 4 muestra un circuito y la Ley de Ohm.

Figura 4 - Ilustración de la Ley de Ohm.
La Ley de Ohm implica que si aumenta el voltaje a través de un conductor, la corriente también aumentará, siempre que la resistencia permanezca constante (Johnson & Hilburn, 2013). La Figura 5 presenta un ejemplo de aplicación de la Ley de Ohm cuyo objetivo es encontrar la corriente en el circuito.

Figura 5 - Ejemplo de la Ley de Ohm.
La Ley de Voltaje de Kirchhoff (LVK) es un principio fundamental en la ingeniería eléctrica y la física (Boylestad, 2015).
Establece que la suma de todas las diferencias de potencial eléctrico (voltajes) alrededor de cualquier red o lazo cerrado es cero (Boylestad, 2015).
La Figura 6 ilustra la Ley de Voltaje de Kirchhoff.

Figura 6 - Ilustración de la Ley de Kirchhoff.
Hay un ejemplo de la aplicación de la Ley de Kirchhoff en la Figura 7 para encontrar la corriente a través de las resistencias R1 y R2.

Figura 7 - Ejemplo de la Ley de Kirchhoff.
El divisor de voltaje es una consecuencia de la Ley de Voltaje de Kirchhoff (LVK) y establece una forma de calcular el Vout, que es el voltaje entre la resistencia R1 y R2.
La fórmula del divisor de voltaje se presenta en la Figura 8.
Un ejemplo de aplicación del divisor de voltaje se presenta en la Figura 9.

Figura 8 - Ilustración del divisor de voltaje.

Figura 9 - Ejemplo de divisor de voltaje.
Una resistencia shunt es una resistencia de bajo valor colocada en serie con la fuente de alimentación del circuito para medir la corriente que fluye a través del circuito.
Usar un shunt para medir corriente es una de las técnicas utilizadas en los multímetros modernos (Boylestad, 2015).
Medir la caída de voltaje a través de la resistencia shunt y conocer su resistencia proporciona suficiente información para calcular la corriente usando la Ley de Ohm.
Para medir el consumo de corriente de un dispositivo Arduino, es necesario colocar una resistencia shunt en serie con el VCC (positivo).
La forma en que se conectará se presenta en la Figura 10.
Nota 1: Tenga en cuenta que en la PoC, en lugar de usar la placa Arduino Uno, el objetivo (microcontrolador atmega328p) se transfiere a una placa de pruebas separada como se presenta en la Figura 11. Esto permite manipular más fácilmente el pinout del microcontrolador sin necesidad de soldadura.
Nota 2: Si no sabe cómo hacer eso, mi artículo anterior que muestra cómo funciona el glitching enseña cómo hacerlo y se puede encontrar en https://github.com/lord-feistel/hardware_hacking_lab)

Figura 10 - Shunt con Arduino.

Figura 11 - Circuito del shunt en la placa de pruebas.
Para demostrar la medición del consumo de corriente usando una resistencia shunt, se conectará un LED (Sedra & Smith, 2014) al GPIO del microcontrolador (Figura 12) y se usará el osciloscopio para observar cómo afecta el consumo de potencia sobre la resistencia shunt en las situaciones donde el LED está encendido o apagado.
Observe que para extraer la clave o observar el efecto de la carga sobre el consumo de potencia no es necesario usar la Ley de Ohm para obtener la corriente, solo la caída de voltaje ya es suficiente (Johnson & Hilburn, 2013).

Figura 12 - Medición de potencia.
Para observarlo mejor, consulte el Video 1 que muestra cómo cae el voltaje cuando el LED está encendido.
Video 1 - Caída de voltaje debido al consumo del LED.
El siguiente código se utilizó para hacer parpadear el LED. También se puede encontrar en este repositorio.```C const int PIN_CHARGE = 9 ; void setup() { pinMode(PIN_CHARGE, OUTPUT);
}
void loop() {
digitalWrite(PIN_CHARGE, HIGH);
delay(10);
digitalWrite(PIN_CHARGE, LOW);
delay(10);
}
Es importante señalar que esta caída de voltaje también ocurre cuando se realiza un cálculo complejo (Kocher, Jaffe, & Jun, 1999).
El siguiente código provoca la caída de voltaje presentada en la **Figura 13**```C
void setup() {
}
void loop() {
volatile unsigned long i = 0;
i = ((i + 1) * (i - 1) + (i * i) - (i / 2) * (i % 3) + (i * i * i * i)) * ((i + 2) * (i - 2) + (i * i) - (i / 3) * (i % 5) + (i * i * i * i));
delayMicroseconds(100);
}
Si la caída de voltaje refleja el cálculo, entonces se puede usar para determinar los datos que se están procesando.

Figura 13 - Consumo de energía en el cálculo pesado.
La forma convencional de realizar la operación de potencia es multiplicar la base n veces.
Supongamos que 23 dará como resultado 2*2*2 ya que 2 es la base y 3 es n.
Funciona muy bien, pero no es lo suficientemente eficiente para hacer factible RSA.
Para lograr dicha implementación se utiliza el algoritmo de exponenciación rápida.
La exponenciación rápida, también conocida como exponenciación por cuadrados, es un método eficiente para elevar un número a una potencia.
A continuación se puede encontrar el pseudocódigo para la exponenciación rápida.```C
function fast_exponentiation(a, b): result = 1 base = a exponent = b
while exponent > 0:
if (exponent % 2 == 1): // If exponent is odd
result = result * base
base = base * base // Square the base
exponent = exponent // 2 // Divide exponent by 2
return result
.
.
Los pasos de la exponenciación rápida de 2<sup>4</sup> se pueden encontrar en la **Tabla 1**
| Iteración | Valor base | Exponente en binario | Operación | Resultado |
|-----------|------------|----------------------|-----------|------------------------------|
| Inicial | 2 | 100 | Inicio | 1 |
| 1 | 4 | 010 | Cuadrado | 1 |
| 2 | 16 | 001 | Cuadrado | 1 |
| 3 | 256 | 000 | Multiplicar | 16 |
| Final | - | - | Fin | 16 |
**Tabla 1** - Iteraciones de la exponenciación rápida de 2<sup>4</sup>.
A continuación se explica el proceso :```
- **Initialization:**
Start with base = 2 , exponent = 4 ( binary 100) , result = 1.
- **Iteration 1:** exponent = 4 (binary 100, even)
Square base to get 4 .
result remains 1.
- **Iteration 2:** exponent = 2 (binary 010, even)
Square base to get 16 .
result remains 1.
- **Iteration 3:** exponent = 1 (binary: 001, odd)
Multiply result by a = 16 to get 16.
result becomes 16.
- **Final:** n = 0 (binary: 000)
The loop ends with result = 16.
Nótese que para números pequeños nada cambia o empeora, sin embargo, para números grandes se obtiene una mejora significativa en la eficiencia.
Reduce el número de operaciones multiplicativas en comparación con el enfoque ingenuo, lo cual es particularmente útil para exponentes grandes.
La Tabla 2 muestra una comparación de las iteraciones para dicho número utilizando la exponenciación ingenua y la exponenciación rápida.
La exponenciación rápida es crítica en RSA tanto para los procesos de cifrado como de descifrado, ya que estos procesos implican elevar números grandes a potencias grandes módulo algún otro número grande (Paar & Pelzl, 2010).
Como se presentó en la sección Ejemplo RSA, la clave es el exponente y generalmente será un número muy grande.
| Exponente (b) | Binario (b) | Operaciones de exponenciación convencional | Operaciones de exponenciación rápida |
|---|---|---|---|
| 1 | 1 | 1 | 1 |
| 2 | 10 | 1 | 1 |
| 4 | 100 | 3 | 2 |
| 8 | 1000 | 7 | 3 |
| 16 | 10000 | 15 | 4 |
| 32 | 100000 | 31 | 5 |
| 64 | 1000000 | 63 | 6 |
| 128 | 10000000 | 127 | 7 |
| 256 | 100000000 | 255 | 8 |
| 512 | 1000000000 | 511 | 9 |
| 1024 | 10000000000 | 1023 | 10 |
Tabla 2 - Comparación de eficiencia entre exponenciación convencional y exponenciación rápida.
Se implementó una exponenciación rápida en el arduino y se cargó en el atmega328p. Al ser una prueba de concepto (PoC), la implementamos de la manera más fácil de visualizar.
Por ejemplo, normalmente se utiliza una operación de desplazamiento sobre una variable entera, pero implementamos el exponente como un arreglo para una mejor comprensión.
Nótese que el exponente que representa la clave es el arreglo {0, 1, 0, 1, 0, 1, 0, 1}, lo cual creará un patrón en la medición adquirida por el osciloscopio como prueba de que funciona.```C
#include <Arduino.h>
volatile long long dumb_vulnerableExponentiation(volatile long long base, const volatile int* exponentArray, volatile int arrayLength, volatile long long modulo) { volatile long long result = 1; base %= modulo;
for (volatile int i = 0; i < arrayLength; ++i) {
result = (result * result) % modulo;
if (exponentArray[i] == 1) {
result = (result * base) % modulo;
}
}
return result;
}
void setup() { }
void loop() { volatile long long base = 3; volatile long long modulo = 1000000007; const volatile int exponentArray[] = {0, 1, 0, 1, 0, 1, 0, 1}; volatile int arrayLength = sizeof(exponentArray) / sizeof(exponentArray[0]); delay(2); volatile long long result = dumb_vulnerableExponentiation(base, exponentArray, arrayLength, modulo); }
### Resultados
Como se presentó al inicio, para la operación de cifrado y descifrado, la clave es el exponente; por lo tanto, descubrir el exponente expone la clave RSA.
Usando el hardware mencionado anteriormente, es posible ver el espectro de consumo de energía en el osciloscopio, como se presenta en la **Figura* 14* y **Figura 15**
Los períodos en los que el voltaje cae durante un tiempo prolongado significan que se está procesando el bit `1` de la clave; de lo contrario, es el bit `0`.
Tenga en cuenta que cuando el exponente es par, hay una multiplicación adicional que hace que la caída de energía tome más tiempo, exponiendo información de la clave.
**Video 2** muestra la captura de la clave. Para entender cómo regular el período y la amplitud, consulte el manual del osciloscopio.

**Figura 14** - Captura de clave

**Figura 15** - Exponiendo 0 y 1 de la clave usando osciloscopio
[](https://youtu.be/MBZ1abtTN_k)
**Video 2** - Capturando la clave con osciloscopio.
Un ataque de este tipo se puede utilizar en un escenario en el que el microcontrolador esté usando una biblioteca conocida, pero el firmware esté bloqueado, no permitiendo que el atacante obtenga la clave directamente de la memoria.
Este tipo de ataque también se puede utilizar contra hardware.
### Conclusión
Implementar su propio sistema de cifrado RSA (Rivest-Shamir-Adleman) es muy desaconsejable debido a varias razones críticas, en particular la vulnerabilidad a ataques sofisticados como los ataques de análisis de potencia.
El cifrado RSA, aunque matemáticamente robusto cuando se implementa correctamente, requiere una atención meticulosa a los detalles en su implementación para garantizar la seguridad.
Incluso fallos menores de implementación o descuidos pueden filtrar inadvertidamente información sobre la clave privada, comprometiendo toda la seguridad del sistema.
Además, las bibliotecas y marcos criptográficos establecidos se someten a un riguroso escrutinio y pruebas por parte de la comunidad de seguridad, asegurando que sean resistentes a ataques y vulnerabilidades conocidos. El uso de estas bibliotecas probadas no solo ahorra tiempo y esfuerzo, sino que también reduce significativamente el riesgo de introducir inadvertidamente vulnerabilidades en el sistema.
### Referencias
1. Understanding Cryptography - Paar, C., & Pelzl, J. (2010). **Understanding Cryptography**. Springer.
2. Handbook of Applied Cryptography - Menezes, A. J., van Oorschot, P. C., & Vanstone, S. A. (1996). **Handbook of Applied Cryptography**. CRC Press.
3. Differential Power Analysis - Kocher, P., Jaffe, J., & Jun, B. (1999). **Differential Power Analysis**. Proceedings of CRYPTO '99, Lecture Notes in Computer Science, vol 1666. Springer, Berlin, Heidelberg. DOI: 10.1007/3-540-48405-1_25.
4. DS1102 Oscilloscope Datasheet - RIGOL Technologies, Inc. (2017). **DS1000E, DS1000D Series Digital Oscilloscope Datasheet**. Retrieved from [RIGOL Datasheet](https://beyondmeasure.rigoltech.com/acton/attachment/1579/f-03b8/1/-/-/-/-/DS1000E_DS1000D_DataSheet_EN.pdf)
5. Introductory Circuit Analysis - Boylestad, R. L. (2015). **Introductory Circuit Analysis** (13th ed.). Pearson.
6. Fundamentals of Electrical Circuits - Johnson, D., & Hilburn, J. L. (2013). **Fundamentals of Electrical Circuits**. McGraw-Hill Education.
7. Microelectronic Circuits - Sedra, A. S., & Smith, K. C. (2014). **Microelectronic Circuits** (7th ed.). Oxford University Press.