Niet random shuffle

Pagina: 1
Acties:

Acties:
  • 0 Henk 'm!

  • vdvleon
  • Registratie: Januari 2008
  • Laatst online: 08-06-2023
Hallo,

Ik wil het volgende maken: een functie die afhankelijk van de positie en het domein een nieuwe positie returned.

Domein is dus bijv. [0, 10> (dus van af 0 tot 10 (dus tien telt niet mee))

De functie moet dan bijv. zoiets doen:

func(0, 10) -> 3
func(1, 10) -> 2
func(2, 10) -> 9
func(3, 10) -> 1
func(4, 10) -> 8
func(5, 10) -> 4
func(6, 10) -> 5
func(7, 10) -> 7
func(8, 10) -> 6
func(9, 10) -> 0

of:
func(0, 3) -> 2
func(1, 3) -> 1
func(2, 3) -> 0

Het gaat er dus om dat er voor elke pos een unieke waarde uit komt.
Je er bijv. 1 in stopt mag er ook best 1 uit komen (als dit maar niet voor elke
waarde in de reeks gebeurt :P). De getallen mogen niet random zijn, elke keer als ik
de functie uitvoer met de zelfde input moet er het zelfde getal uit komen.

Hoe zou ik dit kunnen maken?

Ik heb dit nodig omdat ik een encryptie wil verzinnen voor mijn profielwerkstuk. Ik heb namelijk de input van de encryptie, bijv 934 bytes. Deze deel ik in, in bijv blokken van 44 bytes (en de laatste dus iets kleiner). Met xor etc. doe ik dan wat met deze bytes, maar ik wil ook in de blokken bytes shufflen, maar wel zo, dat dit elke keer op de zelfde manier gebeurt en weer terug te halen is. De grote van de blokken staat niet vast, dus ik heb het bovenstaande nodig functie dus nodig :P

Alvast bedankt voor je hulp.

Acties:
  • 0 Henk 'm!

  • Creepy
  • Registratie: Juni 2001
  • Laatst online: 22:11

Creepy

Tactical Espionage Splatterer

Voor je voorbeeld: knal de 10 cijfers in een array en bepaal steeds random 2 indexen en wissel die met elkaar om. Dus gewoon de array door elkaar husselen.
Ow crap: ik lees niet goed ;) Je wilt dit met een voorspelbaar patroon doen. Dan nog kan het met wat ik noemde maar zul je je random seed elke keer met dezelfde waarde moeten initialiseren.

[ Voor 38% gewijzigd door Creepy op 22-11-2008 19:21 ]

"I had a problem, I solved it with regular expressions. Now I have two problems". That's shows a lack of appreciation for regular expressions: "I know have _star_ problems" --Kevlin Henney


Acties:
  • 0 Henk 'm!

  • vdvleon
  • Registratie: Januari 2008
  • Laatst online: 08-06-2023
Zoiets had ik ook bedacht, maar dan nog, hoe hussel je deze door elkaar zonder random's en met dat domein wat klein en groot kan worden.

Acties:
  • 0 Henk 'm!

  • Creepy
  • Registratie: Juni 2001
  • Laatst online: 22:11

Creepy

Tactical Espionage Splatterer

Dat voeg ik net toe :P

"I had a problem, I solved it with regular expressions. Now I have two problems". That's shows a lack of appreciation for regular expressions: "I know have _star_ problems" --Kevlin Henney


Acties:
  • 0 Henk 'm!

  • vdvleon
  • Registratie: Januari 2008
  • Laatst online: 08-06-2023
bepaal steeds random 2 indexen
Dus je gebruikt wel random, dat kan dus niet :P

[EDIT]
Daar heb je een punt. Je random met zelfde waarde initialieren. Goed idee. Maar er is een probleem. Op elke pc moet het hetzelfde zijn. Een encryptie moet overal dezelfde uitkomsten hebben. En naar mijn weten is dat initialeren van een random voor elke pc niet het zelfde... (corrent me if i am wrong)

[ Voor 61% gewijzigd door vdvleon op 22-11-2008 19:27 ]


Acties:
  • 0 Henk 'm!

Verwijderd

vdvleon schreef op zaterdag 22 november 2008 @ 19:23:
[...]


Dus je gebruikt wel random, dat kan dus niet :P
Meeste 'randoms' zijn pseudo-random. Met dezelfde seed krijg je dezelfde rij getallen, zoals al aangegeven wordt.

Acties:
  • 0 Henk 'm!

  • vdvleon
  • Registratie: Januari 2008
  • Laatst online: 08-06-2023
Verwijderd schreef op zaterdag 22 november 2008 @ 19:26:
[...]

Meeste 'randoms' zijn pseudo-random. Met dezelfde seed krijg je dezelfde rij getallen, zoals al aangegeven wordt.
Lees mijn Edit :P

Acties:
  • 0 Henk 'm!

  • Creepy
  • Registratie: Juni 2001
  • Laatst online: 22:11

Creepy

Tactical Espionage Splatterer

vdvleon: eerst F5'en en dan posten :P
De standaard random functies zijn niets meer dan een bepaalde berekening dat wordt losgelaten op het vorige getal (of bij het eerste getal de seed). Het lijkt random maar als je als seed steeds hetzelfde pakt dan zul je zien dat het helemaal niet random is.

Pff.. iedereen zit te posten en te editen _/-\o_

[ Voor 8% gewijzigd door Creepy op 22-11-2008 19:28 ]

"I had a problem, I solved it with regular expressions. Now I have two problems". That's shows a lack of appreciation for regular expressions: "I know have _star_ problems" --Kevlin Henney


Acties:
  • 0 Henk 'm!

  • vdvleon
  • Registratie: Januari 2008
  • Laatst online: 08-06-2023
Ik Edit me post maar niet meer :P

Dat weet ik wel. Maar ik wil dus een stuk code hebben die voor elke programmeer taal, pc, etc. het zelfde is. Zou ik dan de bron code van zo'n random moeten pakken en die toevoegen (en dus omschrijven naar bijv. php)?

[Tog nog een Edit :P]
Ik bedenk met net. Dat is ongeveer wel de oplossing, maar dan kan er nog steeds 2 x het zelfde getal er uit komen, terwijl dat niet de bedoeling is.

[ Voor 25% gewijzigd door vdvleon op 22-11-2008 19:37 ]


Acties:
  • 0 Henk 'm!

  • GlowMouse
  • Registratie: November 2002
  • Niet online
vdvleon schreef op zaterdag 22 november 2008 @ 19:31:
Ik Edit me post maar niet meer :P

Dat weet ik wel. Maar ik wil dus een stuk code hebben die voor elke programmeer taal, pc, etc. het zelfde is. Zou ik dan de bron code van zo'n random moeten pakken en die toevoegen (en dus omschrijven naar bijv. php)?
Ja dat kan. Linear congruential generators zijn vrij eenvoudig te programmeren.
Ik bedenk met net. Dat is ongeveer wel de oplossing, maar dan kan er nog steeds 2 x het zelfde getal er uit komen, terwijl dat niet de bedoeling is.
Dus f(x,y) moet, als y vast is, voor iedere x een andere waarde geven? Dan pak je een array met alle elementen uit het domein [0,y-1], en ga je die van positie laten wisselen met je random nummer generator. Het element op positie x is dan f(x,y).

beide bovengenoemde trucs hebben overigens slechte eigenschappen als je echt willekeurige getallen zoekt

Acties:
  • 0 Henk 'm!

  • Orion84
  • Registratie: April 2002
  • Laatst online: 26-09 16:41

Orion84

Admin General Chat / Wonen & Mobiliteit

Fotogenie(k)?

* Orion84 vraagt zich af wat het nut is om blocks op 'random' wijze door elkaar te gooien, als de manier waarop je dat doet, hardcoded in je algoritme zit. Volgens mij vervalt dan de waarde van het op een 'random' manier doen nogal, aangezien het perfect voorspelbaar is. Dan kan je net zo goed volgens een veel eenvoudiger, gestructureerd patroon gaan shuffelen. Dat is een stuk makkelijker in je algoritme verwerken :)

Kijk bijvoorbeeld eens naar AES, daar worden de bytes simpelweg in een tabel gezet en word elke regel gewoon cyclisch een bepaald aantal bytes verschoven. Niks ingewikkelds, makkelijk te definiëren in een algoritme en makkelijk (en efficiënt) te implementeren ook nog. (nu is dat niet het enige onderdeel van AES wat er op is gericht om de structuur van de invoer te slopen, maar toch wel een aardige illustratie dacht ik).

[ Voor 42% gewijzigd door Orion84 op 22-11-2008 20:00 ]

The problem with common sense is that it's not all that common. | LinkedIn | Flickr


Acties:
  • 0 Henk 'm!

  • vdvleon
  • Registratie: Januari 2008
  • Laatst online: 08-06-2023
Dat is ook mijn bedoeling! :P Maar omdat de block grootte kan verschillen moet ik anders verzinnen. Die blockgrootte slaat op de groote van de key, vandaar.

Acties:
  • 0 Henk 'm!

  • Orion84
  • Registratie: April 2002
  • Laatst online: 26-09 16:41

Orion84

Admin General Chat / Wonen & Mobiliteit

Fotogenie(k)?

Geen idee wat je precies in gedachten hebt, maar ook met variabele blokgroottes is er prima een veel eenvoudiger (regelmatig) shuffle schema te verzinnen natuurlijk, wat in mijn ogen net zo effectief is? Tenslotte ondersteunt ook AES verschillende blokgroottes zonder dat dat allerlei rare kunstgrepen vereist.

[ Voor 20% gewijzigd door Orion84 op 22-11-2008 20:19 ]

The problem with common sense is that it's not all that common. | LinkedIn | Flickr


Acties:
  • 0 Henk 'm!

  • vdvleon
  • Registratie: Januari 2008
  • Laatst online: 08-06-2023
Ik heb nu het volgende:

C++:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
int* table;
void generate_table(int len){
        // Vars
        int i, k, t;
        
        // Generate table
        table = new int[len];
        for(i=0; i<len; i++) table[i] = i;
        
        // Shuffle table
        for(i=0, k=len-1; i<len; i++){
            // Swap
            t = table[i];
            table[i] = table[k];
            table[k] = t;
            
            // New k
            k = ((k-i)*(i+1))%len;
        }
    }
};


Om dan mijn byte (unsigned char) array te shufflen:

C++:
1
2
3
4
5
for(j=0; j<len; j++){
    t = input[j];
    input[j] = input[table[j]];
    input[table[j]] = t;
}


Het is aardig random. Dus ik vind het goed zo.

Bedankt voor jullie aandacht :P

Acties:
  • 0 Henk 'm!

  • vdvleon
  • Registratie: Januari 2008
  • Laatst online: 08-06-2023
Bij bijv. len=128 komt er dit uit:

116 127 2 9 110 69 84 51 32 3 36 67 8 13 40 75 64 17 68 11 1 21 100 31 96 57 22 7 24 61 18 91 108 33 14 27 106 37 16 47 20 73 38 99 4 5 34 107 10 49 30 43 12 53 26 63 28 89 54 115 56 93 50 123 112 65 46 59 126 77 42 79 44 105 70 87 72 109 66 23 62 81 52 15 48 85 58 95 60 25 86 103 88 29 82 39 124 97 78 19 122 101 74 111 76 41 102 119 104 45 98 55 90 113 94 35 92 117 80 0 6 121 118 83 120 125 114 71

Ziet er random genoeg uit.

Acties:
  • 0 Henk 'm!

  • Zoijar
  • Registratie: September 2001
  • Niet online

Zoijar

Because he doesn't row...

Een simpele en redelijke goede repeatable random krijg je door te beginnen met een seed N0 en dan:

Xn+1 = 16807*Xn mod 2^31 -1

ofwel:

C++:
1
2
3
4
5
6
7
8
9
const int num = 1000;
int rnds[num];

rnds[0] = 12345; // seed
const int P = 2147483647; // 2^31-1

for (int i=1; i<num; ++i) {
   rnds[i] = (rnds[i-1] * 16807) % P;
} 

rnds is nu gevuld met pseudo random numbers, die uiteraard gelijk zijn voor gelijke seeds.

Permutatie maken door steeds uit een lijst te kiezen, rand() % N, waar N het aantal overgebleven elementen in de lijst is. Na elke keuze dat element wissen. Dus modulo N, N-1, N-2, etc.

[ Voor 17% gewijzigd door Zoijar op 22-11-2008 23:06 ]


Acties:
  • 0 Henk 'm!

  • vdvleon
  • Registratie: Januari 2008
  • Laatst online: 08-06-2023
Je zou het dus als volg kunnen zien:

C++:
1
2
3
4
5
6
7
8
int previous;
void srand(int new_previous){
    previous = new_previous;
}
int rand(){
    previous = (previous*16807)%2147483647; // 2147483647 = 2^31-1
    return previous;
}

Acties:
  • 0 Henk 'm!

  • Zoijar
  • Registratie: September 2001
  • Niet online

Zoijar

Because he doesn't row...

Ja, stel dat je alleen positieve getallen hebt, dan kan je op een simpele manier zo een random permutatie maken.
C++:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
unsigned int rand(unsigned int prev) {
   return (prev * 16807) % 2147483647;
}

int find(int* ar, int index) {
   int i = 0;
   do {
      if (ar[i] >= 0) {--index;}
      ++i;
   } while (index >= 0);

  int result = ar[i-1];
  ar[i-1] = -1;
  return result;
}

void perm(int* src, int* dst, int sz, unsigned int seed) {
   for (int i=0; i<sz; ++i) {
      seed = rand(seed);
      dst[i] = find(src, seed % (sz-i));
   }
}

int main(int argc, char* argv[]) {
    const int sz = 10;
    int src[sz], dst[sz];
    for (int i=0; i<sz; ++i) {
        src[i] = i;
        std::cout << src[i] << "  ";
    }
    std::cout << std::endl;

    perm(src, dst, sz, 12345);
    for (int i=0; i<sz; ++i) std::cout << dst[i] << "  ";
    std::cout << std::endl;

    return 0;
}


Toch leuk in ~20 regels :)

Dit is trouwens best een aardige schuffle, maar om 2 redenen niet "crypto-secure": de rand() functie is van redelijke kwaliteit, maar niet goed genoeg, en de uitdrukking "seed % (sz-i));" is niet uniform random vanwege de modulo operatie. Maar op zich is het voor veel toepassingen goed genoeg. Voordeel is wel dat je elk element random pakt, en niet er steeds twee verwisseld (hoe lang moet je dat doen voordat het "random" is?)

[ Voor 23% gewijzigd door Zoijar op 23-11-2008 12:42 ]


Acties:
  • 0 Henk 'm!

  • vdvleon
  • Registratie: Januari 2008
  • Laatst online: 08-06-2023
Ik heb mijn encryptie af.

Ik maak toch gebruik van de standaart C++ srand() en rand() omdat ik deze alleen gebruik om de key te genereren en niet in de encryptie zelf.

C++:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
//...
// Limits
#define VEL_MAX_BYTES 1028 // Max key length = 1024 bytes = 8192 bits

// vel random
class vel_random{
    public:
        // Functions
        int operator()(){
            return rand();
        }
        
        // Init
        vel_random(int seed){
            srand(seed);
        }
};

// vel key
struct vel_key{
    // Vars
    unsigned int    bytes;
    unsigned char   key[VEL_MAX_BYTES];
    bool            ok;
    int*            table;
    int             key_prefix;
    int             last_len;

    // Init
    vel_key(){
        // Default values
        bytes       = 0;
        ok          = false;
        last_len    = -1;
        key_prefix  = 0;
    }
    
    // De-init
    ~vel_key(){
        // Free table
        if(last_len>-1){
            delete [] table;
            table = NULL;
        }
    }
    
    // Set
    void set(int _bytes, const char _key[VEL_MAX_BYTES]){
        // Check _bytes
        ok = true;
        if(_bytes<1 || _bytes>VEL_MAX_BYTES){
            ok = false;
            return;
        }

        // Set bytes and key (convert char to uchar)
        bytes = _bytes;
        memcpy(key, _key, _bytes);
        
        // Vars
        int i, j;
        
        // Generate key_prefix
        key_prefix = 0;
        for(i=0; i<bytes; i++){
            for(j=0; j<8; j++){
                key_prefix = ((key_prefix<<1)|((key[i]>>((i+j)%8))&(i%2)))%1048575;
            }
        }
    }
    
    // Get key as string
    std::string get(){
        // Vars
        char* tmp = new char[bytes];
        std::string result;
        int i;
        
        // Conversion from uchar to char
        memcpy(tmp, key, bytes);
        
        // Conversion from char to string
        for(i=0; i<bytes; i++) result += (char)tmp[i];
        
        // Return
        return result;
    }
    
    // Generate table
    void generate_table(int len, int pre=0){
        // Check
        if(!ok) return;
        
        // Vars
        int i, k, t;
        
        // Generate table
        table = new int[len];
        for(i=0; i<len; i++) table[i] = i;
        
        // Shuffle table
        for(i=0, k=len-1; i<len; i++){
            // Swap
            t = table[i];
            table[i] = table[k];
            table[k] = t;
            
            // New k
            k = ((k+1)*(i+1)+pre+key_prefix)%len;
        }
        
        // Set last_len
        last_len = len;
    }
    
    // Rotate
    void rotate(int steps){
        // Check
        if(!ok) return;
        if(steps<1) return;
        steps = steps%bytes;
        
        // Vars
        unsigned char temp[bytes];
        int i;
        
        // Rotate bytes
        memcpy(temp, key, bytes);
        for(i=0; i<bytes-1; i++) key[i] = temp[i+1];
        key[i] = temp[0];
        
        // Rotate bits
        memcpy(temp, key, bytes);
        for(i=0; i<bytes-1; i++) key[i] = ((key[i]<<4)&0xF0)|(temp[i+1]>>4);
        key[i] = ((key[i]<<4)&0xF0)|(temp[0]>>4);

        // Rotate again
        rotate(steps-1);
    }
};

// vel make key (by string)
vel_key vel_make_key(std::string str){
    // Get Length and check it
    if(str.length()<1)      str = "empty";
    if(str.length()>VEL_MAX_BYTES)  str = str.substr(0, VEL_MAX_BYTES);

    // Make and return vel_key
    vel_key key;
    key.set(str.length(), str.c_str());
    return key;
}

// vel generate key (by length)
vel_key vel_generate_key(int len){
    // Check length
    if(len<0) len = VEL_MAX_BYTES;
    if(len>VEL_MAX_BYTES) len = len%VEL_MAX_BYTES;
    
    // Vars
    char* buf = new char[len];
    std::ifstream ifs;
    int i;
    
    // Init random number generator
    vel_random rand(time(NULL));
    
    // Generate key
    for(i=0; i<len; i++) buf[i] = (char)rand();
    
    // Make key
    vel_key key;
    key.set(len, buf);
    
    // Free buf
    delete [] buf;
    buf = NULL;
    
    // Return
    return key;
}

// class vel_encryption
class vel_encryption{
    private:
        // Vars
        vel_key key;
        
        // string to uchar
        void string_to_uchar(unsigned char* dest, const std::string src){
            // Copy
            memcpy(dest, src.c_str(), src.length());
        }
        
        // uchar to string
        void uchar_to_string(std::string &dest, const unsigned char* src, const int len){
            // Vars
            char* cstr = new char[len];
            int i;
            
            // Clear dest
            dest.clear();
            
            // Copy src to cstr
            memcpy(cstr, src, len);
            
            // Copy cstr to dest
            for(i=0; i<len; i++) dest += cstr[i];
            
            // Free pointer
            delete [] cstr;
            cstr = NULL;
        }
        
    public:
        // set_key
        void set_key(vel_key _key){
            key = _key;
        }
        
        // encrypt
        void encrypt(const std::string source, std::string &desteny){
            // Check key
            if(!key.ok){
                desteny = source;
                return;
            }

            // Vars
            int len = source.length();
            int clen, i, j, k, t;
            unsigned char* input;

            // Convert source to unsigned char
            input = new unsigned char[len];
            string_to_uchar(input, source);
            
            // -----------------------------------------------------------------------------
            
            // Encrypt
            for(k=0, i=0; i<len; i+=key.bytes, k++){
                // Get block range
                clen = key.bytes>(len-i)?(len-i):key.bytes;
                
                // Rotate key
                key.rotate(((key.key[0]&0x3C)>>2)+1);
                
                // Generate block table
                key.generate_table(clen, k);
                
                // Shuffle block
                for(j=0; j<clen; j++){
                    // Swap
                    t = input[i+j];
                    input[i+j] = input[i+key.table[j]];
                    input[i+key.table[j]] = t;
                }

                // Encrypt current block
                for(j=0; j<clen; j++){
                    input[i+j] ^=  key.key[j];
                    input[i+j] ^=  key.key[clen-j-1]>>4;
                    input[i+j] ^=  key.key[key.table[clen-j-1]]&0xF;
                }
            }

            // -----------------------------------------------------------------------------

            // Set result
            uchar_to_string(desteny, input, len);
            
            // Free pointers
            delete [] input;
            input   = NULL;
        }
        
        // decrypt
        void decrypt(std::string source, std::string &desteny){
            // Check key
            if(!key.ok){
                desteny = source;
                return;
            }
            
            // Vars
            int len = source.length();
            int clen, i, j, k, t;
            unsigned char* input;

            // Convert source to unsigned char
            input = new unsigned char[len];
            string_to_uchar(input, source);
            
            // -----------------------------------------------------------------------------
            
            // Decrypt
            for(k=0, i=0; i<len; i+=key.bytes, k++){
                // Get block range
                clen = key.bytes>(len-i)?(len-i):key.bytes;
                
                // Rotate key
                key.rotate(((key.key[0]&0x3C)>>2)+1);
                
                // Generate block table
                key.generate_table(clen, k);
                
                // Decrypt current block (XOR)
                for(j=0; j<clen; j++){
                    input[i+j] ^=  key.key[j];
                    input[i+j] ^=  key.key[clen-j-1]>>4;
                    input[i+j] ^=  key.key[key.table[clen-j-1]]&0xF;
                }
                
                // Shuffle block
                for(j=clen-1; j>=0; j--){
                    // Swap
                    t = input[i+j];
                    input[i+j] = input[i+key.table[j]];
                    input[i+key.table[j]] = t;
                }
            }

            // -----------------------------------------------------------------------------
            
            // Set result
            uchar_to_string(desteny, input, len);
            
            // Free pointers
            delete [] input;
            input   = NULL;
        }
};

// Main
int main(int argc, char** argv){
    // ...
    return 0;
}


De hele code is hier te vinden.

Heeft er iemand zin om mijn programmeer werk te beoordelen en mijn encryptie? Is het wel veilig, of is het zo te kraken?

[EDIT]
Ik heb uit de code een regel geschrapt: if(last_len==len) return; in de generate_table functie.

[EDIT2]
Ik heb nog wat code geschrapt die niet bijdragen aan sterkte encryptie

[EDIT3]
Ik heb de rotate van de key (key.rotate functie) (hopelijk) iets ingewikkelder gemaakt.

[EDIT4]
Domme bitwise foutjes opgelost

[EDIT5]
Wat domme rotate code aangepast.

[ Voor 100% gewijzigd door vdvleon op 25-11-2008 00:02 ]


Acties:
  • 0 Henk 'm!

  • Orion84
  • Registratie: April 2002
  • Laatst online: 26-09 16:41

Orion84

Admin General Chat / Wonen & Mobiliteit

Fotogenie(k)?

Altijd interessant, mensen die hun eigen crypto verzinnen :P

Ik zal er een dezer dagen eens naar kijken :)

The problem with common sense is that it's not all that common. | LinkedIn | Flickr


Acties:
  • 0 Henk 'm!

  • vdvleon
  • Registratie: Januari 2008
  • Laatst online: 08-06-2023
Ik wou als praktisch onderdeel voor mijn eindwerkstuk/profielwerkstuk (6 VWO N&T) over encryptie (en het grootste gedeelte over Enigma) mijn eigen encryptie schrijven en er bij vertellen waarom hij wel/niet goed werkt. Kijk er maar eens na :D ik hoop dat hij lang standhoud. Zou ik anders een ge-encrypt bericht posten en moeten jullie heb kraken?

Acties:
  • 0 Henk 'm!

  • pedorus
  • Registratie: Januari 2008
  • Niet online
Tips/vragen:
  1. Wat is het nut van XOR 0x57? Hoe goed is XOR-encryptie?
  2. Hoeveel verschillende keys kan generate_key genereren?
  3. Waarom is de encryptie per vol block over meerdere encrypties altijd hetzelfde (shuffle+XOR-encryptie), en over meer blokken niet onachterhaalbaar anders?
  4. Hoe shuffle je, hoeveel mogelijkheden levert dat op?
  5. Hoeveel makkelijker zou implementeren in java of c# zijn?

Vitamine D tekorten in Nederland | Dodelijk coronaforum gesloten


Acties:
  • 0 Henk 'm!

  • .oisyn
  • Registratie: September 2000
  • Laatst online: 02:49

.oisyn

Moderator Devschuur®

Demotivational Speaker

Een goede random key is overigens minstens zo belangrijk. Die van jou is dat zeer zeker niet. Als ik tot op de seconde precies weet wanneer iemand's key is gegenereerd kan ik die key reproduceren. Als ik het op de kwartier nauwkeurig kan bepalen, dan hoef ik gemiddeld gezien maar 450 keys uit te proberen.

Voor cryptografie is de tijd nooit een goede bron van entropie.
pedorus schreef op maandag 24 november 2008 @ 11:09:
Tips/vragen:
  1. Hoeveel makkelijker zou implementeren in java of c# zijn?
Vrijwel niet makkelijker.

[ Voor 35% gewijzigd door .oisyn op 24-11-2008 12:03 ]

Give a man a game and he'll have fun for a day. Teach a man to make games and he'll never have fun again.


Acties:
  • 0 Henk 'm!

  • pedorus
  • Registratie: Januari 2008
  • Niet online
Nou ja, in de API's van die talen zit standaard cryptografische functionaliteit zoals cryptografische random numbers... Ik bedoelde niet die 3 regels geheugenmanagement :)

Vitamine D tekorten in Nederland | Dodelijk coronaforum gesloten


Acties:
  • 0 Henk 'm!

  • .oisyn
  • Registratie: September 2000
  • Laatst online: 02:49

.oisyn

Moderator Devschuur®

Demotivational Speaker

Ik dacht dat het om de code van de TS ging. Daarnaast is de std::tr1 random library behoorlijk uitgebreid, met verschillende random generators en functionaliteit om voor de juiste distributie te zorgen.

[ Voor 64% gewijzigd door .oisyn op 24-11-2008 13:21 ]

Give a man a game and he'll have fun for a day. Teach a man to make games and he'll never have fun again.


Acties:
  • 0 Henk 'm!

  • Zoijar
  • Registratie: September 2001
  • Niet online

Zoijar

Because he doesn't row...

pedorus schreef op maandag 24 november 2008 @ 11:09:
Tips/vragen:
  1. Wat is het nut van XOR 0x57? Hoe goed is XOR-encryptie?
  2. Hoeveel verschillende keys kan generate_key genereren?
Goede punten.

Punt 1. Ik zie zinloze obfuscation in je code. Het is net zo goed om gewoon the XOR-en met 1 byte uit je key, als allemaal ingewikkelde dingen te doen. Encryptie moet je zo simpel mogelijk houden met een sterk basis idee. Elke keer dat je iets ingewikkelds doet dat niet direct kracht toevoegt aan het basis idee heb je de kans dat je cypher juist zwakker wordt, maar nooit sterker.

Overigens is "XOR-encryptie" de enige volledig veilige encryptie techniek, als je key length even groot is al je bericht en maar een keer wordt gebruikt :) Je krijgt dan in essentie random data binnen, dus die kan je nooit kraken. Het wordt hier zwakker omdat: de key-length kleiner is dan het bericht, en de key wordt voor meerdere berichten gebruikt. Op en duur is dat kraakbaar met frequentie analyse (maar wel heel moeilijk).

Punt 2. oisyn zei het ook al min of meer, het aantal in essentie verschillende keys hangt af van je seed. Zelfs als je op nanoseconde niveau je klok sampled, dan heb je per seconde alsnog maar 1E9 verschillende keys. Dat is een aantal dat makkelijk kraakbaar is. Als je je klok op microseconde niveau uitleest, wat vaak het geval is, en je weet welke dag de key is gemaakt, dan hoef je maar 86 400 000 000 keys te proberen (naar verwachting de helft)

Acties:
  • 0 Henk 'm!

  • Confusion
  • Registratie: April 2001
  • Laatst online: 01-03-2024

Confusion

Fallen from grace

Encryptie en decryptie zijn deterministische operaties. Welke functie kan randomness daar in hebben?

Wie trösten wir uns, die Mörder aller Mörder?


Acties:
  • 0 Henk 'm!

  • Jaap-Jan
  • Registratie: Februari 2001
  • Laatst online: 26-09 17:47
Confusion schreef op maandag 24 november 2008 @ 13:53:
Encryptie en decryptie zijn deterministische operaties. Welke functie kan randomness daar in hebben?
Sessiesleutels genereren?

| Last.fm | "Mr Bent liked counting. You could trust numbers, except perhaps for pi, but he was working on that in his spare time and it was bound to give in sooner or later." -Terry Pratchett


Acties:
  • 0 Henk 'm!

  • pedorus
  • Registratie: Januari 2008
  • Niet online
.oisyn schreef op maandag 24 november 2008 @ 13:16:
Ik dacht dat het om de code van de TS ging. Daarnaast is de std::tr1 random library behoorlijk uitgebreid, met verschillende random generators en functionaliteit om voor de juiste distributie te zorgen.
Dat is voor simulaties als ik snel kijk. Ze zijn vast beter dan rand() (soms maar een vaste reeks van (minder dan) 32767 getallen), maar niet goed genoeg voor cryptografie.

Vitamine D tekorten in Nederland | Dodelijk coronaforum gesloten


Acties:
  • 0 Henk 'm!

  • .oisyn
  • Registratie: September 2000
  • Laatst online: 02:49

.oisyn

Moderator Devschuur®

Demotivational Speaker

Je hebt gelijk, ik dacht even dat MT geschikt was. Maar dan nog, als je in C++ werkt heb je standaard OS-specifieke functionalteit tot je beschikking, waarmee het ook kan. Stellen dat het in Java of C# makkerlijk gaat vind ik echt onzin :)

Give a man a game and he'll have fun for a day. Teach a man to make games and he'll never have fun again.


Acties:
  • 0 Henk 'm!

  • Confusion
  • Registratie: April 2001
  • Laatst online: 01-03-2024

Confusion

Fallen from grace

pedorus schreef op maandag 24 november 2008 @ 14:57:
Dat is voor simulaties als ik snel kijk. Ze zijn vast beter dan rand() (soms maar een vaste reeks van (minder dan) 32767 getallen), maar niet goed genoeg voor cryptografie.
Afhankelijk van wat de topicstarter wil, zijn er helemaal geen random getallen nodig bij zijn crypto implementatie. Dan is dit gediscussieer over al dan niet voldoende random RNG's bijzonder afleidend.

En als je dan gaat mieren over randomness, neem dan het zekere voor het onzekere en gebruik gewoon een Mersenne Twister, zoals tegenwoordig in ieder geval in Java en Python de standaard is.

[ Voor 7% gewijzigd door Confusion op 24-11-2008 16:36 ]

Wie trösten wir uns, die Mörder aller Mörder?


Acties:
  • 0 Henk 'm!

  • pedorus
  • Registratie: Januari 2008
  • Niet online
Confusion schreef op maandag 24 november 2008 @ 16:33:
Afhankelijk van wat de topicstarter wil, zijn er helemaal geen random getallen nodig bij zijn crypto implementatie. Dan is dit gediscussieer over al dan niet voldoende random RNG's bijzonder afleidend.
In het algoritme van TS werd al rand() gebruikt, waardoor er een ernstige zwakheid ontstaat. Ook zijn goede willekeurige nummers sterk verbonden met elke goede vorm van encryptie. Als je bijvoorbeeld 2x exact hetzelfde bericht encrypt, wil je meestal niet dat je ook 2x exact hetzelfde resultaat krijgt. Als je bijvoorbeeld een TLS/SSL verbinding opzet, gebruik je daarom random numbers.
En als je dan gaat mieren over randomness, neem dan het zekere voor het onzekere en gebruik gewoon een Mersenne Twister, zoals tegenwoordig in ieder geval in Java en Python de standaard is.
Je doet je naam eer aan ;) Die is dus voor simulatie. Zelfs in gelinkte artikel:
Unlike Blum Blum Shub, the algorithm in its native form is not suitable for cryptography.

Vitamine D tekorten in Nederland | Dodelijk coronaforum gesloten


Acties:
  • 0 Henk 'm!

  • .oisyn
  • Registratie: September 2000
  • Laatst online: 02:49

.oisyn

Moderator Devschuur®

Demotivational Speaker

Confusion schreef op maandag 24 november 2008 @ 16:33:
[...]

Afhankelijk van wat de topicstarter wil, zijn er helemaal geen random getallen nodig bij zijn crypto implementatie.
Jawel, voor het genereren van de sleutel. En precies om die reden moet de PRNG sterk zijn, omdat anders de sleutel makkelijk te achterhalen is.

Give a man a game and he'll have fun for a day. Teach a man to make games and he'll never have fun again.


Acties:
  • 0 Henk 'm!

  • vdvleon
  • Registratie: Januari 2008
  • Laatst online: 08-06-2023
Eff over de key generator, die heeft niks te maken met de encryptie zelf. Ik heb deze dan ook alleen achteraf gemaakt om mijn encryptie te kunnen testen. Wil je een betere, kan je dat altijd nog later toevoegen of van buiten dit programma een key genereren.

Maar als ik de ^0x53 weg haal (is idd zinloos, mijn fout :P) hoe is dat de rest van de code? Want namelijk per ronde (per blok dus) word de table waar mee je de dat block 'husselt´ anders. Is dit iets wat het kraken bemoeilijkt of maakt dit niet zo veel uit? Ook na elke ronde word de key 'door gedraait'.

En nog 1 ding, maakt het feit dat de key een variable grote heeft uit ten opzichte van de kraakbaarheid? Want met bruteforcen maakt het vinden van de key bij een lagere grote makkelijker, maar standaart patronen worden weer lastiger om te vinden (neem ik aan).

Acties:
  • 0 Henk 'm!

  • vdvleon
  • Registratie: Januari 2008
  • Laatst online: 08-06-2023
pedorus schreef op maandag 24 november 2008 @ 11:09:
Tips/vragen:
  1. Wat is het nut van XOR 0x57? Hoe goed is XOR-encryptie?
  2. Hoeveel verschillende keys kan generate_key genereren?
  3. Waarom is de encryptie per vol block over meerdere encrypties altijd hetzelfde (shuffle+XOR-encryptie), en over meer blokken niet onachterhaalbaar anders?
  4. Hoe shuffle je, hoeveel mogelijkheden levert dat op?
  5. Hoeveel makkelijker zou implementeren in java of c# zijn?
  1. Niet, heb deze ook weg gehaalt
  2. In theorie, als het echt random is, 256^aantal bytes
  3. Is hier de tip om niet alleen per block de 'shuffle' te laten verschillen maar ook de encryptie (xor)?
  4. Het is niet echt shufflen, maar gewoon afhanklijk van de key maakt hij een tabel waar mee bij de bytes in het block 'husselt'
  5. In priciepe is deze encryptie in elke taal te inplemneteren. Ik ga ook proberen om deze in php na te maken (na dat de encryptie een beetje degelijk is)
Ik hoop je tips / vragen begrepen te hebben :P

Acties:
  • 0 Henk 'm!

  • Confusion
  • Registratie: April 2001
  • Laatst online: 01-03-2024

Confusion

Fallen from grace

.oisyn schreef op maandag 24 november 2008 @ 17:29:
Jawel, voor het genereren van de sleutel. En precies om die reden moet de PRNG sterk zijn, omdat anders de sleutel makkelijk te achterhalen is.
Bij de simpelste encryptie kiest iemand de sleutel, bijvoorbeeld om zijn bestanden te versleutelen. Het lijkt me voor de topicstarter wel zo makkelijk als hij het zichzelf niet moeilijker maakt door daar tegelijk ook over na te moeten denken. Doe eerst die encryptie maar.

Het genereren van sleutels heeft op zich ook eigenlijk niets met encryptie te maken: het heeft met het toepassen van die encryptie te maken. Het lijkt mierenneuken, maar ik denk dat het heel belangrijk is om dat soort onderscheiden te maken, omdat je anders al snel verdrinkt in begripsverwarring.
pedorus schreef op maandag 24 november 2008 @ 17:06:
Als je bijvoorbeeld 2x exact hetzelfde bericht encrypt, wil je meestal niet dat je ook 2x exact hetzelfde resultaat Je doet je naam eer aan ;) Die is dus voor simulatie. Zelfs in gelinkte artikel:
Daar is makkelijk omheen te komen door bijvoorbeeld de SHA1 van een gegenereerd resultaat te nemen. Er zijn ook andere (lees: efficientere) manieren om de Mersenne Twister als basis voor cryptografisch bruikbare random getallen te kunnen gebruiken.

[ Voor 28% gewijzigd door Confusion op 24-11-2008 19:30 ]

Wie trösten wir uns, die Mörder aller Mörder?


Acties:
  • 0 Henk 'm!

  • .oisyn
  • Registratie: September 2000
  • Laatst online: 02:49

.oisyn

Moderator Devschuur®

Demotivational Speaker

Confusion schreef op maandag 24 november 2008 @ 19:22:
[...]

Bij de simpelste encryptie kiest iemand de sleutel, bijvoorbeeld om zijn bestanden te versleutelen. Het lijkt me voor de topicstarter wel zo makkelijk als hij het zichzelf niet moeilijker maakt door daar tegelijk ook over na te moeten denken. Doe eerst die encryptie maar.
That's fine, maar het stond in z'n code en hij vroeg om commentaar. Die kreeg hij. Dat hij achteraf niet de generate_key() functie bedoelde konden we natuurlijk ook niet ruiken.
Het genereren van sleutels heeft op zich ook eigenlijk niets met encryptie te maken: het heeft met het toepassen van die encryptie te maken. Het lijkt mierenneuken, maar ik denk dat het heel belangrijk is om dat soort onderscheiden te maken, omdat je anders al snel verdrinkt in begripsverwarring.
Toch maken PRNG's een heel belangrijk deel uit van de cryptografie, dus ik zou willen stellen dat jij nu degene bent die de boel zit te verwarren (wat ook wel bij je nick past ;)), ookal heb je het louter over encryptie en niet over cryptografie.
[over de onbruikbaarheid van Mersenne Twisters in cryptografie]
Daar is makkelijk omheen te komen door bijvoorbeeld de SHA1 van een gegenereerd resultaat te nemen.
Daar wil ik wel een bewijs van zien dan, zo niet dan blijft het voor mij security through obscurity. Van een MT blijkt dat hij te voorspellen is gegeven een gelimiteerde set gegenereerde outputs. Natuurlijk is het zo dat bij de SHA1 hash de originele MT-output niet te achterhalen is. Echter wil dat niet zeggen dat dat voor een reeks opeenvolgende MT-outputs en hun bijbehorende hashes ook het geval is.

[ Voor 23% gewijzigd door .oisyn op 24-11-2008 19:38 ]

Give a man a game and he'll have fun for a day. Teach a man to make games and he'll never have fun again.


Acties:
  • 0 Henk 'm!

  • vdvleon
  • Registratie: Januari 2008
  • Laatst online: 08-06-2023
Maar dat is niet mijn bedoeling van deze topic. Het gaat er mij om:
  1. Is de code uberhaupt goed geprogrammeert
  2. Is de encryptie uberhaupt wel (een beetje :P) goed
Als deze twee bovenstaande punten ok zijn, ga ik misschien bezig met het ontwerpen / toepassen van een goede keygen wat inderdaad een belangrijk punt is bij een encryptie. Maar zoals ik al eerder zei, daar ben ik nog niet echt mee bezig geweest.

BTW, mijn code is weer iets aangepast. Download het bestand maar of kijk een paar berichten terug naar de code. Je kan het bestand ook hier downloaden.

Acties:
  • 0 Henk 'm!

  • Confusion
  • Registratie: April 2001
  • Laatst online: 01-03-2024

Confusion

Fallen from grace

Ik zou zeggen: regel Applied Cryptography even ergens ;).

Wie trösten wir uns, die Mörder aller Mörder?


Acties:
  • 0 Henk 'm!

  • vdvleon
  • Registratie: Januari 2008
  • Laatst online: 08-06-2023
Ik weet wel ongeveer waar een goede encryptie aan moet voldoen. Er moeten niet te veel patronen in voor komen. Er mogen geen te korte keys gebruikt worden, etc. etc. etc.

Dan stel ik mijn vraag anders: heb ik met mijn code een beetje sterke encryptie weten toe te passen, of moet ik dan iets meer uit de kast halen of gewoon er een studie van maken aan de universiteit :P

We kunnen eigenlijk ook gewoon de proef op de som nemen. Ik pak een bestand van bijv. een 512 KB en encrypt deze en jullie mogen dus de bron code weten die er voor gebruikt is. Voor de zekerheid pak ik even een goede keygen om er zeker van te zijn dat daar het probleem niet ligt. Jullie proberen (als jullie daar zin en tijd voor hebben natuurlijk) dan achter het originele bestand te komen. Als jullie dit snel weten te achterhalen (binnen een week bijv. :P) dan is de encryptie niet al te bijster. Ik geef dus ook niet de grote van de key mee, dat is denk ik / hoop ik misschien juist een sterkte van deze encryptie.

Acties:
  • 0 Henk 'm!

  • Zoijar
  • Registratie: September 2001
  • Niet online

Zoijar

Because he doesn't row...

vdvleon schreef op maandag 24 november 2008 @ 19:35:
Maar dat is niet mijn bedoeling van deze topic. Het gaat er mij om:
  1. Is de code uberhaupt goed geprogrammeert
  2. Is de encryptie uberhaupt wel (een beetje :P) goed
Ik heb niet zo'n zin om je code helemaal te analyseren; ik b liever dat je gewoon simpel en sammengevat uitlegt wat je hebt gedaan. als ik het goed begrijp heb je een "rotating substiution cypher met variable key-length" geschreven. Die zijn best ok (volgens mij hetzelfde basis algoritme als de enigma) maar hedendaags niet "secure". Niettemin zou ik het niet kunnen kraken als je nu iets post. Ik herinner me dat er een hoofdstuk over dit soort cypher in een van mijn crypto boeken staat (lang lang geleden dat ik die heb gelezen...) en volgens mij hingen daar termen aan als 'key length analysis' en 'frequency analysis'. Het kwam erop neer dat als je genoeg encrypted tekst had waarvan je de taal weet dat je de sleutel dan kon vinden. Ingewikkeld gedoe, en ik weet zeker dat ze dat nu ook veel beter kunnen. Verder kan je 2^32 ook makkelijk brute-forcen op huidige parallelle clusters (chinese lottery).

(ik denk trouwens dat je met iets van library support in minder regels een RSA encryptie kan implementeren ;) )

[ Voor 4% gewijzigd door Zoijar op 24-11-2008 19:59 ]


Acties:
  • 0 Henk 'm!

  • vdvleon
  • Registratie: Januari 2008
  • Laatst online: 08-06-2023
Het gaat erom dat ik een eigen encryptie verzin voor mijn profiel werkstuk en daarbij vertel waar het wel goed dan wel niet goed werkt (in de huidige tijd).

Mijn code doet het volgende:
  • Eerst initialiseert hij de key
    Er word een getal berekent afhankelijk van wat er in de key staat. Voor dit getal kan je met meerdere input hetzelfde resultaat krijgen (beetje het md5 princiepe)
  • Nu begint de encryptie: [list]
  • Je pakt het eerste blok, grote is even groot als de key, is de key groter dan de aantal bytes die nog beschikbaar zijn, dan past de block grote zich aan aan deze overige aantal bytes
  • Nu genereer je een tabel die afhankelijk is van deze blok grote, het hoeveelste blok het is en het getal wat bij de key initialisatie gemaakt is
  • Nu gaat hij voor elke byte in het blok, elementen verwisselen afhankelijk van deze net gegeneerde tabel
  • Nu word elke byte van de nieuwe ontstaande block ge-xor-ed met de byte die op de zelfde positie staat in de key (block[i] ^= key[i] in het kort)
  • Nu is er 1 block af gehandelt. Na elk block word de key geroteerde (de aantal keer dat hij geroteerd word wisselt steeds) -> [code=c++](k%7)+(k%5)+(k%3)+(k%2)[/code]. Bij dit roteren worden de bytes in de key door geroteerd en worden de bits van deze bytes ook geroteerd [code=c++]for(i=0; i<bytes-1; i++) key[i] = ((key[i]<<1)&0xFF)|((temp[i+1]>>7)&1); key[i] = ((key[i]<<1)&0xFF)|((temp[0]>>7)&1);[/code]
  • Nu word er dus weer een nieuw blok behandelt. Er word weer een nieuwe (andere) tabel gegenereerd. En bij het xor-en word er nu met andere getallen ge-xor-ed omdat de posities van de bytes en de bytes opzich zijn verandert.
  • [/list]

Acties:
  • 0 Henk 'm!

  • vdvleon
  • Registratie: Januari 2008
  • Laatst online: 08-06-2023
Voor de mensen die wel zin hebben om mijn encrypte te 'kraken'.

Hier bij zit een link naar een zip file met het vel.cpp bestand (de encryptie code) en een bestand wat ik met die code heb ge-encrypted. Voor het generen van de key heb ik ssh-keygen gebruikt en bestand van tussen de 1 en de 1024 bytes gemaakt (om dat ssh-keygen -t das -b 1024 een 1024 bits key geeft heb ik deze meerdere keren uitgevoerd (en natuurlijk de base64_decode erover heen gegooid)).

Nu is het aan jullie om de originele inhoud van het bestand te achterhalen. Je kan het originele bestand naar mij sturen (met link ofsow) of md5sum gebruiken zodat ik kan controleren of je (waarschijnlijk) het juiste originele bestand terug hebt gevonden.

Link naar bestand

De code die ik heb gebruikt (vel.cpp) bevat misschien nog fouten. Omdat jullie natuurlijk wel de code moeten hebben die op dat moment gebruikt is heb ik deze in de zip toegevoegd. Later is deze code dus misschien al verandert / verbeterd.

[ Voor 17% gewijzigd door vdvleon op 24-11-2008 20:58 ]


Acties:
  • 0 Henk 'm!

  • pedorus
  • Registratie: Januari 2008
  • Niet online
Het gekke is dat na mijn tips de encryptie fors achteruit is gegaan... :X Je doet nu nog maar een XOR met 1 waarde uit de roterende key. XOR-encryptie is perfect zolang de stream waarmee geencrypt wordt willekeurig en onbekend genoeg is voor de aanvaller, maar dat is hier niet zo. De eerste 2 blocks is de key waarmee geXORd wordt zelfs exact hetzelfde als ik het goed zie (rotatie van 0 bij k=0).

Stel we hebben als input standaard ASCII tekst, waarbij de 8e bit niet gebruikt wordt. De eerste 2 blocks weten we alle 8e bits van key. Daarna wordt de key 4 bytes en 4 bits geroteerd, zodat we alle 4e bits van de key weten. Daarna 6 bits, zodat we alle 6e bits weten, enzovoort. Op een gegeven moment weten we alle bits, en is het kraken gelukt... :) rotate gaat nu heftig inefficiënt trouwens.

En dan maak ik nog geen gebruik van mogelijk ongelukkige korte keys (vb: "a"). De niet-Knuth shuffle werkt ook niet heel erg goed (voorbeeld: 3 verwisselingen op set van 3 geeft geen willekeurige verdeling), maar dat is voor het kraken nog niet zo heel relevant.
Confusion schreef op maandag 24 november 2008 @ 19:22:
Daar is makkelijk omheen te komen door bijvoorbeeld de SHA1 van een gegenereerd resultaat te nemen.

Je pakt iets dat stuk is, gooit er nog een keer iets dat al lang stuk is overheen, en beweert dan dat volgende bits nooit met grotere kans dan de standaard 0.5 kunnen worden voorspeld? ;)
De les is hier: niet zomaar zelf gaan kloten aan secure random numbers. Hier nog een bekend voorbeeld van Debian met ssh.

Vitamine D tekorten in Nederland | Dodelijk coronaforum gesloten


Acties:
  • 0 Henk 'm!

  • Confusion
  • Registratie: April 2001
  • Laatst online: 01-03-2024

Confusion

Fallen from grace

pedorus schreef op maandag 24 november 2008 @ 21:25:
[small]
Je pakt iets dat stuk is, gooit er nog een keer iets dat al lang stuk is overheen, en beweert dan dat volgende bits nooit met grotere kans dan de standaard 0.5 kunnen worden voorspeld? ;)
Het Mersenne Twister algoritme is sowieso niet stuk. Dat is zoiets als zeggen dat een schroevendraaier stuk is, omdat je er niet goed spijkers mee kan hameren, terwijl je een varieteit aan spijkers en schroefdraadtrekkers beschikbaar hebt.

SHA is voor deze toepassing netzomin stuk. Leuk dat je collissions kan veroorzaken, so what? Bovendien niet relevant, want er zijn dus andere manieren om de Mersenne Twister te gebruiken om cryptografisch veilige random getallen te genereren.

offtopic:
En wat betreft het Debian-ssh verhaal: dat wijten aan 'zelf klooien met secure random numbers' is een ongelovelijke misrepresentatie van de gang van zaken.

[ Voor 20% gewijzigd door Confusion op 24-11-2008 22:01 ]

Wie trösten wir uns, die Mörder aller Mörder?


Acties:
  • 0 Henk 'm!

  • vdvleon
  • Registratie: Januari 2008
  • Laatst online: 08-06-2023
pedorus schreef op maandag 24 november 2008 @ 21:25:
Het gekke is dat na mijn tips de encryptie fors achteruit is gegaan... :X Je doet nu nog maar een XOR met 1 waarde uit de roterende key. XOR-encryptie is perfect zolang de stream waarmee geencrypt wordt willekeurig en onbekend genoeg is voor de aanvaller, maar dat is hier niet zo. De eerste 2 blocks is de key waarmee geXORd wordt zelfs exact hetzelfde als ik het goed zie (rotatie van 0 bij k=0).

Stel we hebben als input standaard ASCII tekst, waarbij de 8e bit niet gebruikt wordt. De eerste 2 blocks weten we alle 8e bits van key. Daarna wordt de key 4 bytes en 4 bits geroteerd, zodat we alle 4e bits van de key weten. Daarna 3 bits, zodat we alle 1e bits weten, enzovoort. Op een gegeven moment weten we alle bits, en is het kraken gelukt... :) rotate gaat nu heftig inefficiënt trouwens.
Ok, hier heb je een punt :P Dan moet ik de deze code aanpassen :
C++:
1
key.rotate((k%7)+(k%5)+(k%3)+(k%2));

en / of met k=1 beginnen en / of eerste rotaten voordat ik de tabel genereer en 'hussel' en encrypt.

Moet ik dan deze code gewoon weer weg halen?:
C++:
1
2
3
4
// Rotate bits
memcpy(temp, key, bytes);
for(i=0; i<bytes-1; i++) key[i] = ((key[i]<<1)&0xFF)|((temp[i+1]>>7)&1);
key[i] = ((key[i]<<1)&0xFF)|((temp[0]>>7)&1);


Want inderdaad, zo word het heel makkelijk om op plekken waar bij de input een 0 staat de hele key te achterhalen.

Wat ik ook zou kunnen doen, is niet de aantal keer dat er gerotate word per block kunnen laten afhanken van het zoveelste block, maar afhankelijk van de key. Bijv:
C++:
1
2
// Rotate key
key.rotate((key.key[0]&0x3C)+1);

Acties:
  • 0 Henk 'm!

  • vdvleon
  • Registratie: Januari 2008
  • Laatst online: 08-06-2023
De code is upgedate (http://www.vdvleon.nl/vel.cpp) en bedankt voor je moeite @ pedorus

Acties:
  • 0 Henk 'm!

  • roy-t
  • Registratie: Oktober 2004
  • Laatst online: 19-09 10:19
(klein nieuwsgierirg vraag je, maar toen ik op 6vwo zat was mijn leraar al in awe als je een paar bewegende blokjes liet zien met wat VB6 code erachter, nu wil je het zeker goed krijgen maar Cryptografie is iets waar ik mezelf nog niet aan waag, ik vraag me af of je goed over het idee van de encryptie hebt nagedacht en dat dit niet gewoon maar een bestaand algoritme is maar dan net even iets anders. :) verder goed werk dat je in 6VWO al zo goed C++ onder de knie hebt! Zeker informatica gaan studeren! :)

~ Mijn prog blog!


Acties:
  • 0 Henk 'm!

  • vdvleon
  • Registratie: Januari 2008
  • Laatst online: 08-06-2023
Ik ga ook informatica studeren :P Nog mooier, ik heb vandaag een dag mee gelopen op de Radboud Universiteit Nijmegen :P

Deze code die van mij is helemaal zelf verzonnen. Maar zoals je in de berichten hier boven kunt lezen is deze nog niet zo heel goed:P (dus deze 6vwo-er lukt het inderdaad nog niet om een baan brekende encryptie te verzinnen hoor :P maar het is gewoon leuk om te proberen en met jullie feedback leer ik er van, iedereen bedankt hiervoor :D).

Ik heb gewoon al heel veel tijd in programmeren gestoken en ook in de c++ syntaxs. Als je eenmaal kunt programmeren is de overstap van de ene taal (php) naar de andere (c++) niet zo heel moeilijk.

Acties:
  • 0 Henk 'm!

  • Orion84
  • Registratie: April 2002
  • Laatst online: 26-09 16:41

Orion84

Admin General Chat / Wonen & Mobiliteit

Fotogenie(k)?

Aangezien je maar één ronde uitvoert, en afgezien van de shuffle die de losse bytes onaangeroerd laat, enkel een XOR met de key uitvoert is je algoritme in elk geval niet bestand tegen chosen plaintext attacks, waarbij de attacker zelf bepaalde invoer kan opstellen en vervolgens de invoer van encryptie met de uitvoer kan vergelijken, aangezien er zodra er een vast patroon in de 0'en zit, er informatie over de sleutel lekt. Als de invoer echt volledig vrij gekozen kan worden is het simpelweg genoeg om een heel block aan 0'en te laten vercijferen, waarbij de uitvoer gelijk is aan de gebruikte key, als ik het algoritme goed begrijp?

Zoals al in de wiki staat klinkt dat een beetje als een onrealistisch scenario, maar daar staat ook al uitgelegd dat dat in de praktijk vaak totaal niet het geval is.

Sowieso is het enige wat een bekende plaintext en een bekende ciphertext van elkaar scheidt enkel een shuffle (op basis van die key_prefix) en vervolgens een XOR met de key. Geen idee hoe lang die key_prefix precies is (een getal kleiner dan 1048575 als ik het goed lees?), maar als die niet al te lang is kan je vrij eenvoudig een soort van known (dus niet chosen) plaintext attack uitvoeren.
Je stelt voor alle mogelijke key_prefixes de shuffle tabel op en voert voor al die opties de shuffle uit op het eerste blok van de plaintext. Vervolgens bereken je de XOR van die geshuffelde bloks en de cyphertext, waarmee je alle kandidaten voor de key verkrijgt. Als je dan alle mogelijke keys gaat vergelijken met de key_prefix die bij die optie gebruikt was, dan kan je denk ik daarmee achterhalen welke key_prefix en key degene zijn die daadwerkelijk gebruikt zijn.

Door alle rare rotaties en verschuivingen is het wat lastig om zonder er veel te veel tijd in te steken in te zien of dit wel of niet een goed algoritme is. En dat maakt het dus niet alleen een aanvaller lastig (die is vaak volhardend genoeg, als er eenmaal interessante informatie (==geld) te achterhalen is), maar het maakt het ook erg lastig om aan te tonen dat je algoritme bestand is tegen bepaalde bekende aanvals mechanismen.

offtopic:
Vandaag meegelopen in Nijmegen? Had ik je nog tegen kunnen komen :P * Orion84 had vandaag wat vakken in Nijmegen, in het kader van de Kerckhoffs Information Security Master

[ Voor 5% gewijzigd door Orion84 op 24-11-2008 23:07 ]

The problem with common sense is that it's not all that common. | LinkedIn | Flickr


Acties:
  • 0 Henk 'm!

  • vdvleon
  • Registratie: Januari 2008
  • Laatst online: 08-06-2023
Maar wat je dus weer niet weet is hoe groot de key is, en dus hoe groot de blocken zijn.

C++:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
void generate_table(int len, int pre=0){
    // Check
    if(!ok) return;
        
    // Vars
    int i, k, t;
        
    // Generate table
    table = new int[len];
    for(i=0; i<len; i++) table[i] = i;
        
    // Shuffle table
    for(i=0, k=len-1; i<len; i++){
        // Swap
        t = table[i];
        table[i] = table[k];
        table[k] = t;
        
        // New k
        k = ((k+1)*(i+1)+pre+key_prefix)%len;
    }
    
    // Set last_len
    last_len = len;
}


Het husselen van de tabel heeft 3 invloeden: de lengte van de key (die je niet weet), pre = ((key.key[0]&0x3C)>>2)+clen (uit encrypt functie, dus ook afhankelijk van de key) en dus key_prefix (die vanuit de ook vanuit key word berekent). Als jij denkt dat deze key_prefix te weinig mogelijkheden heeft en daardoor te makkelijk te kraken is kan ik wel een grotere mogelijkheid maken (dus gebruik maken van de maximale int waarde of gewoon meerdere key_prefixen gebruiken :P) maar is dit wel nodig omdat er dus nog 2 andere factoren zijn die mee spelen in het husselen van de tabel?

Acties:
  • 0 Henk 'm!

  • Orion84
  • Registratie: April 2002
  • Laatst online: 26-09 16:41

Orion84

Admin General Chat / Wonen & Mobiliteit

Fotogenie(k)?

Mja, key length (en block length) lijken me nou typisch dingen die in de praktijk gestandaardiseerd worden, dus dat vind ik niet zo'n bijster sterk argument aangezien dat dus (evt. met een hele kleine keuzeruimte) bekend is bij de aanvaller.

Die derde factor in het bepalen van die tabel had ik even over het hoofd gezien, (zoals ik al zei, het is niet de meest overzichtelijke specificatie van een crypto algoritme ooit, al was het alleen maar omdat we het moeten doen met C++ code, in plaats van een goed gestructureerde omschrijving.), maar bedenk maar eens hoeveel mogelijke tables er zijn, als je even meeneemt dat je de lengte van de key (en dus de blocks) weet (ik heb de ballen verstand van C++, dus ik zie even niet wat ((key.key[0]&0x3C)>>2)+clen precies inhoudt).

Ik heb iig nog steeds een sterk vermoeden dat dat aantal fors kleiner is dan het aantal mogelijke keys...

The problem with common sense is that it's not all that common. | LinkedIn | Flickr


Acties:
  • 0 Henk 'm!

  • vdvleon
  • Registratie: Januari 2008
  • Laatst online: 08-06-2023
Ik moet voor mijn profiel werkstuk toch nog mijn encryptie in normaal nederlands beschrijven, dus dat doe ik dan maar een deze dagen (denk morgen).

Nog eff over: ((key.key[0]&0x3C)>>2)+clen :P

Dat betekend : als key.key[0] (eerste byte van de key op dat moment) bijv 01101110 is word dat:

01101110 and 0x3C of wel 01101110 and 00111100 en dat word 00101100.
Dat shift je dan weer 2 plaatsen naar rechts, dus dat word 1011 => 11 (decimaal) + clen

Ik gebruik alleen de 4 middelste bits van de byte omdat inderdaad omdat bij ascii teksten de laatste 2 bits minder (en in iedergeval de laatste bit) bijna altijd 0 is. De eerste 2 bits gaan eraf omdat ik de code ook een beetje snel wil houden en getallen van 4 bits liggen in [0, 15] en de + clen is weer voor extra mogelijkheden. Maar wat ik me bedenk is dat clen vaak ook een groot getal is :P en dus je als nog veel loops moet doorlopen. Dus ik moet dat aanpassen in bijv. 1 (omdat ((key.key[0]&0x3C)>>2) ook 0 kan geven).

Acties:
  • 0 Henk 'm!

  • vdvleon
  • Registratie: Januari 2008
  • Laatst online: 08-06-2023
Orion84 schreef op maandag 24 november 2008 @ 23:04:
offtopic:
Vandaag meegelopen in Nijmegen? Had ik je nog tegen kunnen komen :P * Orion84 had vandaag wat vakken in Nijmegen, in het kader van de Kerckhoffs Information Security Master
Wat is de wereld toch klein (of nederland gewoon :P)

Acties:
  • 0 Henk 'm!

  • Orion84
  • Registratie: April 2002
  • Laatst online: 26-09 16:41

Orion84

Admin General Chat / Wonen & Mobiliteit

Fotogenie(k)?

vdvleon schreef op maandag 24 november 2008 @ 23:47:
Ik moet voor mijn profiel werkstuk toch nog mijn encryptie in normaal nederlands beschrijven, dus dat doe ik dan maar een deze dagen (denk morgen).

Nog eff over: ((key.key\[0]&0x3C)>>2)+clen :P

Dat betekend : als key.key\[0] (eerste byte van de key op dat moment) bijv 01101110 is word dat:

01101110 and 0x3C of wel 01101110 and 00111100 en dat word 00101100.
Dat shift je dan weer 2 plaatsen naar rechts, dus dat word 1011 => 11 (decimaal) + clen

Ik gebruik alleen de 4 middelste bits van de byte omdat inderdaad omdat bij ascii teksten de laatste 2 bits minder (en in iedergeval de laatste bit) bijna altijd 0 is. De eerste 2 bits gaan eraf omdat ik de code ook een beetje snel wil houden en getallen van 4 bits liggen in [0, 15] en de + clen is weer voor extra mogelijkheden. Maar wat ik me bedenk is dat clen vaak ook een groot getal is :P en dus je als nog veel loops moet doorlopen. Dus ik moet dat aanpassen in bijv. 1 (omdat ((key.key\[0]&0x3C)>>2) ook 0 kan geven).
Tsja, die 'pre' is dus maar 4 bits groot, voegt dus, zoals ik al dacht, niet bijster veel toe aan het aantal mogelijke tables en komt op mij over op nogal een rare hack oplossing om een of andere weakness waar iemand je op wees te proberen te verhelpen. Sowieso is het niet echt nuttig om dat soort tweaks toe te passen om zulke specifieke weaknesses te verhelpen, aangezien zo'n weakness op een veel structurelere fout wijst.

The problem with common sense is that it's not all that common. | LinkedIn | Flickr


Acties:
  • 0 Henk 'm!

  • vdvleon
  • Registratie: Januari 2008
  • Laatst online: 08-06-2023
Ik ben helemaal overnieuw begonnen. Ik hoop dat dit wat beter is (het is nog makkelijk uitbreidbaar mocht het te simpel zijn).

C++:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
// Type defines
typedef unsigned char vel_key[128]; // 1024 bits

// Shuffle tables
// ... 

// ucstr to key function
bool vel_makekey(vel_key &key, const ustring str){
    // Vars
    unsigned int i;
    
    // Wrong size? 
    if(str.length()!=128){
        for(i=0; i<128; i++) key[i] = (unsigned char)(i*9)%0x100;
        return false;
    }
    
    // Copy
    for(i=0; i<128; i++) key[i] = (unsigned char)str[i];
    
    // OK
    return true;
}

// Class vel_encryption
class vel_encryption{
    private:
        vel_key key;

    public:
        vel_encryption(vel_key _key){
            memcpy(key, _key, sizeof(vel_key));
        }
        
        ustring encrypt(const ustring input, bool debug){
            // Vars
            unsigned int i, j, blocks;
            unsigned short org_len = input.length();
            ustring str = input;
            vel_random random(time(NULL));
            unsigned char block[128], block_temp[128];

            // Fill input to n blocks of 128 bytes
            while((str.length()%128)>0) str += (unsigned char)(random.random()%0x100);
            str += (unsigned char)(128-(org_len%128));
            
            // Get block count
            blocks = (unsigned int)(str.length()/128);
            
            // For each block in str
            for(i=0; i<blocks; i++){
                // Get current block
                ucstr_to_ucp(block, str.substr(i*128), 128);
                
                // Shuffle block
                ucp_to_ucp(block_temp, block, 128);
                switch((i+1)%4){
                    case 0: for(j=0; j<128; j++){ block[j] = block_temp[vel_1024_table_a[j]]; } break;
                    case 1: for(j=0; j<128; j++){ block[j] = block_temp[vel_1024_table_b[j]]; } break;
                    case 2: for(j=0; j<128; j++){ block[j] = block_temp[vel_1024_table_c[j]]; } break;
                    case 3: for(j=0; j<128; j++){ block[j] = block_temp[vel_1024_table_d[j]]; } break;
                }
                    
                // XOR
                switch((i+2)%4){
                    case 0: for(j=0; j<128; j++){ block[j] ^= key[vel_1024_table_a[j]] ^ key[vel_1024_table_c[j]]; } break;
                    case 1: for(j=0; j<128; j++){ block[j] ^= key[vel_1024_table_b[j]] ^ key[vel_1024_table_a[j]]; } break;
                    case 2: for(j=0; j<128; j++){ block[j] ^= key[vel_1024_table_d[j]] ^ key[vel_1024_table_a[j]]; } break;
                    case 3: for(j=0; j<128; j++){ block[j] ^= key[vel_1024_table_d[j]] ^ key[vel_1024_table_b[j]]; } break;
                }
                
                // Update str
                for(j=0; j<128; j++) str[i*128+j] = block[j];
            }
            
            // Return string
            return str;
        }
        
        ustring decrypt(const ustring input, bool debug){
            // Vars
            unsigned int i, j, blocks;
            ustring str = input;
            unsigned char block[128], block_temp[128];

            // Test input, if not have n blocks of 128 bytes return error
            if((str.length()%128)!=1){
                // Error
                return to_ucstr("error");
            }
            
            // Get block count
            blocks = (unsigned int)(str.length()/128);
            
            // For each block in str
            for(i=0; i<blocks; i++){
                // Get current block
                ucstr_to_ucp(block, str.substr(i*128), 128);
                
                // XOR
                switch((i+2)%4){
                    case 0: for(j=0; j<128; j++){ block[j] ^= key[vel_1024_table_a[j]] ^ key[vel_1024_table_c[j]]; } break;
                    case 1: for(j=0; j<128; j++){ block[j] ^= key[vel_1024_table_b[j]] ^ key[vel_1024_table_a[j]]; } break;
                    case 2: for(j=0; j<128; j++){ block[j] ^= key[vel_1024_table_d[j]] ^ key[vel_1024_table_a[j]]; } break;
                    case 3: for(j=0; j<128; j++){ block[j] ^= key[vel_1024_table_d[j]] ^ key[vel_1024_table_b[j]]; } break;
                }
                
                // Shuffle block
                ucp_to_ucp(block_temp, block, 128);
                switch((i+1)%4){
                    case 0: for(j=0; j<128; j++){ block[j] = block_temp[vel_1024_table_a_inverse[j]]; } break;
                    case 1: for(j=0; j<128; j++){ block[j] = block_temp[vel_1024_table_b_inverse[j]]; } break;
                    case 2: for(j=0; j<128; j++){ block[j] = block_temp[vel_1024_table_c_inverse[j]]; } break;
                    case 3: for(j=0; j<128; j++){ block[j] = block_temp[vel_1024_table_d_inverse[j]]; } break;
                }
                
                // Update str
                for(j=0; j<128; j++) str[i*128+j] = block[j];
            }
            
            // Remove extra bytes
            unsigned char extra_len = *(str.end()-1);
            str = str.substr(0, str.length()-extra_len-1);
            
            // Return string
            return str;
        }
};


De hele code is hier te vinden.

Ik maak nu wel gebruik van een vaste key (1024 bits = 128 bytes = 2^1024 mogelijkheden (een getal van 310 letters)). Ook maak ik nu geen table meerr aan de hand van de key, maar maak ik gewoon gebruik van vaste tables.

Met termen als ucstr en ustring bedoel ik unsigned chars strings. Misschien eff handig om te weten.
In de class vel_random (random.h) maak ik nu nog gebruik van de standaart C++ srand() en rand(). Dit was even nodig om hem te testen. Eigenlijk moet ik nog een goede random number generator zoeken.

Is dit een verbetering op de vorige versie?

[edit]
De Shuffle tables staan niet in de code omdat het bericht dan te groot word. Je kan de hele code dus hier zien.

[ Voor 4% gewijzigd door vdvleon op 27-11-2008 08:26 ]


  • Orion84
  • Registratie: April 2002
  • Laatst online: 26-09 16:41

Orion84

Admin General Chat / Wonen & Mobiliteit

Fotogenie(k)?

Maak a.u.b. eens gewoon een fatsoenlijke gestructureerde omschrijving van je algoritme, want al die C++ code is leuk en aardig, maar ik vind dat verre van overzichtelijk om fatsoenlijk te analyseren. Op deze manier kost het me te veel tijd en haak ik af en dat is jammer, aangezien ik toch wel erg benieuwd ben naar wat je veranderd hebt en hoe het nu in elkaar steekt en het voor jou ook leerzaam is om zo veel mogelijk respons te krijgen lijkt me?

Na me toch maar even door de brij aan .cpp en .h files heengewerkt te hebben begrijp ik, als ik me niet vergis dat de enige daadwerkelijke encryptie actie plaatsvindt in het volgende stukje code:

C++:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
// Shuffle block
ucp_to_ucp(block_temp, block, 128);
switch((i+1)%4){
case 0: for(j=0; j<128; j++){ block[j] = block_temp[vel_1024_table_a[j]]; } break;
case 1: for(j=0; j<128; j++){ block[j] = block_temp[vel_1024_table_b[j]]; } break;
case 2: for(j=0; j<128; j++){ block[j] = block_temp[vel_1024_table_c[j]]; } break;
case 3: for(j=0; j<128; j++){ block[j] = block_temp[vel_1024_table_d[j]]; } break;
}

// XOR
switch((i+2)%4){
case 0: for(j=0; j<128; j++){ block[j] ^= key[vel_1024_table_a[j]] ^ key[vel_1024_table_c[j]]; } break;
case 1: for(j=0; j<128; j++){ block[j] ^= key[vel_1024_table_b[j]] ^ key[vel_1024_table_a[j]]; } break;
case 2: for(j=0; j<128; j++){ block[j] ^= key[vel_1024_table_d[j]] ^ key[vel_1024_table_a[j]]; } break;
case 3: for(j=0; j<128; j++){ block[j] ^= key[vel_1024_table_d[j]] ^ key[vel_1024_table_b[j]]; } break;
}


Goed, dat is nog wel beknopt genoeg om even kort te analyseren :P

De shuffle actie die plaatsvindt is een bekende functie, dus die kan eenieder uitvoeren, waardoor het geen extra weerstand biedt tegen een known plaintext attack.

Daarna wordt elke byte ge-XOR-ed met de XOR van twee bytes uit de (op vaste manier geshufflede) key. Indien plaintext en cyphertext bekend zijn (known plaintext attack) is de uitkomst van die XOR van de twee key bytes te achterhalen door simpelweg de XOR van de plaintext en cyphertext te bepalen.
Daarmee heb je vervolgens alle informatie die je nodig hebt om als attacker zelf nieuwe berichten te encrypten of andere onderschepte berichten waarvan de plaintext niet bekend is te decrypten. Kortom, wat betreft de known plaintext attack is je algoritme er alleen maar zwakker op geworden.

De chosen plaintext attack is natuurlijk ook nog onverminderd van toepassing.

[ Voor 68% gewijzigd door Orion84 op 27-11-2008 11:05 ]

The problem with common sense is that it's not all that common. | LinkedIn | Flickr


  • vdvleon
  • Registratie: Januari 2008
  • Laatst online: 08-06-2023
Dus als ik bijv dit er van zou maken?

C++:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
// XOR 
switch((i+2)%4){ 
case 0: for(j=0; j<128; j++){ block[j] ^= key[vel_1024_table_a[(j+key[j])%128]] ^ key[vel_1024_table_c[(j+1+key[j])%128]]; } break; 
case 1: for(j=0; j<128; j++){ block[j] ^= key[vel_1024_table_b[(j+key[j])%128]] ^ key[vel_1024_table_a[(j+2+key[j])%128]]; } break; 
case 2: for(j=0; j<128; j++){ block[j] ^= key[vel_1024_table_d[(j+key[j])%128]] ^ key[vel_1024_table_a[(j+3+key[j])%128]]; } break; 
case 3: for(j=0; j<128; j++){ block[j] ^= key[vel_1024_table_d[(j+key[j])%128]] ^ key[vel_1024_table_b[(j+4+key[j])%128]]; } break; 
 } 
                 
// Shuffle block 
ucp_to_ucp(block_temp, block, 128); 
switch((i+1)%4){ 
case 0: for(j=0; j<128; j++){ block[j] = block_temp[vel_1024_table_a_inverse[(j+1+key[j])%128]]; } break; 
case 1: for(j=0; j<128; j++){ block[j] = block_temp[vel_1024_table_b_inverse[(j+2+key[j])%128]]; } break; 
case 2: for(j=0; j<128; j++){ block[j] = block_temp[vel_1024_table_c_inverse[(j+3+key[j])%128]]; } break; 
case 3: for(j=0; j<128; j++){ block[j] = block_temp[vel_1024_table_d_inverse[(j+4+key[j])%128]]; } break; 
} 


Zou het dan wat bestander worden tegen know plain text attack ?

  • Orion84
  • Registratie: April 2002
  • Laatst online: 26-09 16:41

Orion84

Admin General Chat / Wonen & Mobiliteit

Fotogenie(k)?

Het aanpassen van het XOR gedeelte voegt wat dit betreft niet veel toe. Om als attacker een volgende cyphertext te decrypten hoef je de daadwerkelijke key niet te weten, je moet alleen het resultaat weten van:
C++:
1
key[vel_1024_table_d[(j+key[j])%128]] ^ key[vel_1024_table_a[(j+3+key[j])%128]]

In feite is de uitkomst van die expressie je encryptie/decryptie key.

Door de shuffle afhankelijk te maken wordt het wel lastiger, aangezien een attacker dan niet meer de invoer en uitvoer van de XOR kan bepalen om de gebruikte key kan achterhalen. In je eerste poging bleek echter dat het aantal mogelijke shuffles, ook al hing dat van de key af, een stuk kleiner was dan het aantal mogelijke sleutels, waardoor het algoritme al met al nog niet erg sterk was.

Voor zover ik zo snel kan zien heb je dat nu een stuk beter opgelost. De index voor de shuffle wordt bepaald door (j+x+key[j])%128, waarvan j en x bekend zijn maar key[j] 256 verschillende waardes aan kan nemen. Daardoor zijn er 128 mogelijkheden voor (j+x+key[j])%128, waardoor het aantal mogelijke manieren waarop een block geshuffled kan worden, zo uit m'n hoofd, op 128128 = 2896 uitkomt, wat me niet echt haalbaar lijkt om uit te gaan proberen.
Nog afgezien van de vraag of het wel te controleren is welke van die 2896 uiteindelijk de juiste was, maar dat is denk ik wel te doen, door de gekozen shuffle index te gaan vergelijken met de bytes die uit de XOR van plaintext en (inversed ge-shufflede) cyphertext rollen.

Kortom, het lijkt zo op het eerste gezicht op deze manier al een stuk beter dan de oplossing die je eerder aandroeg en in elk geval beter dan de oplossing zoals je die gisteravond postte. Maargoed, dat wil niet zeggen dat er met ingewikkeldere aanvalsmethodes niet alsnog zwakheden te benutten zijn, maar daar heb ik niet genoeg verstand van om er iets zinnigs over te zeggen.

Wat is trouwens de gedachtengang achter het omwisselen van de shuffle en de XOR?

[ Voor 7% gewijzigd door Orion84 op 27-11-2008 12:01 ]

The problem with common sense is that it's not all that common. | LinkedIn | Flickr


  • Hydra
  • Registratie: September 2000
  • Laatst online: 21-08 17:09
vdvleon schreef op maandag 24 november 2008 @ 20:56:
Voor de mensen die wel zin hebben om mijn encrypte te 'kraken'.
Dat gaat niet gebeuren vrees ik. Een extreem simpele roterende XOR encryptie tussen een plaintext van een bekende lengte en een key van een bekende lengte is cryptografisch hardstikke zwak, maar het is gewoon te veel werk om dat hier te gaan bewijzen. Met het handje uitzoeken wat de key is haal je met een simpele substitution cipher (Caesar cipher bijvoorbeeld, wie kent 'em niet :)) nog, maar daarbuiten ga je toch frequentie analyses e.d. nodig hebben.

Als je nu uiteen zet wat je denkpatronen zijn (ook erg belangrijk dat je functioneel kunt beschrijven wat je doet als je informatica wilt gaan doen ;)) kunnen mensen daar gaten in schieten.

https://niels.nu


  • vdvleon
  • Registratie: Januari 2008
  • Laatst online: 08-06-2023
Ik heb dit keer mijn programmeer werk in ieder geval sterk verbeterd. Het encrypten en decrypten gaat nu veel sneller (omdat hij nu alleen het block in het geheugen laat en niet het hele bestand). Ook is het beter te overzien.

C++:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
// Blocks
void encrypt_block(vel_block &block){
    // Vars
    vel_block block_temp;
    unsigned int i, j;
    unsigned char t;

    // Shuffle block
    for(j=0; j<128; j++){
        t = block[j];
        block[j] = block[vel_table[(j+key[j])%128]];
        block[vel_table[(j+key[j])%128]] = t;
    }
        
    // XOR
    for(j=0; j<128; j++){
        block[j] ^= key[j] ^ key[(j+1)%128];
    }
    
    // Vigenere
    ucp_to_ucp(block_temp, block, 128);
    for(j=0; j<128; j++){
        block[j] = vigenere_table[key[j]][block_temp[j]];
    }
}
void decrypt_block(vel_block &block){
    // Vars
    vel_block block_temp;
    unsigned int j;
    unsigned char t;
    
    // Vigenere
    ucp_to_ucp(block_temp, block, 128);
    for(j=0; j<128; j++){
        block[j] = vigenere_table_inverse[block_temp[j]][key[j]];
    }
    
    // XOR
    for(j=0; j<128; j++){
        block[j] ^= key[j] ^ key[(j+1)%128];
    }
    
    // Shuffle block
    for(j=128; j>0; j--){
        t = block[j-1];
        block[j-1] = block[vel_table[(j-1+key[j-1])%128]];
        block[vel_table[(j-1+key[j-1])%128]] = t;
    }
}


Het hele bestand staat nog steeds hier.

Ik bedenk me net iets. Kan je d.m.v. het onderstaande achter (relatief) snel achter de key komen?
C++:
1
2
3
4
// XOR
for(j=0; j<128; j++){
    block[j] ^= key[j] ^ key[(j+1)%128];
}


Wat nou als ik het volgende doe, zou dit optimaal veilig zijn? (voor een xor)
C++:
1
2
3
4
5
6
// XOR
for(j=0; j<128; j++){
    for(k=0; k<128; k++){
        block[j] ^= key[k];
    }
}

[ Voor 12% gewijzigd door vdvleon op 28-11-2008 00:10 ]


Acties:
  • 0 Henk 'm!

  • Orion84
  • Registratie: April 2002
  • Laatst online: 26-09 16:41

Orion84

Admin General Chat / Wonen & Mobiliteit

Fotogenie(k)?

Oftewel voor elke j:
(...((((block[j] XOR key[0]) XOR key[1]) XOR key[2]) XOR key[3])...XOR key[127] ) == block[j] XOR (key[0] XOR key[1] XOR key[2] XOR...XOR key[127] )

Dat komt er uiteindelijk op neer dat je elk byte uit de (geshufflede) plaintext XOR'ed met een XOR over alle bytes in de key. Die XOR over alle keybytes geeft steeds hetzelfde resultaat, oftewel, elke byte in de plaintext wordt vercijferd met een en dezelfde byte. Kortom je verkleint je keyspace (afgezien van wat je met de shuffle doet) tot welgeteld één hele byte ;)

Heb je überhaupt door hoe de XOR werkt en denk je met die kennis in het achterhoofd ook maar een klein beetje na voordat je je volgende hersenspinsel hier post :?

Je hebt nu binnen een paar dagen al allerlei rare proefballonnetjes losgelaten, waarvan de een nog minder hout snijdt dan de andere. Het lijkt me handiger om er eerst eens goed over na te denken of op z'n minst hier toe te lichten waarom je voor bepaalde constructies kiest, zodat we zoals iemand hierboven ook al aangaf kunnen aangeven waar je denkwerk de fout in gaat, dat is een stuk leerzamer denk ik zo. Kortom, probeer je keuzes eens te verantwoorden, niet alleen voor ons, maar ook voor jezelf, voor je ze hier post :)

[ Voor 60% gewijzigd door Orion84 op 28-11-2008 10:57 ]

The problem with common sense is that it's not all that common. | LinkedIn | Flickr


Acties:
  • 0 Henk 'm!

  • pedorus
  • Registratie: Januari 2008
  • Niet online
Wat denk ik wel een goede testmethode is, is om alleen maar 0-bytes te encoderen. Als je echt een goede encryptie hebt, dan is de output daarvan een reeks secure random bytes.

Als je bijvoorbeeld dit algoritme zou testen op die manier, dan is het eerste block van 128 steeds dezelfde byte, niet bepaald random dus. :) (En misschien alle volgende bytes ook, ik weet niet of je de key nog aanpast tussendoor.)

Verder: Is eerst shufflen en dan XOR-en een goed idee, of kan dat beter andersom? Zijn blocks een goed idee als je gaat shufflen, of zou je misschien alles als een block willen zien? Ik kan me ook nauwelijks voorstellen dat een bestand in delen inlezen veel sneller is, of je moet echt een groot bestand hebben. :)

Vitamine D tekorten in Nederland | Dodelijk coronaforum gesloten


Acties:
  • 0 Henk 'm!

  • Zoijar
  • Registratie: September 2001
  • Niet online

Zoijar

Because he doesn't row...

vdvleon schreef op donderdag 27 november 2008 @ 22:56:
Ik bedenk me net iets. Kan je d.m.v. het onderstaande achter (relatief) snel achter de key komen?
C++:
1
2
3
4
// XOR
for(j=0; j<128; j++){
    block[j] ^= key[j] ^ key[(j+1)%128];
}


Wat nou als ik het volgende doe, zou dit optimaal veilig zijn? (voor een xor)
C++:
1
2
3
4
5
6
// XOR
for(j=0; j<128; j++){
    for(k=0; k<128; k++){
        block[j] ^= key[k];
    }
}
Je doet nog steeds veel dingen "omdat het ingewikkeld lijkt". Dat heet "security through obscurity": iets dat het moeilijker leesbaar maakt en lastiger om even snel te achterhalen maar niet daadwerkelijk iets toevoegt aan de kracht van je algoritme -- het verzwakt vaak zelfs je algoritme, en het maakt het moeilijker om te kijken of het correct is. Simpel is beter.

Twee XORs is niet veiliger dan eentje. Een XOR is gewoon een substitutie. Het is ook niet veiliger als ik eerst in een tekst alle A's vervang door E's en dan alle E's door B's; dan kan ik net zo goed alle A's door B's vervangen. Het gevaar is dat ik eerst van A naar E ga, dan van E naar B, en dan per ongeluk van B naar A, en weg is je security. Wat is dit bv key[j] ^ key[(j+1)%128]; waarom niet gewoon key[j]?

Begin gewoon simpel en voeg dan dingen toe om specifieke aanvallen tegen te gaan.

for (i in plaintext) plaintext[i] ^= key[i % keylength]

Dat is je basis. Wat is hier mis mee? Wat wil je verbeteren? Waarom? Hoe krijg je dat zo simpel mogelijk voor elkaar? Wat zijn de consequenties?

(hier: Wikipedia: Stream cipher attack bijvoorbeeld twee attacks op deze cypher)

Wat ik denk dat je wilt is dat er geen bekende 1-1 correspondentie is tussen input bytes en output bytes. Oplossing is dan om op basis van je key de output plek te bepalen. Daar kan je je oorspronkelijke schuffle voor gebruiken denk ik.

Dus:

for (i in plaintext) plaintext[i] ^= key[i % keylength];
permute(plaintext, seed=key); // een random permutatie/shuffle met je key als seed

[ Voor 13% gewijzigd door Zoijar op 28-11-2008 12:36 ]


Acties:
  • 0 Henk 'm!

  • .oisyn
  • Registratie: September 2000
  • Laatst online: 02:49

.oisyn

Moderator Devschuur®

Demotivational Speaker

for (i in plaintext) plaintext[i] ^= key[i] % keylength
Moet die % keylength niet tussen de blokhaken, zodat je de modulo op de i uitvoert ipv op key[i]?

Give a man a game and he'll have fun for a day. Teach a man to make games and he'll never have fun again.


Acties:
  • 0 Henk 'm!

  • Zoijar
  • Registratie: September 2001
  • Niet online

Zoijar

Because he doesn't row...

.oisyn schreef op vrijdag 28 november 2008 @ 12:31:
[...]

Moet die % keylength niet tussen de blokhaken, zodat je de modulo op de i uitvoert ipv op key[i]?
|:( Ja...

Acties:
  • 0 Henk 'm!

  • Orion84
  • Registratie: April 2002
  • Laatst online: 26-09 16:41

Orion84

Admin General Chat / Wonen & Mobiliteit

Fotogenie(k)?

* Orion84 sluit zich aan bij Zoijar :)

The problem with common sense is that it's not all that common. | LinkedIn | Flickr


Acties:
  • 0 Henk 'm!

  • vdvleon
  • Registratie: Januari 2008
  • Laatst online: 08-06-2023
Dan heb ik nu dit:
C++:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
// XOR
for(j=0; j<128; j++){
    block[j] ^= key[j];
}
            
// Shuffle block
for(j=0; j<128; j++){
    t = block[j];
    block[j] = block[vel_table[(j+key[j])%128]];
    block[vel_table[(j+key[j])%128]] = t;
}
            
// Vigenere
ucp_to_ucp(block_temp, block, 128);
    for(j=0; j<128; j++){
    block[j] = vigenere_table[key[j]][block_temp[j]];
}


Heeft het vigenere princiepe in de huidige tijd nog wel een echte toevoeging? Volgens mij wel, omdat dat je voor elke byte 256 verschillende mogelijkheden krijgt (als je table[256][256] is).

[edit]
Ik werk met blokken omdat ik mijn encryptie voor elke grote van de input fatsoenlijk wil laten werken. Het is toch geen 'zwakte' dat het blok uit 128 bytes bestaat? Er zijn aardig wat mogelijkheden om zo'n block te 'shufflen' dacht ik zo.

[edit2]
Ik merk nu wat gebreken. Als de key uit 128 * 0 bestaat en de input (het block) ook uit 128*0 dan word het ook 128*0 Hoe zou ik dit kunnen oplossen?

[ Voor 24% gewijzigd door vdvleon op 28-11-2008 13:05 ]


Acties:
  • 0 Henk 'm!

  • Zoijar
  • Registratie: September 2001
  • Niet online

Zoijar

Because he doesn't row...

vdvleon schreef op vrijdag 28 november 2008 @ 12:57:
Heeft het vigenere princiepe in de huidige tijd nog wel een echte toevoeging?
Weet je wat ook een goede toevoeging is? Na al je XOR-en er een RSA encryptie stap overheen gooien ;)
Pagina: 1