/
lib.rs
205 lines (167 loc) · 5.63 KB
/
lib.rs
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
extern crate pairing;
extern crate rustc_hex;
use std::io::{self, Read};
use pairing::bls12_381::{Bls12, Fq12, G1Affine, G2Affine};
use pairing::{CurveAffine, EncodedPoint, Engine, Field};
#[derive(Debug)]
pub struct Error(String);
impl From<String> for Error {
fn from(val: String) -> Self {
Error(val)
}
}
impl From<io::Error> for Error {
fn from(val: io::Error) -> Self {
Error(val.to_string())
}
}
fn read_bls12_pairing_input(
mut input: &[u8],
) -> Result<
Vec<(
<G1Affine as CurveAffine>::Prepared,
<G2Affine as CurveAffine>::Prepared,
)>,
Error,
> {
let length = input.len();
if length % 144 != 0 {
return Err(Error::from("wrong size".to_string()));
}
let mut res = vec![];
for _ in 0..length / 144 {
let mut g1_repr = <G1Affine as CurveAffine>::Compressed::empty();
input.read_exact(g1_repr.as_mut())?;
let a = g1_repr
.into_affine()
.map_err(|e| io::Error::new(io::ErrorKind::InvalidData, e))
.and_then(|e| {
if e.is_zero() {
Err(io::Error::new(
io::ErrorKind::InvalidData,
"point at infinity",
))
} else {
Ok(e)
}
})?;
let mut g2_repr = <G2Affine as CurveAffine>::Compressed::empty();
input.read_exact(g2_repr.as_mut())?;
let b = g2_repr
.into_affine()
.map_err(|e| io::Error::new(io::ErrorKind::InvalidData, e))
.and_then(|e| {
if e.is_zero() {
Err(io::Error::new(
io::ErrorKind::InvalidData,
"point at infinity",
))
} else {
Ok(e)
}
})?;
res.push((a.prepare(), b.prepare()));
}
Ok(res)
}
static TRUE_RES: [u8; 32] = [
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01,
];
static FALSE_RES: [u8; 32] = [
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
];
pub fn bls12_pairing(input: &[u8], output: &mut [u8; 32]) -> Result<(), Error> {
match read_bls12_pairing_input(input) {
Ok(points) => {
let refs: Vec<_> = points.iter().map(|(ref a, ref b)| (a, b)).collect();
if compute_pairing_check(refs.iter()) {
*output = TRUE_RES;
} else {
*output = FALSE_RES;
}
Ok(())
}
Err(err) => Err(err),
}
}
fn compute_pairing_check<'a, I>(i: I) -> bool
where
I: IntoIterator<
Item = &'a (
&'a <G1Affine as CurveAffine>::Prepared,
&'a <G2Affine as CurveAffine>::Prepared,
),
>,
{
Bls12::final_exponentiation(&Bls12::miller_loop(i)).unwrap() == Fq12::one()
}
#[cfg(test)]
mod tests {
use pairing::bls12_381::{G1, G2};
use pairing::CurveProjective;
use rustc_hex::FromHex;
use super::*;
#[test]
fn empty() {
assert!(compute_pairing_check(vec![]))
}
#[test]
fn unity() {
assert!(!compute_pairing_check(vec![&(
&G1Affine::from(G1::one()).prepare(),
&G2Affine::from(G2::one()).prepare(),
)]))
}
#[test]
fn read_empty() {
let input = FromHex::from_hex("").unwrap();
let mut output = [0u8; 32];
let expected =
FromHex::from_hex("0000000000000000000000000000000000000000000000000000000000000001")
.unwrap();
bls12_pairing(&input[..], &mut output).unwrap();
assert_eq!(output.to_vec(), expected);
}
#[test]
fn read_two_pairs_true() {
// check that e(1, 1) * e(-1, 1) = 1
let a1 = G1Affine::from(G1::one()).into_compressed();
let a2 = G2Affine::from(G2::one()).into_compressed();
let mut minus_one = G1::one();
minus_one.negate();
let b1 = G1Affine::from(minus_one).into_compressed();
let b2 = G2Affine::from(G2::one()).into_compressed();
let input: Vec<_> = vec![a1.as_ref(), a2.as_ref(), b1.as_ref(), b2.as_ref()]
.into_iter()
.flat_map(|s| s.into_iter())
.map(|x| *x)
.collect();
let mut output = [0u8; 32];
let expected =
FromHex::from_hex("0000000000000000000000000000000000000000000000000000000000000001")
.unwrap();
bls12_pairing(&input[..], &mut output).unwrap();
assert_eq!(output.to_vec(), expected);
}
#[test]
fn read_two_pairs_false() {
// check that e(1, 1) * e(1, 1) != 1
let a1 = G1Affine::from(G1::one()).into_compressed();
let a2 = G2Affine::from(G2::one()).into_compressed();
let b1 = G1Affine::from(G1::one()).into_compressed();
let b2 = G2Affine::from(G2::one()).into_compressed();
let input: Vec<_> = vec![a1.as_ref(), a2.as_ref(), b1.as_ref(), b2.as_ref()]
.into_iter()
.flat_map(|s| s.into_iter())
.map(|x| *x)
.collect();
let mut output = [0u8; 32];
let expected =
FromHex::from_hex("0000000000000000000000000000000000000000000000000000000000000000")
.unwrap();
bls12_pairing(&input[..], &mut output).unwrap();
assert_eq!(output.to_vec(), expected);
}
}