# $P is chosen the same way as the examples above, so we'll just use that. my $N = 10; # the number of PAs, plus the TA my @s = map( $pairing->init_Zr->random, 1 .. $N ); my @P = map( $P->clone->pow_zn( $_ ), @s ); my $Y = $P->clone; $Y->pow_zn( $_ ) for @s; # The TA calculates P0 := $s[0]$P and transmits to the first PA who # calculates P1 := $s[1]$P[0] and so on. Notice the in-efficiency? # Hint: $P[0] == ($P->clone->pow_zn($s[0])). In fact, @P isn't needed # at all, unless you're combining shared-secrets with secure key # distribution. # $Q_0 (tye) and $Q_1 (merlyn) are defined above ... $d_0 = $Q_0->clone; $d_0->pow_zn( $_ ) for @s; $d_1 = $Q_1->clone; $d_1->pow_zn( $_ ) for @s; $K_01_a = $pairing->init_GT->e_hat( $Q_0, $d_1 ); $K_01_b = $pairing->init_GT->e_hat( $d_0, $Q_1 ); print "[Y] authenticated secret is the same:\n\t", substr($K_01_a->as_base64, 0, 80), "\n\t", substr($K_01_b->as_base64, 0, 80), "\n\n"; $r = $pairing->init_Zr->random; $rP = $P->clone->pow_zn( $r ); $W1 = $pairing->init_GT->e_hat( $Q_0, $Y )->pow_zn( $r ); $W2 = $pairing->init_GT->e_hat( $d_0, $rP ); print "[Y] un-authenticated secret is the same:\n\t", substr($W1->as_base64, 0, 80), "\n\t", substr($W2->as_base64, 0, 80), "\n\n";