Skip to content

Commit b99b505

Browse files
authored
add oberon to okapi (#186)
* add oberon to okapi Co-authored-by: Seth Back <[email protected]>
1 parent b31334f commit b99b505

File tree

12 files changed

+681
-0
lines changed

12 files changed

+681
-0
lines changed

include/okapi.h

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,26 @@ int32_t ldproofs_verify_proof(struct ByteBuffer request,
4747
struct ByteBuffer *response,
4848
struct ExternError *err);
4949

50+
int32_t oberon_create_token(struct ByteBuffer request,
51+
struct ByteBuffer *response,
52+
struct ExternError *err);
53+
54+
int32_t oberon_blind_token(struct ByteBuffer request,
55+
struct ByteBuffer *response,
56+
struct ExternError *err);
57+
58+
int32_t oberon_unblind_token(struct ByteBuffer request,
59+
struct ByteBuffer *response,
60+
struct ExternError *err);
61+
62+
int32_t oberon_create_proof(struct ByteBuffer request,
63+
struct ByteBuffer *response,
64+
struct ExternError *err);
65+
66+
int32_t oberon_verify_proof(struct ByteBuffer request,
67+
struct ByteBuffer *response,
68+
struct ExternError *err);
69+
5070
void didcomm_byte_buffer_free(struct ByteBuffer v);
5171

5272
void didcomm_string_free(char *s);

native/Cargo.toml

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,9 @@ serde_json = "1.0.60"
2020
serde_jcs = "0.1.0"
2121
sha2 = { version = "0.9", default-features = false }
2222
bs58 = "0.3.1"
23+
oberon = { git = "https://github.com/sethjback/oberon", branch = "fix_proof_bytes" }
24+
rand = "0.8"
25+
subtle = "2.4"
2326

2427
[lib]
2528
name = "okapi"

native/build.rs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,7 @@ fn compile_protobuf_files() {
4343
"../proto/examples.proto",
4444
"../proto/keys.proto",
4545
"../proto/proofs.proto",
46+
"../proto/security.proto"
4647
],
4748
&["../proto", "../proto/pbmse"],
4849
)
@@ -52,12 +53,14 @@ fn compile_protobuf_files() {
5253
copy("okapi.keys.rs", "./src/proto/okapi_keys.rs").unwrap();
5354
copy("okapi.transport.rs", "./src/proto/okapi_transport.rs").unwrap();
5455
copy("okapi.proofs.rs", "./src/proto/okapi_proofs.rs").unwrap();
56+
copy("okapi.security.rs", "./src/proto/okapi_security.rs").unwrap();
5557
copy("google.protobuf.rs", "./src/proto/google_protobuf.rs").unwrap();
5658
copy("pbmse.rs", "./src/proto/pbmse.rs").unwrap();
5759
remove_file("okapi.examples.rs").unwrap();
5860
remove_file("okapi.keys.rs").unwrap();
5961
remove_file("okapi.transport.rs").unwrap();
6062
remove_file("okapi.proofs.rs").unwrap();
63+
remove_file("okapi.security.rs").unwrap();
6164
remove_file("google.protobuf.rs").unwrap();
6265
remove_file("pbmse.rs").unwrap();
6366
}

native/src/ffi/mod.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
pub mod didcomm;
22
pub mod didkey;
33
pub mod ldproofs;
4+
pub mod oberon;
45
pub mod utils;

native/src/ffi/oberon.rs

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
use crate::{proto::security::*, *};
2+
use ffi_support::{ByteBuffer, ExternError};
3+
4+
#[no_mangle]
5+
pub extern "C" fn oberon_create_token(request: ByteBuffer, response: &mut ByteBuffer, err: &mut ExternError) -> i32 {
6+
c_impl!(CreateOberonTokenRequest, Oberon, token, request, response, err)
7+
}
8+
9+
#[no_mangle]
10+
pub extern "C" fn oberon_blind_token(request: ByteBuffer, response: &mut ByteBuffer, err: &mut ExternError) -> i32 {
11+
c_impl!(BlindOberonTokenRequest, Oberon, blind, request, response, err)
12+
}
13+
14+
#[no_mangle]
15+
pub extern "C" fn oberon_unblind_token(request: ByteBuffer, response: &mut ByteBuffer, err: &mut ExternError) -> i32 {
16+
c_impl!(UnBlindOberonTokenRequest, Oberon, blind, request, response, err)
17+
}
18+
19+
#[no_mangle]
20+
pub extern "C" fn oberon_create_proof(request: ByteBuffer, response: &mut ByteBuffer, err: &mut ExternError) -> i32 {
21+
c_impl!(CreateOberonProofRequest, Oberon, proof, request, response, err)
22+
}
23+
24+
#[no_mangle]
25+
pub extern "C" fn oberon_verify_proof(request: ByteBuffer, response: &mut ByteBuffer, err: &mut ExternError) -> i32 {
26+
c_impl!(VerifyOberonProofRequest, Oberon, verify, request, response, err)
27+
}

native/src/lib.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ use prost::{DecodeError, Message};
55
pub struct DIDComm {}
66
pub struct DIDKey {}
77
pub struct LdProofs {}
8+
pub struct Oberon {}
89

910
#[allow(clippy::ptr_arg)]
1011
pub trait MessageFormatter {
@@ -42,6 +43,7 @@ mod ffi;
4243
#[cfg(not(target_arch = "wasm32"))]
4344
mod jni;
4445
mod ldproofs;
46+
mod oberon;
4547
pub mod proto;
4648
#[cfg(test)]
4749
mod tests;

native/src/oberon/mod.rs

Lines changed: 144 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,144 @@
1+
use crate::{proto::security::*, didcomm::Error};
2+
use std::convert::TryInto;
3+
use oberon;
4+
use rand::prelude::*;
5+
6+
impl crate::Oberon{
7+
pub fn token<'a>(request: &CreateOberonTokenRequest) -> Result<CreateOberonTokenReply, Error<'a>> {
8+
if request.data.len() == 0 {
9+
return Err(Error::InvalidField("must provide data"))
10+
}
11+
12+
let skbytes: [u8; oberon::SecretKey::BYTES] = match request.sk.as_slice().try_into() {
13+
Ok(skbytes) => skbytes,
14+
Err(_) => return Err(Error::InvalidField("invalid secret key provided"))
15+
};
16+
17+
let sk = oberon::SecretKey::from(&skbytes);
18+
let mut token = match oberon::Token::new(&sk, &request.data) {
19+
None => return Err(Error::InvalidField("invalid data provided")),
20+
Some(token) => token
21+
};
22+
23+
let blind_iter = request.blinding.iter();
24+
for blind in blind_iter {
25+
let b = oberon::Blinding::new(&blind);
26+
token = token - b;
27+
}
28+
29+
Ok(CreateOberonTokenReply {
30+
token: token.to_bytes().to_vec()
31+
})
32+
}
33+
34+
pub fn proof<'a>(request: &CreateOberonProofRequest) -> Result<CreateOberonProofReply, Error<'a>> {
35+
if request.data.len() == 0 {
36+
return Err(Error::InvalidField("must provide data"))
37+
}
38+
39+
let tokenbytes: [u8; oberon::Token::BYTES] = match request.token.as_slice().try_into() {
40+
Ok(tokenbytes) => tokenbytes,
41+
Err(_) => return Err(Error::InvalidField("invalid token provided"))
42+
};
43+
44+
let tkn = oberon::Token::from_bytes(&tokenbytes);
45+
if tkn.is_none().into() {
46+
return Err(Error::InvalidField("invalid token provided"))
47+
}
48+
49+
let blinds: Vec<oberon::Blinding> = request.blinding.iter().map(|v|{
50+
oberon::Blinding::new(&v)
51+
}).collect();
52+
53+
let mut rng = thread_rng();
54+
55+
let proof = match oberon::Proof::new(&tkn.unwrap(), &blinds, &request.data, &request.nonce, &mut rng) {
56+
None => return Err(Error::Unknown),
57+
Some(proof) => proof,
58+
};
59+
60+
Ok(CreateOberonProofReply{
61+
proof: proof.to_bytes().to_vec()
62+
})
63+
}
64+
65+
pub fn verify<'a>(request: &VerifyOberonProofRequest) -> Result<VerifyOberonProofReply, Error<'a>> {
66+
if request.data.len() == 0 {
67+
return Err(Error::InvalidField("must provide data"))
68+
}
69+
70+
let pkbytes: [u8; oberon::PublicKey::BYTES] = match request.pk.as_slice().try_into() {
71+
Ok(pkbytes) => pkbytes,
72+
Err(_) => return Err(Error::InvalidField("invalid public key provided"))
73+
};
74+
75+
let pk = oberon::PublicKey::from_bytes(&pkbytes);
76+
if pk.is_none().into() {
77+
return Err(Error::InvalidField("invalid public key provided"))
78+
}
79+
80+
let proofbytes: [u8; oberon::Proof::BYTES] = match request.proof.as_slice().try_into() {
81+
Ok(proofbytes) => proofbytes,
82+
Err(_) => return Err(Error::InvalidField("invalid proof provided"))
83+
};
84+
85+
let proof = oberon::Proof::from_bytes(&proofbytes);
86+
if proof.is_none().into() {
87+
return Err(Error::InvalidField("invalid proof provided"))
88+
}
89+
90+
let valid = proof.unwrap().open(pk.unwrap(), &*request.data, &request.nonce);
91+
92+
Ok(VerifyOberonProofReply{
93+
valid: valid.into()
94+
})
95+
}
96+
97+
pub fn blind<'a>(request: &BlindOberonTokenRequest) -> Result<BlindOberonTokenReply, Error<'a>> {
98+
let tokenbytes: [u8; oberon::Token::BYTES] = match request.token.as_slice().try_into() {
99+
Ok(tokenbytes) => tokenbytes,
100+
Err(_) => return Err(Error::InvalidField("invalid token provided"))
101+
};
102+
103+
let tkn = oberon::Token::from_bytes(&tokenbytes);
104+
if tkn.is_none().into() {
105+
return Err(Error::InvalidField("invalid token provided"))
106+
}
107+
108+
let mut tkn = tkn.unwrap();
109+
110+
let blind_iter = request.blinding.iter();
111+
for blind in blind_iter {
112+
let b = oberon::Blinding::new(&blind);
113+
tkn = tkn - b;
114+
}
115+
116+
Ok(BlindOberonTokenReply{
117+
token: tkn.to_bytes().to_vec()
118+
})
119+
}
120+
121+
pub fn unblind<'a>(request: &UnBlindOberonTokenRequest) -> Result<BlindOberonTokenReply, Error<'a>> {
122+
let tokenbytes: [u8; oberon::Token::BYTES] = match request.token.as_slice().try_into() {
123+
Ok(tokenbytes) => tokenbytes,
124+
Err(_) => return Err(Error::InvalidField("invalid token provided"))
125+
};
126+
127+
let tkn = oberon::Token::from_bytes(&tokenbytes);
128+
if tkn.is_none().into() {
129+
return Err(Error::InvalidField("invalid token provided"))
130+
}
131+
132+
let mut tkn = tkn.unwrap();
133+
134+
let blind_iter = request.blinding.iter();
135+
for blind in blind_iter {
136+
let b = oberon::Blinding::new(&blind);
137+
tkn = tkn + b;
138+
}
139+
140+
Ok(BlindOberonTokenReply{
141+
token: tkn.to_bytes().to_vec()
142+
})
143+
}
144+
}

native/src/proto/mod.rs

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -282,7 +282,11 @@ pub mod transport {
282282
pub mod proofs {
283283
pub use crate::proto::okapi_proofs::*;
284284
}
285+
pub mod security {
286+
pub use crate::proto::okapi_security::*;
287+
}
285288
pub mod okapi_keys;
286289
pub mod okapi_proofs;
287290
pub mod okapi_transport;
291+
pub mod okapi_security;
288292
pub mod pbmse;

native/src/proto/okapi_security.rs

Lines changed: 110 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,110 @@
1+
/// Create a new oberon token
2+
#[derive(::serde::Serialize, ::serde::Deserialize)]
3+
#[derive(Clone, PartialEq, ::prost::Message)]
4+
pub struct CreateOberonTokenRequest {
5+
/// raw BLS key bytes
6+
#[prost(bytes="vec", tag="1")]
7+
pub sk: ::prost::alloc::vec::Vec<u8>,
8+
/// data is the public part of the oberon protocol and can be any data
9+
#[prost(bytes="vec", tag="2")]
10+
pub data: ::prost::alloc::vec::Vec<u8>,
11+
/// optional blinding for the token
12+
#[prost(bytes="vec", repeated, tag="3")]
13+
pub blinding: ::prost::alloc::vec::Vec<::prost::alloc::vec::Vec<u8>>,
14+
}
15+
/// Contains the token with optional blinding
16+
#[derive(::serde::Serialize, ::serde::Deserialize)]
17+
#[derive(Clone, PartialEq, ::prost::Message)]
18+
pub struct CreateOberonTokenReply {
19+
/// raw token bytes
20+
#[prost(bytes="vec", tag="1")]
21+
pub token: ::prost::alloc::vec::Vec<u8>,
22+
}
23+
/// Create a proof that holder knows the token
24+
#[derive(::serde::Serialize, ::serde::Deserialize)]
25+
#[derive(Clone, PartialEq, ::prost::Message)]
26+
pub struct CreateOberonProofRequest {
27+
/// data used to create the token
28+
#[prost(bytes="vec", tag="1")]
29+
pub data: ::prost::alloc::vec::Vec<u8>,
30+
/// token data
31+
#[prost(bytes="vec", tag="2")]
32+
pub token: ::prost::alloc::vec::Vec<u8>,
33+
/// any blindings used to create the token
34+
#[prost(bytes="vec", repeated, tag="3")]
35+
pub blinding: ::prost::alloc::vec::Vec<::prost::alloc::vec::Vec<u8>>,
36+
/// nonce for generating the proof
37+
#[prost(bytes="vec", tag="4")]
38+
pub nonce: ::prost::alloc::vec::Vec<u8>,
39+
}
40+
/// Contains the token proof
41+
#[derive(::serde::Serialize, ::serde::Deserialize)]
42+
#[derive(Clone, PartialEq, ::prost::Message)]
43+
pub struct CreateOberonProofReply {
44+
/// raw proof bytes
45+
#[prost(bytes="vec", tag="2")]
46+
pub proof: ::prost::alloc::vec::Vec<u8>,
47+
}
48+
/// Verify the presented proof is valid
49+
#[derive(::serde::Serialize, ::serde::Deserialize)]
50+
#[derive(Clone, PartialEq, ::prost::Message)]
51+
pub struct VerifyOberonProofRequest {
52+
/// raw proof bytes returned from CreateProof
53+
#[prost(bytes="vec", tag="1")]
54+
pub proof: ::prost::alloc::vec::Vec<u8>,
55+
/// data used to create the token
56+
#[prost(bytes="vec", tag="2")]
57+
pub data: ::prost::alloc::vec::Vec<u8>,
58+
/// nonce used to generate the proof
59+
#[prost(bytes="vec", tag="3")]
60+
pub nonce: ::prost::alloc::vec::Vec<u8>,
61+
/// public key that was used to generate the token
62+
#[prost(bytes="vec", tag="4")]
63+
pub pk: ::prost::alloc::vec::Vec<u8>,
64+
}
65+
/// Contains the status of the proof validation
66+
#[derive(::serde::Serialize, ::serde::Deserialize)]
67+
#[derive(Clone, PartialEq, ::prost::Message)]
68+
pub struct VerifyOberonProofReply {
69+
/// whether the given proof was valid
70+
#[prost(bool, tag="1")]
71+
pub valid: bool,
72+
}
73+
/// Blind an oberon token
74+
#[derive(::serde::Serialize, ::serde::Deserialize)]
75+
#[derive(Clone, PartialEq, ::prost::Message)]
76+
pub struct BlindOberonTokenRequest {
77+
/// raw token bytes
78+
#[prost(bytes="vec", tag="1")]
79+
pub token: ::prost::alloc::vec::Vec<u8>,
80+
/// blinding to apply to the token
81+
#[prost(bytes="vec", repeated, tag="2")]
82+
pub blinding: ::prost::alloc::vec::Vec<::prost::alloc::vec::Vec<u8>>,
83+
}
84+
/// Contains the blinded token reply
85+
#[derive(::serde::Serialize, ::serde::Deserialize)]
86+
#[derive(Clone, PartialEq, ::prost::Message)]
87+
pub struct BlindOberonTokenReply {
88+
/// raw blinded token bytes
89+
#[prost(bytes="vec", tag="1")]
90+
pub token: ::prost::alloc::vec::Vec<u8>,
91+
}
92+
/// UnBlind an oberon token
93+
#[derive(::serde::Serialize, ::serde::Deserialize)]
94+
#[derive(Clone, PartialEq, ::prost::Message)]
95+
pub struct UnBlindOberonTokenRequest {
96+
/// raw token bytes
97+
#[prost(bytes="vec", tag="1")]
98+
pub token: ::prost::alloc::vec::Vec<u8>,
99+
/// blinding to remove from the token
100+
#[prost(bytes="vec", repeated, tag="2")]
101+
pub blinding: ::prost::alloc::vec::Vec<::prost::alloc::vec::Vec<u8>>,
102+
}
103+
/// Contains the unblinded token reply
104+
#[derive(::serde::Serialize, ::serde::Deserialize)]
105+
#[derive(Clone, PartialEq, ::prost::Message)]
106+
pub struct UnBlindOberonTokenReply {
107+
/// raw unblinded token bytes
108+
#[prost(bytes="vec", tag="1")]
109+
pub token: ::prost::alloc::vec::Vec<u8>,
110+
}

native/src/tests/mod.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
11
pub mod keys;
22
pub mod pack;
33
pub mod sign;
4+
pub mod oberon;

0 commit comments

Comments
 (0)