File Coverage

blib/lib/Crypt/PBC/WIBE.pm
Criterion Covered Total %
statement 10 12 83.3
branch n/a
condition n/a
subroutine 4 4 100.0
pod n/a
total 14 16 87.5


line stmt bran cond sub pod time code
1             package Crypt::PBC::WIBE;
2             # ABSTRACT: Crypt::PBC::WIBE - Wildcarded Identity-based Encryption Scheme
3              
4 1     1   19757 use strict;
  1         2  
  1         34  
5 1     1   5 use warnings;
  1         2  
  1         24  
6 1     1   4 use Carp;
  1         5  
  1         79  
7 1     1   319 use Crypt::PBC;
  0            
  0            
8              
9             use constant DEFAULT_PAIRING_A => <
10             type a
11             q 8780710799663312522437781984754049815806883199414208211028653399266475630880222957078625179422662221423155858769582317459277713367317481324925129998224791
12             h 12016012264891146079388821366740534204802954401251311822919615131047207289359704531102844802183906537786776
13             r 730750818665451621361119245571504901405976559617
14             exp2 159
15             exp1 107
16             sign1 1
17             sign0 1
18             EOF
19              
20             =pod
21              
22             =encoding utf8
23              
24             =head1 NAME
25              
26             Crypt::PBC::WIBE - Implementation of the Boneh-Gentry-Goh Wildcarded Identity-based Encryption scheme.
27              
28             =head1 SYNOPSIS
29              
30             use Crypt::PBC::WIBE;
31              
32             # Create a new instance, generate public, master secret key
33             my $wibe = new Crypt::PBC::WIBE( L => 2 );
34              
35             # Derive Key for Alice, Bob
36             my $alice = $wibe->derive(1);
37             my $bob = $wibe->derive(2);
38              
39             # Derive Subkey (notice: same ID!) for friend of alice
40             my $carol = $alice->derive(1);
41              
42             # Recap: Alice now has the ID vector [1]
43             # and carol (friend of alice) has [1,1]
44              
45             # Pattern: Allow all friends (*)
46             my $pattern = ['*'];
47              
48             # Create a random element from Crypt::PBC
49             my $msg = $wibe->pairing->init_GT->random;
50              
51             my $cipher = $wibe->encrypt_element($pattern, $msg);
52              
53             die "Alice should be able to decrypt"
54             unless $alice->decrypt_element($cipher)->is_eq($msg);
55              
56             die "Carol must be unable to decrypt"
57             if $carol->decrypt_element($cipher)->is_eq($msg);
58              
59              
60             =head1 OVERVIEW
61              
62             This module provides an implementation to the Boneh–Boyen–Goh Wildcarded Identity-Based Encryption scheme
63             as proposed by Abdalla et al., as appeared in I.
64              
65             This implementation relies on the PBC library and thus, its Perl bindings L.
66              
67             =head1 DISCLAIMER
68              
69             This module is part of a prototype implementation of the Boneh-Gentry-Goh WIBE.
70             While it works fine in my tests, I advise against using it for anything productive other than experimental work.
71              
72             I appreciate your input on anything you might encounter while using this module.
73              
74             =head1 METHODS
75              
76             The exposed methods described below follow the four algorithms from the paper closely.
77              
78             =head2 new
79              
80             Returns a WIBE instance. C expects a parameter hash with at least the
81             following pair set:
82              
83             =over 4
84              
85             =item L
86              
87             Pattern length / Maximum hierarchy of the encryption scheme.
88              
89             =back
90              
91             and the following optional keys:
92              
93             =over 4
94              
95             =item pairing
96              
97             A Type-A pairing. Passed directly to L.
98             May be a pairing string, filehandle or filename.
99              
100             =item SK, MPK
101              
102             Secret and Public Key of the system. If not set, they
103             are generated through C.
104              
105             =back
106              
107             =cut
108             sub new {
109             my $class = shift;
110             my %options = @_;
111              
112             croak("Missing parameter 'L' from parameters.")
113             unless defined $options{L};
114              
115             croak("Invalid parameter 'L', must be an integer > 0.")
116             unless ($options{L} > 0);
117              
118             my $self = bless {
119             L => $options{L},
120             pairing => new Crypt::PBC($options{pairing} || DEFAULT_PAIRING_A),
121             }, $class;
122              
123             # Use existing keys if set.
124             $self->{$_} = $options{$_} for (qw(SK MPK DSK));
125              
126             # If MPK is missing, we assume a new instance, generate keys.
127             unless (defined $self->{MPK}) {
128             $self->setup;
129             }
130              
131             # Generate my own decryption key for patterns l+1
132             # By convention, we use ID=0 as the identifier for 'self'.
133             #
134             # I.e., Alice with ID=1 derives a key for [1,0],
135             # so that she may decrypt a pattern of length 2.
136             $self->{SK} = $self->key_derive(0)
137             unless (defined $self->{SK});
138              
139             return $self;
140             }
141              
142             =head2 pairing
143              
144             Returns the Type-A pairing used in this WIBE instance.
145              
146             See L.
147              
148             =cut
149             sub pairing {
150             return shift->{pairing};
151             }
152              
153             =head2 setup
154              
155             Generates the I (public key) and I (master secret key)
156             of the WIBE system and stores them in the WIBE instance.
157              
158             =cut
159             sub setup {
160             my ($self) = @_;
161              
162             # mpk = (g_1, g_2, h_1, u_0, .. , u_L)
163             my ($mpk, $msk);
164              
165             # Choose random g_1, g_2 from G
166             $mpk->{g1} = $self->{pairing}->init_G1->random;
167             $mpk->{g2} = $self->{pairing}->init_G1->random;
168            
169             # Choose random alpha from Zp
170             my $alpha = $self->{pairing}->init_Zr->random;
171            
172             # Compute h_1 as g_1^(alpha)
173             $mpk->{h1} = $self->{pairing}->init_G1->pow_zn($mpk->{g1}, $alpha);
174            
175             # Choose random u_i for i = 0, .. , L
176             for(my $i = 0; $i <= $self->{L}; $i++) {
177             $mpk->{u}->[$i] = $self->{pairing}->init_G1->random;
178             }
179              
180             # Initialize msk
181             # msk = (d_0, d_1, ..., d_L, d_L+1)
182              
183             # Set d_0 to g_2 ^ alpha
184             $msk->{key}->[0] = $self->{pairing}->init_G1;
185             $msk->{key}->[0]->pow_zn($mpk->{g2}, $alpha);
186              
187             # Initialize all elements of msk as 1 in G
188             for(my $i = 1; $i < $self->{L} + 2; $i++) {
189             $msk->{key}->[$i] = $self->{pairing}->init_G1->set1;
190             }
191            
192              
193             # ID ids is empty, as this is the master
194             $msk->{ids} = [];
195              
196             $self->{DSK} = $msk;
197             $self->{MPK} = $mpk;
198              
199             }
200              
201             =head2 derive
202              
203             Returns a WIBE instance for a derived ID element.
204              
205             Required Parameters:
206              
207             =over 4
208              
209             =item next_id
210              
211             Next Identifier element in the hierarchy.
212              
213             =back
214              
215             This serves as a shortcut for the following steps:
216              
217             =over 4
218              
219             =item 1.
220              
221             Create a derived key C<key_derive(next_id)>>.
222              
223             =item 2.
224              
225             Create a new WIBE instance with the same public key and the derived secret key C
226              
227             =item 3.
228              
229             Returns that instance.
230              
231             =back
232              
233             =cut
234             sub derive {
235             my ($self, $next_id) = @_;
236              
237             # Derive the new key
238             my $derived_key = $self->key_derive($next_id);
239              
240             # Pass that key, along with MPK, to a new instance
241             my $options = { map { $_ => $self->{$_} } (qw(L MPK)) };
242              
243             # If the instance ID vector is = L, it is a leaf,
244             # thus it may no longer derive keys.
245             # We denote that key as SK.
246              
247             if ($self->{L} == scalar(@{$derived_key->{ids}})) {
248             $options->{SK} = $derived_key;
249             } else {
250             # Otherwise, the key is derivable (denoted as DSK).
251             $options->{DSK} = $derived_key;
252             }
253              
254             return Crypt::PBC::WIBE->new(%$options);
255             }
256              
257             =head2 key_derive
258              
259             Derive a key for the given ID element
260             using the derivable secret key I<(DSK)> of this instance.
261              
262             Parameters:
263              
264             =over 4
265              
266             =item id
267              
268             Next Identifier element in the hierarchy.
269              
270             =back
271              
272             Returns the derived key of size (sk - 1),
273             which is a simple hash with the following keys:
274              
275             =over 4
276              
277             =item key
278              
279             The element_t secret key for the derived ID.
280              
281             =item ids
282              
283             Hierarchy of the secret key.
284              
285             =back
286              
287             B
288              
289             =over 4
290              
291             =item *
292              
293             Alice derives an identity 1 (Zp) for Bob
294             using the Master Key. (size |L| + 2)
295              
296             =item *
297              
298             Bob receives a secret key of size |L| + 1
299             and its identity.
300              
301             =item *
302             Bob derives an identity 0 (Zp) for Bob
303             (i.e., the self key).
304              
305             Bob can decrypt for Pattern [1,*] or [1,0].
306              
307             =back
308              
309             =cut
310             sub key_derive {
311             my ($self, $ID) = @_;
312              
313             # Use the DSK unless key is set
314             croak("Cannot derive key without DSK.")
315             unless defined $self->{DSK};
316              
317             croak("ID must be an integer >= 0")
318             unless ($ID =~ qr/^\d+$/ && $ID >= 0);
319              
320             # Load next ID element in Zp
321             my $ID_el = $self->{pairing}->init_Zr->set_to_int($ID);
322              
323             # l = Current ID vector length
324             my $l = scalar(@{ $self->{DSK}->{ids} });
325             # Length of DSK
326             my $keylen = scalar(@{ $self->{DSK}->{key} });
327             # Length of derived key = l - 1
328             my $derived_keylen = $keylen - 1;
329              
330             # secret key = (d_0, d_l+1, ..., d_L, d_L+1)
331             # new key = (d_0', d_l+2', ..., d_L, d_L+1)
332             my $derived;
333            
334             # Initialize all elements of the derived key in G
335             for(my $i = 0; $i < $derived_keylen; $i++) {
336             $derived->[$i] = $self->{pairing}->init_G1;
337             }
338              
339             # Compute IDs
340             my $derived_ids = [ @{$self->{DSK}->{ids}}, $ID];
341              
342             # Initialize r as random from Zp
343             my $r = $self->{pairing}->init_Zr->random;
344             my $temp = $self->{pairing}->init_G1;
345              
346             # Compute d_0'
347             $derived->[0]->set($self->{MPK}->{u}->[0]);
348             my $id_i = $self->{pairing}->init_Zr;
349            
350             for(my $i = 0; $i < $l + 1; $i++) {
351             $id_i->set_to_int($derived_ids->[$i]);
352             # multiply with u_i ^ ID_i-1
353             $temp->pow_zn($self->{MPK}->{u}->[$i+1], $id_i);
354             $derived->[0]->mul($temp);
355             }
356            
357             # Lastly pow with r
358             $derived->[0]->pow_zn($r);
359              
360             # compute d_l+1 ^ ID_l+1
361             $temp->set($self->{DSK}->{key}->[1]);
362             $temp->pow_zn($ID_el);
363            
364             # Multiply with temp
365             $derived->[0]->mul($temp);
366            
367             # Multiply with d_0
368             $derived->[0]->mul($self->{DSK}->{key}->[0]);
369            
370             # Compute d_i' for i=1,..,len-2 of derived key
371             for (my $i = 2; $i < $keylen - 1; $i++) {
372              
373             # Set d_i' to d_(i) * u_(l+i) ^ r
374             # multiply with u_(l+i)
375             $derived->[$i - 1]->pow_zn($self->{MPK}->{u}->[$l + $i], $r);
376             $derived->[$i - 1]->mul($self->{DSK}->{key}->[$i]);
377             }
378            
379             # Finally, compute d_L+1' as (g_1 ^ r) * d_L+1
380             $derived->[$derived_keylen - 1]->pow_zn($self->{MPK}->{g1}, $r);
381             $derived->[$derived_keylen - 1]->mul($self->{DSK}->{key}->[$keylen - 1]);
382              
383             return {
384             ids => $derived_ids,
385             key => $derived
386             };
387             }
388              
389             =head2 encrypt_element
390              
391             Perform an encryption for an element in G1 using the WIBE scheme.
392              
393             This key may later be expanded using HKDF and used in a symmetric AE scheme
394             as a hybrid encryption scheme.
395              
396             Parameters:
397              
398             =over 4
399              
400             =item Pattern
401              
402             An arrayref of size L with one of:
403             1.) C<'*'>, wildcard. Can be derived by any containing the parent pattern
404             2.) An Identifier (int >= 0). Derived only by the owner of that identifier.
405              
406             B: For L=2, possible patterns are:
407              
408             =over 4
409              
410             =item *
411              
412             C<['*','*']>: Decrypt possible with patterns matching C<'X.*'> or C<'X.Y'> for any C.
413              
414             =item *
415              
416             C<['X','*']>: Decrypt possible for X and any subkeys of id C.
417              
418             =item *
419              
420             C<['X', 0 ]>: Decrypt possible for subkey 0 of C, which by convention is C.
421              
422             =back
423              
424             =item m
425              
426             An element of G1 to encrypt.
427              
428             =back
429              
430             The resulting ciphertext of the encryption is a hashref.
431              
432             =cut
433             sub encrypt_element {
434             my ($self, $pattern, $m) = @_;
435              
436             croak("Pattern must be of length <= " . $self->{L})
437             unless (scalar(@$pattern) <= $self->{L});
438              
439             for my $id (@$pattern) {
440             croak("Pattern must only either an * or an integer >= 0")
441             unless ($id eq '*' || $id >= 0);
442             }
443              
444             croak("Cannot encrypt without a public key.")
445             unless defined $self->{MPK};
446              
447             # cipher = (P, C1, C2, C3, C4)
448             my $cipher;
449              
450             $cipher->{P} = $pattern;
451            
452             my $r = $self->{pairing}->init_Zr->random;
453            
454             # Initialize C1 as g_1 ^ r
455             $cipher->{C1} = $self->{pairing}->init_G1;
456             $cipher->{C1}->pow_zn($self->{MPK}->{g1}, $r);
457              
458             # Compute C2 and C4
459             $cipher->{C2} = $self->{pairing}->init_G1;
460             $cipher->{C2}->set($self->{MPK}->{u}->[0]);
461             # C4 denotes a vector of length |pattern|
462            
463             my $temp = $self->{pairing}->init_G1;
464             my $p_i = $self->{pairing}->init_Zr;
465             for (my $i = 0; $i < scalar(@$pattern); $i++) {
466             if ($pattern->[$i] eq '*') {
467             # Set C4[i] to u_i ^ r
468             $cipher->{C4}->[$i] = $self->{pairing}->init_G1;
469             $cipher->{C4}->[$i]->pow_zn($self->{MPK}->{u}->[$i+1], $r);
470             } else {
471             # that is not a wildcard
472             $p_i->set_to_int($pattern->[$i]);
473             $temp->pow_zn($self->{MPK}->{u}->[$i+1], $p_i);
474             $cipher->{C2}->mul($temp);
475             }
476             }
477            
478             # Finalize C2 as C2 ^ r
479             $cipher->{C2}->pow_zn($r);
480            
481             # Compute C3 as m * e(h1, g2)^3
482             $cipher->{C3} = $self->{pairing}->init_GT;
483             $cipher->{C3}->pairing_apply($self->{MPK}->{h1}, $self->{MPK}->{g2});
484             $cipher->{C3}->pow_zn($r);
485             $cipher->{C3}->mul($m);
486              
487             return $cipher;
488             }
489              
490             =head2 decrypt_element
491              
492             Recover the element of GT from the given ciphertext.
493              
494             Required parameters:
495              
496             =over 4
497              
498             =item Ciphertext
499              
500             The ciphertext is a hashref with (P,C1,..C4) keys,
501             as returned from the C method.
502              
503             =back
504              
505             To decrypt, the secret key (SK) is used. It must be of hierarchy length >= |P| in
506             order to be able to decrypt the pattern.
507              
508             Returns an element of GT.
509             L
510             to determine the success or failure of the decryption.
511              
512             =cut
513             sub decrypt_element {
514             my ($self, $cipher) = @_;
515              
516             croak("Cannot decrypt without secret key") unless (defined $self->{SK});
517              
518             my $pattern_len = scalar(@{$cipher->{P}});
519             my $key_hierarchy_len = scalar(@{$self->{SK}->{ids}});
520              
521             croak("Cannot decrypt pattern of length " . $pattern_len
522             . ", ID hierarchy too small: " . $key_hierarchy_len)
523             unless $key_hierarchy_len >= $pattern_len;
524              
525             for my $id ($cipher->{P}) {
526             croak("Pattern must only either an * or an integer >= 0")
527             unless ($id eq '*' || $id >= 0);
528             }
529              
530             my $c_2n = $self->{pairing}->init_G1;
531             my $temp = $self->{pairing}->init_G1;
532             # Initialize C2' as C2
533             $c_2n->set($cipher->{C2});
534              
535             # Prepare IDs from ids
536             my $ID_el = $self->{pairing}->init_Zr;
537            
538             for (my $i = 0; $i < $pattern_len; $i++) {
539             if ($cipher->{P}->[$i] eq '*') {
540             # Compute v_i ^ ID_i for each i in p that is a wildcard
541             $ID_el->set_to_int($self->{SK}->{ids}->[$i]);
542             $temp->pow_zn($cipher->{C4}->[$i], $ID_el);
543             $c_2n->mul($temp);
544             }
545             }
546              
547             # Compute m as C3 * e(C2', d_L+1) / e(C1, d_0)
548             my $m = $self->{pairing}->init_GT;
549             my $tempGT = $self->{pairing}->init_GT;
550              
551             my $keylen = scalar(@{$self->{SK}->{key}});
552             $m->pairing_apply($c_2n, $self->{SK}->{key}->[$keylen - 1]);
553             $tempGT->pairing_apply($cipher->{C1}, $self->{SK}->{key}->[0]);
554             $m->div($tempGT);
555             $m->mul($cipher->{C3});
556              
557             return $m;
558             }
559              
560             =head1 AUTHOR
561              
562             Oliver Günther
563              
564             =head1 COPYRIGHT
565              
566             Copyright (C) 2014 by Oliver Günther
567              
568             This program is free software: you can redistribute it and/or modify
569             it under the terms of the GNU General Public License as published by
570             the Free Software Foundation, either version 3 of the License, or
571             (at your option) any later version.
572              
573             This program is distributed in the hope that it will be useful,
574             but WITHOUT ANY WARRANTY; without even the implied warranty of
575             MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
576             GNU General Public License for more details.
577              
578             You should have received a copy of the GNU General Public License
579             along with this program. If not, see .
580              
581             =head1 SEE ALSO
582              
583             L
584              
585             L
586              
587             L
588              
589             =cut
590              
591             1;