mirror of
https://github.com/taigrr/arduinolibs
synced 2025-01-18 04:33:12 -08:00
Random number generator class based on ChaCha
This commit is contained in:
@@ -27,6 +27,7 @@ This example runs tests on the ChaCha implementation to verify correct behaviour
|
||||
#include <Crypto.h>
|
||||
#include <ChaCha.h>
|
||||
#include <string.h>
|
||||
#include <avr/pgmspace.h>
|
||||
|
||||
#define MAX_PLAINTEXT_SIZE 64
|
||||
#define MAX_CIPHERTEXT_SIZE 64
|
||||
@@ -50,7 +51,7 @@ struct TestVector
|
||||
// specification doesn't contain test vectors - these were generated
|
||||
// using the reference implementation from http://cr.yp.to/chacha.html.
|
||||
|
||||
static TestVector const testVectorChaCha20_128 = {
|
||||
static TestVector const testVectorChaCha20_128 PROGMEM = {
|
||||
.name = "ChaCha20 128-bit",
|
||||
.key = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16},
|
||||
.keySize = 16,
|
||||
@@ -76,7 +77,7 @@ static TestVector const testVectorChaCha20_128 = {
|
||||
.size = 64
|
||||
};
|
||||
|
||||
static TestVector const testVectorChaCha20_256 = {
|
||||
static TestVector const testVectorChaCha20_256 PROGMEM = {
|
||||
.name = "ChaCha20 256-bit",
|
||||
.key = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16,
|
||||
201, 202, 203, 204, 205, 206, 207, 208, 209, 210,
|
||||
@@ -104,7 +105,7 @@ static TestVector const testVectorChaCha20_256 = {
|
||||
.size = 64
|
||||
};
|
||||
|
||||
static TestVector const testVectorChaCha12_128 = {
|
||||
static TestVector const testVectorChaCha12_128 PROGMEM = {
|
||||
.name = "ChaCha12 128-bit",
|
||||
.key = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16},
|
||||
.keySize = 16,
|
||||
@@ -130,7 +131,7 @@ static TestVector const testVectorChaCha12_128 = {
|
||||
.size = 64
|
||||
};
|
||||
|
||||
static TestVector const testVectorChaCha12_256 = {
|
||||
static TestVector const testVectorChaCha12_256 PROGMEM = {
|
||||
.name = "ChaCha12 256-bit",
|
||||
.key = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16,
|
||||
201, 202, 203, 204, 205, 206, 207, 208, 209, 210,
|
||||
@@ -158,7 +159,7 @@ static TestVector const testVectorChaCha12_256 = {
|
||||
.size = 64
|
||||
};
|
||||
|
||||
static TestVector const testVectorChaCha8_128 = {
|
||||
static TestVector const testVectorChaCha8_128 PROGMEM = {
|
||||
.name = "ChaCha8 128-bit",
|
||||
.key = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16},
|
||||
.keySize = 16,
|
||||
@@ -184,7 +185,7 @@ static TestVector const testVectorChaCha8_128 = {
|
||||
.size = 64
|
||||
};
|
||||
|
||||
static TestVector const testVectorChaCha8_256 = {
|
||||
static TestVector const testVectorChaCha8_256 PROGMEM = {
|
||||
.name = "ChaCha8 256-bit",
|
||||
.key = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16,
|
||||
201, 202, 203, 204, 205, 206, 207, 208, 209, 210,
|
||||
@@ -212,6 +213,8 @@ static TestVector const testVectorChaCha8_256 = {
|
||||
.size = 64
|
||||
};
|
||||
|
||||
TestVector testVector;
|
||||
|
||||
ChaCha chacha;
|
||||
|
||||
byte buffer[128];
|
||||
@@ -272,6 +275,9 @@ void testCipher(ChaCha *cipher, const struct TestVector *test)
|
||||
{
|
||||
bool ok;
|
||||
|
||||
memcpy_P(&testVector, test, sizeof(TestVector));
|
||||
test = &testVector;
|
||||
|
||||
Serial.print(test->name);
|
||||
Serial.print(" ... ");
|
||||
|
||||
@@ -291,20 +297,15 @@ void testCipher(ChaCha *cipher, const struct TestVector *test)
|
||||
Serial.println("Failed");
|
||||
}
|
||||
|
||||
// The data space of this sketch is too big if we try to test the
|
||||
// performance of all of setKey(), encrypt(), and decrypt().
|
||||
// Since decryption is almost identical to encryption, only test
|
||||
// that if the PERF_DECRYPT option is enabled, suppressing setKey().
|
||||
//#define PERF_DECRYPT 1
|
||||
|
||||
#if !defined(PERF_DECRYPT)
|
||||
|
||||
void perfCipherSetKey(ChaCha *cipher, const struct TestVector *test)
|
||||
{
|
||||
unsigned long start;
|
||||
unsigned long elapsed;
|
||||
int count;
|
||||
|
||||
memcpy_P(&testVector, test, sizeof(TestVector));
|
||||
test = &testVector;
|
||||
|
||||
Serial.print(test->name);
|
||||
Serial.print(" SetKey ... ");
|
||||
|
||||
@@ -322,14 +323,15 @@ void perfCipherSetKey(ChaCha *cipher, const struct TestVector *test)
|
||||
Serial.println(" per second");
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
void perfCipherEncrypt(ChaCha *cipher, const struct TestVector *test)
|
||||
{
|
||||
unsigned long start;
|
||||
unsigned long elapsed;
|
||||
int count;
|
||||
|
||||
memcpy_P(&testVector, test, sizeof(TestVector));
|
||||
test = &testVector;
|
||||
|
||||
Serial.print(test->name);
|
||||
Serial.print(" Encrypt ... ");
|
||||
|
||||
@@ -348,14 +350,15 @@ void perfCipherEncrypt(ChaCha *cipher, const struct TestVector *test)
|
||||
Serial.println(" bytes per second");
|
||||
}
|
||||
|
||||
#if defined(PERF_DECRYPT)
|
||||
|
||||
void perfCipherDecrypt(ChaCha *cipher, const struct TestVector *test)
|
||||
{
|
||||
unsigned long start;
|
||||
unsigned long elapsed;
|
||||
int count;
|
||||
|
||||
memcpy_P(&testVector, test, sizeof(TestVector));
|
||||
test = &testVector;
|
||||
|
||||
Serial.print(test->name);
|
||||
Serial.print(" Decrypt ... ");
|
||||
|
||||
@@ -374,17 +377,11 @@ void perfCipherDecrypt(ChaCha *cipher, const struct TestVector *test)
|
||||
Serial.println(" bytes per second");
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
void perfCipher(ChaCha *cipher, const struct TestVector *test)
|
||||
{
|
||||
#if !defined(PERF_DECRYPT)
|
||||
perfCipherSetKey(cipher, test);
|
||||
perfCipherEncrypt(cipher, test);
|
||||
#else
|
||||
perfCipherEncrypt(cipher, test);
|
||||
perfCipherDecrypt(cipher, test);
|
||||
#endif
|
||||
}
|
||||
|
||||
void setup()
|
||||
|
||||
44
libraries/Crypto/examples/TestNoise/TestNoise.ino
Normal file
44
libraries/Crypto/examples/TestNoise/TestNoise.ino
Normal file
@@ -0,0 +1,44 @@
|
||||
|
||||
// This example dumps the raw data from a transistor noise source
|
||||
// without any of the whitening normally performed by the RNG class.
|
||||
|
||||
#include <Crypto.h>
|
||||
#include <TransistorNoiseSource.h>
|
||||
|
||||
char const hexchars[] = "0123456789ABCDEF";
|
||||
|
||||
class RawNoiseSource : public TransistorNoiseSource
|
||||
{
|
||||
public:
|
||||
RawNoiseSource(uint8_t pin) : TransistorNoiseSource(pin) {}
|
||||
|
||||
protected:
|
||||
void output(const uint8_t *data, size_t len, unsigned int credit)
|
||||
{
|
||||
for (size_t posn = 0; posn < len; ++posn) {
|
||||
uint8_t value = data[posn];
|
||||
Serial.print(hexchars[(value >> 4) & 0x0F]);
|
||||
Serial.print(hexchars[value & 0x0F]);
|
||||
}
|
||||
Serial.println();
|
||||
}
|
||||
};
|
||||
|
||||
RawNoiseSource noise(A1);
|
||||
bool calibrating = true;
|
||||
|
||||
void setup() {
|
||||
Serial.begin(9600);
|
||||
Serial.println();
|
||||
Serial.println("calibrating");
|
||||
}
|
||||
|
||||
void loop() {
|
||||
noise.stir();
|
||||
bool nowCalibrating = noise.calibrating();
|
||||
if (nowCalibrating != calibrating) {
|
||||
calibrating = nowCalibrating;
|
||||
if (calibrating)
|
||||
Serial.println("calibrating");
|
||||
}
|
||||
}
|
||||
70
libraries/Crypto/examples/TestRNG/TestRNG.ino
Normal file
70
libraries/Crypto/examples/TestRNG/TestRNG.ino
Normal file
@@ -0,0 +1,70 @@
|
||||
|
||||
// Example of initializing and using the random number generator.
|
||||
|
||||
#include <Crypto.h>
|
||||
#include <RNG.h>
|
||||
#include <TransistorNoiseSource.h>
|
||||
|
||||
// Change "MyApp 1.0" to some other tag for your application
|
||||
// so that different applications will generate different results
|
||||
// even if the input noise or seed data is otherwise identical.
|
||||
#define RNG_APP_TAG "MyApp 1.0"
|
||||
|
||||
// EEPROM address to save the random number seed at.
|
||||
#define RNG_EEPROM_ADDRESS 500
|
||||
|
||||
// Noise source to seed the random number generator.
|
||||
TransistorNoiseSource noise(A1);
|
||||
|
||||
bool calibrating = false;
|
||||
byte data[32];
|
||||
unsigned long startTime;
|
||||
|
||||
void setup() {
|
||||
Serial.begin(9600);
|
||||
Serial.println("start");
|
||||
|
||||
// Initialize the random number generator.
|
||||
RNG.begin(RNG_APP_TAG, RNG_EEPROM_ADDRESS);
|
||||
|
||||
startTime = millis();
|
||||
}
|
||||
|
||||
void printHex(const byte *data, unsigned len)
|
||||
{
|
||||
static char const hexchars[] = "0123456789ABCDEF";
|
||||
unsigned long time = millis() - startTime;
|
||||
Serial.print(time / 1000);
|
||||
Serial.print('.');
|
||||
Serial.print((time / 100) % 10);
|
||||
Serial.print(": ");
|
||||
while (len > 0) {
|
||||
int b = *data++;
|
||||
Serial.print(hexchars[(b >> 4) & 0x0F]);
|
||||
Serial.print(hexchars[b & 0x0F]);
|
||||
--len;
|
||||
}
|
||||
Serial.println();
|
||||
}
|
||||
|
||||
void loop() {
|
||||
// Track changes to the calibration state on the noise source.
|
||||
bool newCalibrating = noise.calibrating();
|
||||
if (newCalibrating != calibrating) {
|
||||
calibrating = newCalibrating;
|
||||
if (calibrating)
|
||||
Serial.println("calibrating");
|
||||
}
|
||||
|
||||
// If the noise source has accumulated new entropy, then stir it in.
|
||||
RNG.stir(noise);
|
||||
|
||||
// Perform regular housekeeping on the random number generator.
|
||||
RNG.loop();
|
||||
|
||||
// Generate output whenever 32 bytes of entropy have been accumulated.
|
||||
if (RNG.available(sizeof(data))) {
|
||||
RNG.rand(data, sizeof(data));
|
||||
printHex(data, sizeof(data));
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user