-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathutil.rs
153 lines (140 loc) · 5.17 KB
/
util.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
// Copyright 2023 The Dots Authors
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
use blake2::{Blake2s256, Blake2b512, Digest};
use p256::{NonZeroScalar, Scalar, U256};
use elliptic_curve::{generic_array::{GenericArray, typenum::U32}, bigint::Encoding, subtle::ConstantTimeEq};
use block_padding::{Pkcs7, Padding};
use rand::prelude::*;
use rand_chacha::ChaCha20Rng;
pub const THRESHOLD: usize = 2;
pub const NUM_SERVERS: usize = 5;
// This constant is for the number of A's each individual server belongs to.
pub const NUM_A: usize = 6; // NUM_SERVERS - 1 choose (NUM_SERVERS - THRESHOLD - 1)
pub fn string_hash_to_nzs(str: &str) -> NonZeroScalar {
// make string take up 256 bits by hashing
let mut hasher = Blake2s256::new();
hasher.update(str.as_bytes());
let mut buf = [0u8; 32];
hasher.finalize_into_reset(GenericArray::from_mut_slice(&mut buf));
// turn bytes into U256
let str_uint = U256::from_be_bytes(buf);
// get field element from U256 (Uint for the P256 curve)
let str_nzs = NonZeroScalar::from_uint(str_uint).unwrap();
str_nzs
}
pub fn sk_to_field_elts(str: &str) -> Vec<NonZeroScalar> {
let sk_bytes = str.as_bytes();
let mut sk_nzs_vec = Vec::new();
// split string into chunks
for chunk in sk_bytes.chunks(31) {
let pos = chunk.len();
let mut block: GenericArray::<u8, U32> = [0u8; 32].into();
block[..pos].copy_from_slice(chunk);
// pad each chunk to 32 bytes
Pkcs7::pad(&mut block, pos);
// turn bytes into U256
let chunk_uint = U256::from_be_bytes(block.into());
// get field element from U256 (Uint for the P256 curve)
let chunk_nzs = NonZeroScalar::from_uint(chunk_uint).unwrap();
sk_nzs_vec.push(chunk_nzs);
}
sk_nzs_vec
}
pub fn field_elts_to_string(scalars: &[Scalar]) -> String {
let mut sk_combined = String::new();
for scalar in scalars {
let bytes: GenericArray::<u8, U32> = scalar.to_bytes();
let res = Pkcs7::unpad(&bytes).unwrap();
let sk_string = String::from_utf8(res.to_vec()).unwrap();
sk_combined = sk_combined + sk_string.as_str();
}
sk_combined
}
//TODO: write test?
pub fn verify_sk_hash(salts: &[&[u8]], hashes: &[&[u8]], sk_vec: &[Scalar]) -> bool {
let mut hasher = Blake2b512::new();
for i in 0..hashes.len() {
hasher.update(&salts[i]);
for scalar in sk_vec {
hasher.update(scalar.to_bytes());
}
let hash_result = hasher.finalize_reset();
if hashes[i] != hash_result.to_vec() {
return false;
}
}
true
}
#[test]
fn test_string_hash_to_nzs() {
let str1 = String::from("str1");
let str2 = String::from("str2");
let nz1 = string_hash_to_nzs(&str1);
let nz2 = string_hash_to_nzs(&str1);
let nz3 = string_hash_to_nzs(&str2);
assert_eq!(nz1.ct_eq(&nz2).unwrap_u8(), 1);
assert_eq!(nz1.ct_eq(&nz3).unwrap_u8(), 0);
}
#[test]
fn test_sk_to_field_elt() {
let sk1 = String::from("my_key");
let nz1 = sk_to_field_elts(&sk1);
let mut scalar_vec = Vec::new();
for nz in nz1 {
scalar_vec.push(*nz.as_ref());
}
let sk_recovered = field_elts_to_string(scalar_vec.as_slice());
assert!(sk1 == sk_recovered);
let sk2 = String::from("AD302A6F48F74DD6F9D257F7149E4D06CD8936FE200AF67E08EF88D1CBA4525D");
let nz2 = sk_to_field_elts(&sk2);
let mut scalar_vec2 = Vec::new();
for nz in nz2 {
scalar_vec2.push(*nz.as_ref());
}
let sk_recovered2 = field_elts_to_string(scalar_vec2.as_slice());
assert!(sk2 == sk_recovered2);
let sk3 = String::from("");
let nz3 = sk_to_field_elts(&sk3);
let mut scalar_vec3 = Vec::new();
for nz in nz3 {
scalar_vec3.push(*nz.as_ref());
}
let sk_recovered3 = field_elts_to_string(scalar_vec3.as_slice());
assert!(sk3 == sk_recovered3);
}
//#[test]
// fn test_verify_sk_hash() {
// let rng = &mut ChaCha20Rng::from_entropy();
// let salt = rng.gen::<[u8; 32]>();
// let scalars = &mut [Scalar::ONE; 3];
// let mut hasher = Blake2b512::new();
// hasher.update(salt);
// for i in 0..3 {
// hasher.update(scalars[i].to_bytes());
// }
// let mut salts = Vec::new();
// let mut salts_bad = Vec::new();
// let mut hashes = Vec::new();
// let mut hashes_bad = Vec::new();
// let res = hasher.finalize();
// for _ in 0..3 {
// salts.push(salt.to_vec());
// hashes.push(res.to_vec());
// salts_bad.push(Vec::new());
// hashes_bad.push(Vec::new());
// }
// assert!(verify_sk_hash(salts, hashes, scalars));
// scalars[0] = Scalar::ZERO;
// assert!(!verify_sk_hash(salts_bad, hashes_bad, scalars));
// }