The English list of the EFF, pinned; testdata and wordlists at e671032

testdata and wordlists at datekeys-go e671032, with the same testdata:
wordlists/en.txt is the large wordlist of the EFF, 7776 words, CC BY 4.0,
in its order and without the dice numbers. wordListSha256 pins it, and
the alphabet of en is a to z and the hyphen of its four compound words,
as Go has them. The vectors are generated again by Go at e671032: only
their source and the list of lists change. The tests read the English
list too, and check the hyphen and the accent in each alphabet.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
v0.15
dev 11 hours ago
parent fcc7780cf1
commit bf0f3d35d4

@ -19,6 +19,7 @@ Cambios notables de la librería Dart. El proyecto usa versionado semántico; mi
- **Vectores de Go:** `test/vectors/wordlist_vectors.json`, de `tool/wordlist_go_vectors.go` en una exportación de `datekeys-go` en `27a75ee`, con su copia en Dart para Node.js: el cuerpo de `List` sobre 19 textos; `CheckList` sobre 83 listas, y con cada punto de código de los planos 0, 1 y 14 en una lista; `Generate` en 51 casos, sobre la lista española y listas de 12 a 2^20 + 1 palabras, con el keystream de `SeededRandomSource`, bloques de SHA-256 y bytes que se acaban, entre ellos la semilla de `TestGenerate`, que solo saca dos índices y se queda sin bytes; y `Bits`, bit a bit, en 221 casos y cuatro resúmenes.
- **Pruebas.** 19 nuevas en la VM y 11 en Node.js: `test/wordlist_test.dart`, también compilado a JavaScript, con los vectores y los casos de `TestCheckList`, `TestGenerate` y `TestBits` de Go; `test/wordlist_vm_test.dart`, con cada punto de código y, sobre la lista española de `wordlists/`, los casos de `TestBuiltInLists`, `TestGenerate` y `TestGenerateUniform`; y `test/testdata_test.dart`, con la línea de `wordlists/`. En total, 2230 en la VM y 705 en Node.js.
- **Fallos inyectados** en `wordlist.dart`, uno a uno y revertidos: los 30 que cambian algún resultado, en el alfabeto, el orden de las comprobaciones, la cuenta de letras, los números de línea, el corte de las líneas, el SHA-256, el sorteo y los bits, los detectan pruebas que corren también en Node.js. Otros dos dan lo mismo con cualquier entero: quitar el atajo de las potencias de dos de `Log2`, porque `Log` da ahí lo mismo, y el borde de √2/2 en `Log`, al que no llega ningún entero.
- **La lista inglesa.** `datekeys-go` añade en `e671032` la lista grande de la EFF, `wordkey/lists/en.txt`, de 7776 palabras, CC BY 4.0, en su orden y sin los números de los dados, y `-dic` la toma por defecto. `testdata` y `wordlists` pasan a `e671032`, con el mismo `testdata`; `wordListSha256` fija la nueva lista, y el alfabeto de `en` es de la `a` a la `z` y el guion de sus cuatro palabras compuestas, como `t-shirt`. Los vectores se regeneran con Go en `e671032`: solo cambian su campo `source` y la lista de listas.
- **Diferencias con Go.** Una `RandomSource` no se acaba: lo que lance la fuente sale de `generateWords`, donde Go da `wordkey: EOF`. El fichero de una lista se lee como lee Go un string, como bytes, y sus palabras se decodifican después de la comprobación, que rechaza con el texto de Go un byte que no es UTF-8 válido.
### La recuperación a largo plazo: el objeto release y el release en la mano (07-10-2026)

@ -599,12 +599,12 @@ tool/check.sh
## Datos de prueba
`testdata/` es una copia de `datekeys-go/testdata` en un commit fijo. `testdata/SOURCE.json` registra el commit y el SHA-256 de cada fichero, igual que en `datekeys-ts`. La copia actual es la de `datekeys-go` en `27a75ee`, la rama `v0.15` después del tag `spec-v0.15`, cuyo `testdata/` es el del tag, `fe50885`, byte a byte: 142 ficheros, con `release.json` y `releases/`, el objeto release, el JSON de drand y el archivo de releases de la v0.15, con el campo `source` de `mutations.json`, con `tlock_steps.json`, los pasos 10 y 11 de Quicknet valor a valor, con `resolved_ip.json`, con `wordkey.json`, los vectores compartidos de la llave de palabras, y los veredictos y las líneas de la v0.12. Cada fichero dice `"spec": "0.15"`, como el `SpecVersion` de Go.
`testdata/` es una copia de `datekeys-go/testdata` en un commit fijo. `testdata/SOURCE.json` registra el commit y el SHA-256 de cada fichero, igual que en `datekeys-ts`. La copia actual es la de `datekeys-go` en `e671032`, la rama `v0.15` después del tag `spec-v0.15`, cuyo `testdata/` es el del tag, `fe50885`, byte a byte: 142 ficheros, con `release.json` y `releases/`, el objeto release, el JSON de drand y el archivo de releases de la v0.15, con el campo `source` de `mutations.json`, con `tlock_steps.json`, los pasos 10 y 11 de Quicknet valor a valor, con `resolved_ip.json`, con `wordkey.json`, los vectores compartidos de la llave de palabras, y los veredictos y las líneas de la v0.12. Cada fichero dice `"spec": "0.15"`, como el `SpecVersion` de Go.
`wordlists/` es la copia de `wordkey/lists` del mismo commit: las listas de palabras de `wordkey.Generate`, hoy `es.txt`, y su `README.md`, con la fuente, el método y la licencia de cada lista. `wordlists/SOURCE.json` tiene el formato de `testdata/SOURCE.json`, y `.gitattributes` guarda sus bytes exactos, como los de `testdata/`: `lib/src/wordlist.dart` fija el SHA-256 de cada lista.
`wordlists/` es la copia de `wordkey/lists` del mismo commit: las listas de palabras de `wordkey.Generate`, hoy `en.txt`, la de la EFF, y `es.txt`, y su `README.md`, con la fuente, el método y la licencia de cada lista. `wordlists/SOURCE.json` tiene el formato de `testdata/SOURCE.json`, y `.gitattributes` guarda sus bytes exactos, como los de `testdata/`: `lib/src/wordlist.dart` fija el SHA-256 de cada lista.
```bash
dart run tool/sync_testdata.dart sync --commit 27a75ee
dart run tool/sync_testdata.dart sync --commit e671032
```
```bash
@ -725,7 +725,7 @@ rm -rf "$tmp"
El de las listas de palabras corre en una exportación del commit de `wordlists/SOURCE.json`, para que sus vectores sean los de esas listas: `tool/wordlist_go_vectors.go` lee `wordkey/lists` y da a `Generate`, en lugar de `crypto/rand`, el keystream de `SeededRandomSource`, bloques de SHA-256 o bytes que se acaban. La salida es la misma en cada ejecución:
```bash
commit=$(git -C ../datekeys-go rev-parse 27a75ee)
commit=$(git -C ../datekeys-go rev-parse e671032)
out=$PWD/test/vectors
tmp=$(mktemp -d)
git -C ../datekeys-go archive "$commit" | tar -x -C "$tmp"
@ -816,7 +816,7 @@ rm -rf "$tmp"
| `pathrule_vectors.g.dart` | El mismo JSON como constante de Dart |
| `wordkey_vectors.json` | La llave de palabras de `wordkey`: 400 textos con sus palabras, 515 listas de palabras con el resultado de `Check`, y cuatro llaves con su contraseña P y su sal S, el PBKDF2 de 1000 iteraciones para Node.js y el recipient; la primera es el vector del §38.1 |
| `wordkey_vectors.g.dart` | El mismo JSON como constante de Dart |
| `wordlist_vectors.json` | Las listas de palabras de `wordkey` (`generate.go`), en `27a75ee`: el SHA-256, los bytes y las palabras de cada lista de Go; el cuerpo de `List` sobre 19 textos de una lista base, con y sin el LF final, con líneas CRLF, una línea vacía, una marca de orden de bytes y bytes que no son UTF-8 válido; `CheckList` sobre 83 listas editadas, con los casos de `TestCheckList`; `CheckList` con cada punto de código de los planos 0, 1 y 14 en la primera palabra, como el SHA-256 de sus resultados, y uno a uno hasta U+017F; `Generate` en 51 casos, sobre la lista española y listas de 12 a 2^20 + 1 palabras, con el keystream de `SeededRandomSource`, bloques de SHA-256 y bytes que se acaban, entre ellos la semilla de `TestGenerate`, que solo saca dos índices y se queda sin bytes; y `Bits`, el double de Go bit a bit, en 221 casos y cuatro resúmenes |
| `wordlist_vectors.json` | Las listas de palabras de `wordkey` (`generate.go`), en `e671032`: el SHA-256, los bytes y las palabras de cada lista de Go; el cuerpo de `List` sobre 19 textos de una lista base, con y sin el LF final, con líneas CRLF, una línea vacía, una marca de orden de bytes y bytes que no son UTF-8 válido; `CheckList` sobre 83 listas editadas, con los casos de `TestCheckList`; `CheckList` con cada punto de código de los planos 0, 1 y 14 en la primera palabra, como el SHA-256 de sus resultados, y uno a uno hasta U+017F; `Generate` en 51 casos, sobre la lista española y listas de 12 a 2^20 + 1 palabras, con el keystream de `SeededRandomSource`, bloques de SHA-256 y bytes que se acaban, entre ellos la semilla de `TestGenerate`, que solo saca dos índices y se queda sin bytes; y `Bits`, el double de Go bit a bit, en 221 casos y cuatro resúmenes |
| `wordlist_vectors.g.dart` | El mismo JSON como constante de Dart |
| `mutation_texts.json` | De `tool/mutation_go_texts.go`, port de `scripts/mutation-go-texts.go` de `datekeys-ts` sobre el `testdata/` de este repositorio: el texto del error de `capsule.Open` en cada caso del corpus de mutaciones, `ok` si se abre, y sus comprobaciones con el detalle de cada paso. Si Go y el corpus discreparan en el código o el paso de un caso, lo diría con `go_error` y `go_step`: en ninguno de los 222 casos del corpus de la v0.15 lo hacen con Go en `fe50885`, que abre cada caso con su `source`, como `testkit` |
| `open_cases.json` | `capsule.Open` sobre cada fixture con cada una de sus credenciales, y sobre fixtures editados o con otras opciones en cada paso que el corpus no alcanza: la trama, los campos, las extensiones y los vínculos de una `.dkk` en el paso 9.a, el reloj y los fallos de la fuente del release, las cabeceras `age` de los pasos 11 y 17, un stanza X25519 mal formado en `INNER_ACCESS_AGE`, `CONTROL_CBOR` sellado otra vez, `BODY` del formato 3 sellado otra vez, los sinks y la salida que fallan, el rechazo de `Accept` y las extensiones inutilizables de cada objeto. Cada caso tiene el resultado, el texto, el paso, las comprobaciones con su detalle, las peticiones del release, el estado del sink y el contenido o los ficheros, y los del formato 3 que se abren, sus veredictos con sus líneas, también con la clave de autor guardada |

@ -43,6 +43,7 @@ const minListSize = 2048;
/// wordkey/lists/README.md records it: [readWordList] takes a list only with
/// these bytes, so that a list changes only with its hash here.
const Map<String, String> wordListSha256 = {
'en': '6d557f0693958fb5e650b68b5bee585eb82cf4da32965505c789e924743bc522',
'es': 'ff77b487765c000da97cca58fe94a2cdb947303e7a07460614d7d95d800034fe',
};
@ -51,8 +52,10 @@ const Map<String, String> wordListSha256 = {
// looks like one of these, such as the Cyrillic U+0430 for the Latin a,
// would be written down and typed again with the letter of the keyboard, and
// the capsule would not open. The alphabet of a list comes from here, never
// from the list: Go's alphabets.
// from the list: Go's alphabets. The English one has the ASCII hyphen of the
// four compound words of the list of the EFF, such as t-shirt.
const _alphabets = {
'en': 'abcdefghijklmnopqrstuvwxyz-',
'es': 'abcdefghijklmnopqrstuvwxyz\u00e1\u00e9\u00ed\u00f3\u00fa\u00fc\u00f1',
};

@ -7,13 +7,14 @@ const wordlistVectorsJson = r'''
{
"description": "The word lists of package wordkey of the Go reference (generate.go, spec \u00a738.1) for lib/src/wordlist.dart; see tool/wordlist_go_vectors.go. Binary values and words are lower-case hex. The base list is word i = pal and three letters, a + i/676, a + i/26%26 and a + i%26; a case of size n takes its first n words, replaces the word at each at of set, and adds those of append. lists: the SHA-256, bytes and words of each built-in list. parse: the body of List on the text prefix, the base list joined by sep, and suffix (sha256 is that of the text): the words read, and ok or the error. check_list: CheckList, ok or the error (sha256 is that of the words joined by LF). alphabet: CheckList of the base list of 2048 whose first word is pala, a code point and zz, for each code point of the planes but the surrogates: the SHA-256 of the lines U+XXXX result, the code points of the words it accepts, and alphabet_results, each result up to U+017F. generate: Generate on the list of the Spanish words (list es) or on a list of size words whose indices they are, reading a stream: seeded, the keystream of SeededRandomSource of the seed; counter, SHA-256 of the label and a 32-bit big-endian counter from 0, block after block; bytes, hex repeated repeat times, which end. The indices drawn, the bytes read and the next four of an endless stream, or the error. bits: Bits, its shortest decimal and the hex of its float64. bits_digests: the SHA-256 of the 8 big-endian bytes of each Bits of the sizes and counts, inclusive, sizes outer.",
"generator": "tool/wordlist_go_vectors.go, go1.26.8",
"source": "27a75eefcd2ac2a3b32930d6872f3b5b6e648792",
"source": "e671032e04a3cd0999cf073ebedf50c45b088683",
"default_count": 7,
"min_list_size": 2048,
"min_words": 6,
"min_letters": 3,
"alphabet": {"word":"pala, the code point and zz, the first word of the base list of 2048","planes":[0,1,14],"count":194560,"sha256":"9119a1741586b087cc8fdcce99b00931d34c926f5dc54d7fa0ff250402a11ba9","ok":["a","b","c","d","e","f","g","h","i","j","k","l","m","n","o","p","q","r","s","t","u","v","w","x","y","z","\u00e1","\u00e9","\u00ed","\u00f1","\u00f3","\u00fa","\u00fc"]},
"lists": [
{"lang":"en","sha256":"6d557f0693958fb5e650b68b5bee585eb82cf4da32965505c789e924743bc522","bytes":62144,"words":7776},
{"lang":"es","sha256":"ff77b487765c000da97cca58fe94a2cdb947303e7a07460614d7d95d800034fe","bytes":61843,"words":7776}
],
"parse": [

@ -1,13 +1,14 @@
{
"description": "The word lists of package wordkey of the Go reference (generate.go, spec \u00a738.1) for lib/src/wordlist.dart; see tool/wordlist_go_vectors.go. Binary values and words are lower-case hex. The base list is word i = pal and three letters, a + i/676, a + i/26%26 and a + i%26; a case of size n takes its first n words, replaces the word at each at of set, and adds those of append. lists: the SHA-256, bytes and words of each built-in list. parse: the body of List on the text prefix, the base list joined by sep, and suffix (sha256 is that of the text): the words read, and ok or the error. check_list: CheckList, ok or the error (sha256 is that of the words joined by LF). alphabet: CheckList of the base list of 2048 whose first word is pala, a code point and zz, for each code point of the planes but the surrogates: the SHA-256 of the lines U+XXXX result, the code points of the words it accepts, and alphabet_results, each result up to U+017F. generate: Generate on the list of the Spanish words (list es) or on a list of size words whose indices they are, reading a stream: seeded, the keystream of SeededRandomSource of the seed; counter, SHA-256 of the label and a 32-bit big-endian counter from 0, block after block; bytes, hex repeated repeat times, which end. The indices drawn, the bytes read and the next four of an endless stream, or the error. bits: Bits, its shortest decimal and the hex of its float64. bits_digests: the SHA-256 of the 8 big-endian bytes of each Bits of the sizes and counts, inclusive, sizes outer.",
"generator": "tool/wordlist_go_vectors.go, go1.26.8",
"source": "27a75eefcd2ac2a3b32930d6872f3b5b6e648792",
"source": "e671032e04a3cd0999cf073ebedf50c45b088683",
"default_count": 7,
"min_list_size": 2048,
"min_words": 6,
"min_letters": 3,
"alphabet": {"word":"pala, the code point and zz, the first word of the base list of 2048","planes":[0,1,14],"count":194560,"sha256":"9119a1741586b087cc8fdcce99b00931d34c926f5dc54d7fa0ff250402a11ba9","ok":["a","b","c","d","e","f","g","h","i","j","k","l","m","n","o","p","q","r","s","t","u","v","w","x","y","z","\u00e1","\u00e9","\u00ed","\u00f1","\u00f3","\u00fa","\u00fc"]},
"lists": [
{"lang":"en","sha256":"6d557f0693958fb5e650b68b5bee585eb82cf4da32965505c789e924743bc522","bytes":62144,"words":7776},
{"lang":"es","sha256":"ff77b487765c000da97cca58fe94a2cdb947303e7a07460614d7d95d800034fe","bytes":61843,"words":7776}
],
"parse": [

@ -102,6 +102,19 @@ void main() {
]) {
expect(outcome(() => checkWordList('es', list)), contains(want));
}
// The hyphen of the compound words of the list of the EFF is a letter
// of en and not of es; an accent is a letter of es and not of en.
checkWordList('en', withWord(5, 't-shirt'));
expect(
outcome(() => checkWordList('es', withWord(5, 't-shirt'))),
'line 6, "t-shirt", holds U+002D, which is not in the alphabet of '
'"es"',
);
expect(
outcome(() => checkWordList('en', withWord(5, 'pala\u00e1f'))),
'line 6, "pala\u00e1f", holds U+00E1, which is not in the alphabet '
'of "en"',
);
});
test('refuses lists as wordkey.CheckList, with its texts', () {
@ -195,7 +208,7 @@ void main() {
test('readWordList refuses a language without a list and other bytes', () {
expect(
outcome(() => readWordList('xx', const [])),
'wordkey: no word list for "xx"; the lists are es',
'wordkey: no word list for "xx"; the lists are en, es',
);
final text = utf8Bytes('palaaa\n');
expect(
@ -206,7 +219,7 @@ void main() {
// The language first, as Go's List looks for its list first.
expect(
outcome(() => readWordList('ES', text)),
'wordkey: no word list for "ES"; the lists are es',
'wordkey: no word list for "ES"; the lists are en, es',
);
});

@ -2,9 +2,10 @@
// test/vectors/wordlist_vectors.json that wordlist_test.dart reads, a Dart
// constant for the tests compiled to JavaScript, is the JSON file byte for
// byte; checkWordList gives the result of Go's CheckList for every code
// point of planes 0, 1 and 14; readWordList reads wordlists/es.txt, the
// Spanish list of datekeys-go, as Go's List reads the list built into it
// (TestBuiltInLists), and generateWords draws from it the words of Go; and,
// point of planes 0, 1 and 14; readWordList reads wordlists/es.txt and
// wordlists/en.txt, the lists of datekeys-go, as Go's List reads the lists
// built into it (TestBuiltInLists), and generateWords draws from the Spanish
// one the words of Go; and,
// as TestGenerate and TestGenerateUniform of Go, the words drawn with the
// CSPRNG of the platform are a key, and each about as likely. On the VM
// only: they read files, use Random.secure or take a few seconds.
@ -63,8 +64,8 @@ void main() {
List<Json> cases(String name) => (vectors[name]! as List).cast<Json>();
test('is the list of Go, with its pinned SHA-256 (TestBuiltInLists)', () {
expect(wordListLanguages(), ['es']);
final go = cases('lists').single;
expect(wordListLanguages(), ['en', 'es']);
final go = cases('lists').singleWhere((l) => l['lang'] == 'es');
expect(go['lang'], 'es');
expect(toHex(sha256(file)), wordListSha256['es']);
expect(file, hasLength(go['bytes']));
@ -82,7 +83,7 @@ void main() {
checkWordList('es', es);
expect(
outcome(() => readWordList('xx', file)),
'wordkey: no word list for "xx"; the lists are es',
'wordkey: no word list for "xx"; the lists are en, es',
);
});
@ -156,4 +157,28 @@ void main() {
}
});
});
group('the English list of wordlists/', () {
final file = File('wordlists/en.txt').readAsBytesSync();
test('is the list of the EFF that Go builds in, in its order', () {
final en = readWordList('en', file);
final go = (vectors['lists']! as List).cast<Json>().singleWhere(
(l) => l['lang'] == 'en',
);
expect(toHex(sha256(file)), wordListSha256['en']);
expect(go['sha256'], wordListSha256['en']);
expect(file, hasLength(go['bytes']));
expect(en, hasLength(go['words']));
expect(utf8Bytes('${en.join('\n')}\n'), file);
// The dice 11111 give its first word and 66666 its last.
expect([en[0], en[1], en.last], ['abacus', 'abdomen', 'zoom']);
expect(en.where((w) => w.contains('-')), [
'drop-down',
'felt-tip',
't-shirt',
'yo-yo',
]);
});
});
}

@ -1,6 +1,6 @@
{
"module": "g.activething.com/go/DateKeys",
"commit": "27a75eefcd2ac2a3b32930d6872f3b5b6e648792",
"commit": "e671032e04a3cd0999cf073ebedf50c45b088683",
"files": {
"README.md": "d26b3f507edf5afe89600f063cb509b9ef62a908b93ed476bff964b5a443bf4b",
"fixtures/empty_payload.dkc": "871e9bf05b52bbae17f3adfbbf97b46e7f0e53aa8f57bcaa506e43f36f53a9d4",

@ -41,9 +41,9 @@
// the Dart constant is too. The output is the same on every run. It imports
// the package wordkey and reads wordkey/lists, so it runs in an export of
// datekeys-go made with git archive, without changing the repository, at
// 27a75ee, the branch v0.15 after the tag spec-v0.15:
// e671032, the branch v0.15 after the tag spec-v0.15:
//
// commit=$(git -C ../datekeys-go rev-parse 27a75ee)
// commit=$(git -C ../datekeys-go rev-parse e671032)
// out=$PWD/test/vectors
// tmp=$(mktemp -d)
// git -C ../datekeys-go archive "$commit" | tar -x -C "$tmp"

@ -7,8 +7,14 @@ from the normalized text of the words, whatever list they came from.
| List | Words | SHA-256 | Status |
|---|---|---|---|
| `en.txt` | 7776 | `6d557f0693958fb5e650b68b5bee585eb82cf4da32965505c789e924743bc522` | The large wordlist of the EFF, as published |
| `es.txt` | 7776 | `ff77b487765c000da97cca58fe94a2cdb947303e7a07460614d7d95d800034fe` | Draft, not yet reviewed by a native speaker |
Each list has 7776 = 6^5 words, sorted, so that five dice give a word: each
die minus one is a digit of the position of the word in base 6, the first
die the most significant. The dice 11111 give the first word and 66666 the
last, as in the list of the EFF.
A list changes only with its hash in this file and in `generate_test.go`:
an application that downloads a list pins its SHA-256 and refuses any other.
`wordkey.CheckList` checks a list against the alphabet of its language,
@ -18,8 +24,26 @@ typed again with the letter of the keyboard, and the capsule would not open.
| Language | Alphabet |
|---|---|
| `en` | `a` to `z` and the ASCII hyphen of the four compound words of the list of the EFF (`drop-down`, `felt-tip`, `t-shirt` and `yo-yo`), in lower case |
| `es` | `a` to `z`, `á`, `é`, `í`, `ó`, `ú`, `ü` and `ñ`, in lower case and NFC |
## `en.txt`
- **Source:** the large wordlist for passphrases of the Electronic Frontier
Foundation, by Joseph Bonneau (2016),
<https://www.eff.org/files/2016/07/18/eff_large_wordlist.txt>, whose
SHA-256 was
`addd35536511597a02fa0a9ff1e5284677b8883b83e986e43f15a3db996b903e` when
it was downloaded on 7 October 2026. The EFF explains it in
<https://www.eff.org/deeplinks/2016/07/new-wordlists-random-passphrases>.
- **License:** original material of the EFF, which its
[copyright policy](https://www.eff.org/copyright) licenses under
[CC BY 4.0](https://creativecommons.org/licenses/by/4.0/), unlike the code
of this module (Apache 2.0).
- **Change:** the dice number before each word is left out, and nothing
else: the words and their order are those of the EFF, so the position of a
word still gives its number.
## `es.txt`
- **Source:** the frequencies of

@ -1,8 +1,9 @@
{
"module": "g.activething.com/go/DateKeys",
"commit": "27a75eefcd2ac2a3b32930d6872f3b5b6e648792",
"commit": "e671032e04a3cd0999cf073ebedf50c45b088683",
"files": {
"README.md": "db71bbd031a335adeeff9e0453fdc2b2378b3bacc0104907efdfbc72fc7e6d6a",
"README.md": "d73a477d2ad4a03c6f1d61c21eeb8b754ec5a758346af62e6426979934eda097",
"en.txt": "6d557f0693958fb5e650b68b5bee585eb82cf4da32965505c789e924743bc522",
"es.txt": "ff77b487765c000da97cca58fe94a2cdb947303e7a07460614d7d95d800034fe"
}
}

File diff suppressed because it is too large Load Diff
Loading…
Cancel
Save

Powered by TurnKey Linux.