diff --git a/External/Pearl b/External/Pearl
index daa260b3..0e9484b6 160000
--- a/External/Pearl
+++ b/External/Pearl
@@ -1 +1 @@
-Subproject commit daa260b3ecaca266ffcfa597e9350900dda6cc56
+Subproject commit 0e9484b6512150fbbfffdddcdec62f8e9a741254
diff --git a/MasterPassword/C/build b/MasterPassword/C/build
index 1469f69f..9d1d038a 100755
--- a/MasterPassword/C/build
+++ b/MasterPassword/C/build
@@ -1,2 +1,3 @@
-#!/usr/bin/env bash
-gcc -I"lib/scrypt/lib" -I"lib/scrypt/libcperciva" -I"lib/proplib/include" -l "crypto_aesctr.o" -l "sha256.o" -l "crypto_scrypt-nosse.o" -l "memlimit.o" -l "scryptenc_cpuperf.o" -l"scryptenc.o" -l"crypto" -l"prop" -L"lib/scrypt" -L"lib/proplib/src/.libs" mpw.c -o mpw
+#!/usr/bin/env bash -e
+gcc types.c -o types.o
+gcc -I"lib/scrypt/lib" -I"lib/scrypt/libcperciva" -l "crypto_aesctr.o" -l "sha256.o" -l "crypto_scrypt-nosse.o" -l "memlimit.o" -l "scryptenc_cpuperf.o" -l"scryptenc.o" -l"types.o" -l"crypto" -L"lib/scrypt" mpw.c -o mpw
diff --git a/MasterPassword/C/ciphers b/MasterPassword/C/ciphers
new file mode 100644
index 00000000..0c5f6472
--- /dev/null
+++ b/MasterPassword/C/ciphers
@@ -0,0 +1,78 @@
+
+
+
+
+ MPElementGeneratedEntity
+
+ Maximum Security Password
+
+ anoxxxxxxxxxxxxxxxxx
+ axxxxxxxxxxxxxxxxxno
+
+ Long Password
+
+ CvcvnoCvcvCvcv
+ CvcvCvcvnoCvcv
+ CvcvCvcvCvcvno
+ CvccnoCvcvCvcv
+ CvccCvcvnoCvcv
+ CvccCvcvCvcvno
+ CvcvnoCvccCvcv
+ CvcvCvccnoCvcv
+ CvcvCvccCvcvno
+ CvcvnoCvcvCvcc
+ CvcvCvcvnoCvcc
+ CvcvCvcvCvccno
+ CvccnoCvccCvcv
+ CvccCvccnoCvcv
+ CvccCvccCvcvno
+ CvcvnoCvccCvcc
+ CvcvCvccnoCvcc
+ CvcvCvccCvccno
+ CvccnoCvcvCvcc
+ CvccCvcvnoCvcc
+ CvccCvcvCvccno
+
+ Medium Password
+
+ CvcnoCvc
+ CvcCvcno
+
+ Basic Password
+
+ aaanaaan
+ aannaaan
+ aaannaaa
+
+ Short Password
+
+ Cvcn
+
+ PIN
+
+ nnnn
+
+
+ MPCharacterClasses
+
+ V
+ AEIOU
+ C
+ BCDFGHJKLMNPQRSTVWXYZ
+ v
+ aeiou
+ c
+ bcdfghjklmnpqrstvwxyz
+ A
+ AEIOUBCDFGHJKLMNPQRSTVWXYZ
+ a
+ AEIOUaeiouBCDFGHJKLMNPQRSTVWXYZbcdfghjklmnpqrstvwxyz
+ n
+ 0123456789
+ o
+ @&%?,=[]_:-+*$#!'^~;()/.
+ x
+ AEIOUaeiouBCDFGHJKLMNPQRSTVWXYZbcdfghjklmnpqrstvwxyz0123456789!@#$%^&*()
+
+
+
diff --git a/MasterPassword/C/ciphers.plist b/MasterPassword/C/ciphers.plist
deleted file mode 120000
index 383ea2e0..00000000
--- a/MasterPassword/C/ciphers.plist
+++ /dev/null
@@ -1 +0,0 @@
-../Resources/Data/ciphers.plist
\ No newline at end of file
diff --git a/MasterPassword/C/mpw.c b/MasterPassword/C/mpw.c
index 93af69a4..354b65e3 100644
--- a/MasterPassword/C/mpw.c
+++ b/MasterPassword/C/mpw.c
@@ -20,7 +20,7 @@
#include
#include
-#include
+#include "types.h"
#define MP_N 32768
#define MP_r 8
@@ -178,38 +178,15 @@ int main(int argc, char *const argv[]) {
free(sitePasswordInfo);
// Determine the cipher.
- prop_dictionary_t MPTypes_ciphers = prop_dictionary_internalize_from_file("ciphers.plist");
- if (!MPTypes_ciphers) {
- fprintf (stderr, "Could not read cipher definitions: %d\n", errno);
- return 1;
- }
- prop_array_t typeCiphers = prop_dictionary_get(prop_dictionary_get(MPTypes_ciphers, "[self classNameOfType:type]"), "[self nameOfType:type]");
- if (!typeCiphers) {
- fprintf (stderr, "Could not find cipher definition for type: %s\n", siteTypeString);
- return 1;
- }
- prop_string_t cipher = prop_array_get(typeCiphers, sitePasswordSeed[0] % prop_array_count(typeCiphers));
- if (!typeCiphers) {
- fprintf (stderr, "Missing cipher definitions for type: %s\n", siteTypeString);
- return 1;
- }
+ const char *cipher = CipherForType(siteType, sitePasswordSeed);
//trc(@"type %@, ciphers: %@, selected: %@", [self nameOfType:type], typeCiphers, cipher);
// Encode the password from the seed using the cipher.
//NSAssert([seed length] >= [cipher length] + 1, @"Insufficient seed bytes to encode cipher.");
- const prop_dictionary_t characterClasses = prop_dictionary_get(MPTypes_ciphers, "MPCharacterClasses");
- char *sitePassword = calloc(prop_string_size(cipher) + 1, sizeof(char));
- char cipherClass[2] = {0, 0};
- for (int c = 0; c < prop_string_size(cipher); ++c) {
-
- const uint16_t keyByte = sitePasswordSeed[c + 1];
- cipherClass[0] = prop_string_cstring_nocopy(cipher)[c];
- const prop_string_t cipherClassCharacters = prop_dictionary_get(characterClasses, cipherClass);
- const char character = prop_string_cstring_nocopy(cipherClassCharacters)[ keyByte % prop_string_size(cipherClassCharacters) ];
-
+ char *sitePassword = calloc(strlen(cipher) + 1, sizeof(char));
+ for (int c = 0; c < strlen(cipher); ++c)
//trc(@"class %@ has characters: %@, index: %u, selected: %@", cipherClass, cipherClassCharacters, keyByte, character);
- sitePassword[c] = character;
- }
+ sitePassword[c] = CharacterFromClass(cipher[c], sitePasswordSeed[c + 1]);
memset(sitePasswordSeed, 0, sizeof(sitePasswordSeed));
// Output the password.
diff --git a/MasterPassword/C/types.c b/MasterPassword/C/types.c
new file mode 100644
index 00000000..983f958f
--- /dev/null
+++ b/MasterPassword/C/types.c
@@ -0,0 +1,63 @@
+//
+// MPTypes.h
+// MasterPassword
+//
+// Created by Maarten Billemont on 02/01/12.
+// Copyright (c) 2012 Lyndir. All rights reserved.
+//
+
+#include
+#include "types.h"
+
+const char *CipherForType(MPElementType type, char seedByte) {
+ if (!(type & MPElementTypeClassGenerated)) {
+ fprintf(stderr, "Not a generated type: %d", type);
+ abort();
+ }
+
+ switch (type) {
+ case MPElementTypeGeneratedMaximum:
+ char *ciphers = { "anoxxxxxxxxxxxxxxxxx", "axxxxxxxxxxxxxxxxxno" };
+ return ciphers[seedByte % 2];
+ case MPElementTypeGeneratedLong:
+ char *ciphers = { "CvcvnoCvcvCvcv", "CvcvCvcvnoCvcv", "CvcvCvcvCvcvno", "CvccnoCvcvCvcv", "CvccCvcvnoCvcv", "CvccCvcvCvcvno", "CvcvnoCvccCvcv", "CvcvCvccnoCvcv", "CvcvCvccCvcvno", "CvcvnoCvcvCvcc", "CvcvCvcvnoCvcc", "CvcvCvcvCvccno", "CvccnoCvccCvcv", "CvccCvccnoCvcv", "CvccCvccCvcvno", "CvcvnoCvccCvcc", "CvcvCvccnoCvcc", "CvcvCvccCvccno", "CvccnoCvcvCvcc", "CvccCvcvnoCvcc", "CvccCvcvCvccno" };
+ return ciphers[seedByte % 21];
+ case MPElementTypeGeneratedMedium:
+ char *ciphers = { "CvcnoCvc", "CvcCvcno" };
+ return ciphers[seedByte % 2];
+ case MPElementTypeGeneratedBasic:
+ char *ciphers = { "aaanaaan", "aannaaan", "aaannaaa" };
+ return ciphers[seedByte % 3];
+ case MPElementTypeGeneratedShort:
+ return "Cvcn";
+ case MPElementTypeGeneratedPIN:
+ return "nnnn";
+ }
+}
+
+const char CharacterFromClass(char characterClass, char seedByte) {
+ switch (characterClass) {
+ case 'V':
+ return "AEIOU"[seedByte];
+ case 'C':
+ return "BCDFGHJKLMNPQRSTVWXYZ"[seedByte];
+ case 'v':
+ return "aeiou"[seedByte];
+ case 'c':
+ return "bcdfghjklmnpqrstvwxyz"[seedByte];
+ case 'A':
+ return "AEIOUBCDFGHJKLMNPQRSTVWXYZ"[seedByte];
+ case 'a':
+ return "AEIOUaeiouBCDFGHJKLMNPQRSTVWXYZbcdfghjklmnpqrstvwxyz"[seedByte];
+ case 'n':
+ return "0123456789"[seedByte];
+ case 'o':
+ return "@&%?,=[]_:-+*$#!'^~;()/."[seedByte];
+ case 'x':
+ return "AEIOUaeiouBCDFGHJKLMNPQRSTVWXYZbcdfghjklmnpqrstvwxyz0123456789!@#$%^&*()"[seedByte];
+ }
+
+ fprintf(stderr, "Unknown character class: %c", characterClass);
+ abort();
+}
+
diff --git a/MasterPassword/C/types.h b/MasterPassword/C/types.h
new file mode 100644
index 00000000..03ab96e5
--- /dev/null
+++ b/MasterPassword/C/types.h
@@ -0,0 +1,42 @@
+//
+// MPTypes.h
+// MasterPassword
+//
+// Created by Maarten Billemont on 02/01/12.
+// Copyright (c) 2012 Lyndir. All rights reserved.
+//
+
+typedef NS_ENUM(NSUInteger, MPElementContentType) {
+ MPElementContentTypePassword,
+ MPElementContentTypeNote,
+ MPElementContentTypePicture,
+};
+
+typedef NS_ENUM(NSUInteger, MPElementTypeClass) {
+ /** Generate the password. */
+ MPElementTypeClassGenerated = 1 << 4,
+ /** Store the password. */
+ MPElementTypeClassStored = 1 << 5,
+};
+
+typedef NS_ENUM(NSUInteger, MPElementFeature) {
+ /** Export the key-protected content data. */
+ MPElementFeatureExportContent = 1 << 10,
+ /** Never export content. */
+ MPElementFeatureDevicePrivate = 1 << 11,
+};
+
+typedef NS_ENUM(NSUInteger, MPElementType) {
+ MPElementTypeGeneratedMaximum = 0x0 | MPElementTypeClassGenerated | 0x0,
+ MPElementTypeGeneratedLong = 0x1 | MPElementTypeClassGenerated | 0x0,
+ MPElementTypeGeneratedMedium = 0x2 | MPElementTypeClassGenerated | 0x0,
+ MPElementTypeGeneratedBasic = 0x4 | MPElementTypeClassGenerated | 0x0,
+ MPElementTypeGeneratedShort = 0x3 | MPElementTypeClassGenerated | 0x0,
+ MPElementTypeGeneratedPIN = 0x5 | MPElementTypeClassGenerated | 0x0,
+
+ MPElementTypeStoredPersonal = 0x0 | MPElementTypeClassStored | MPElementFeatureExportContent,
+ MPElementTypeStoredDevicePrivate = 0x1 | MPElementTypeClassStored | MPElementFeatureDevicePrivate,
+};
+
+extern const char *CipherForType(MPElementType type, char seedByte);
+extern const char CharacterFromClass(char characterClass, char seedByte);
diff --git a/Site/2013-05/algorithm.html b/Site/2013-05/algorithm.html
index 06974284..70293790 100644
--- a/Site/2013-05/algorithm.html
+++ b/Site/2013-05/algorithm.html
@@ -40,7 +40,7 @@
FAQ
Algorithm
Support
- Source (GPL)
+ Source (GPL)
@@ -330,6 +330,19 @@ passWord[i] = passChar
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+