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
//! This crate implements the CoverCrypt scheme. This cryptographic scheme
//! allows to:
//!
//! - encrypt messages for a given set of policy attributes;
//! - decrypt messages if the decryptor corresponds to one of the policy
//! attributes;
//! - "rotate" policy attributes, which allows to prevent decryption of older
//! ciphertexts for a new user and decryption of new ciphertexts by old users.
//! Old users can be granted decryption right for new ciphertexts after a key
//! refresh.
//!
//! The `api` module exposes the KEM built on top of CoverCrypt.
//! The `interface::statics` module exposes hybrid methods to encrypt and
//! decrypt headers and blocks using the `api` KEM and a `DEM` based on
//! AES 256 GCM.
//!
//! # Example
//!
//! ```
//! use abe_policy::{AccessPolicy, Attribute, Policy, PolicyAxis};
//! use cosmian_crypto_core::symmetric_crypto::aes_256_gcm_pure::Aes256GcmCrypto;
//! use cosmian_cover_crypt::{CoverCrypt, interfaces::statics::*};
//!
//! //
//! // Declare a new policy
//!
//! // The first attribute axis will be a security level.
//! // This axis is hierarchical, i.e. users matching
//! // `Security Level::Confidential` can also decrypt
//! // messages encrypted for `Security Level::Protected`.
//! let sec_level = PolicyAxis::new(
//!     "Security Level",
//!     &["Protected", "Confidential", "Top Secret"],
//!     true,
//! );
//!
//! // Another attribute axis will be department names.
//! // This axis is *not* hierarchical.
//! let department = PolicyAxis::new("Department", &["R&D", "HR", "MKG", "FIN"], false);
//!
//! // Generate a new `Policy` object with a 100 revocations allowed.
//! let mut policy = Policy::new(100);
//!
//! // Add the two generated axes to the policy
//! policy.add_axis(&sec_level)
//!     .unwrap();
//! policy.add_axis(&department)
//!     .unwrap();
//!
//! //
//! // Setup CoverCrypt and generate master keys
//! let cc = CoverCrypt::default();
//! let (mut master_private_key, mut master_public_key) = cc.generate_master_keys(&policy)
//!     .unwrap();
//!
//! //
//! // Generate user private key
//!
//! // The user has a security clearance `Security Level::Top Secret`,
//! // and belongs to the finance department (`Department::FIN`).
//! let access_policy =
//!     AccessPolicy::from_boolean_expression("Security Level::Top Secret && Department::FIN")
//!         .unwrap();
//! let mut user_key =
//!     cc.generate_user_private_key(&master_private_key, &access_policy, &policy)
//!         .unwrap();
//!
//! //
//! // Encrypt
//! let encrypted_header = encrypt_hybrid_header::<Aes256GcmCrypto>(
//!     &policy,
//!     &master_public_key,
//!     &[Attribute::from(("Security Level", "Top Secret"))],
//!     None,
//! ).unwrap();
//!
//! //
//! // Decryption
//!
//! // The user is able to decrypt the encrypted header.
//! assert!(decrypt_hybrid_header::<Aes256GcmCrypto>(
//!     &user_key,
//!     &encrypted_header.header_bytes,
//! )
//! .is_ok());
//!
//! //
//! // Rotate the `Security Level::Top Secret` attribute
//! policy.rotate(&Attribute::from(("Security Level", "Top Secret")))
//!     .unwrap();
//!
//! // Master keys need to be updated to take into account the policy rotation
//! cc.update_master_keys(&policy, &mut master_private_key, &mut master_public_key)
//!     .unwrap();
//!
//! //
//! // Encrypt with rotated attribute
//! let new_encrypted_header = encrypt_hybrid_header::<Aes256GcmCrypto>(
//!     &policy,
//!     &master_public_key,
//!     &[Attribute::from(("Security Level", "Top Secret"))],
//!     None,
//! ).unwrap();
//!
//! // user cannot decrypt the newly encrypted header
//! assert!(decrypt_hybrid_header::<Aes256GcmCrypto>(
//!     &user_key,
//!     &new_encrypted_header.header_bytes,
//! )
//! .is_err());
//!
//! // refresh user private key, do not grant old encryption access
//! cc.refresh_user_private_key
//!     (&mut user_key, &access_policy, &master_private_key, &policy, false)
//!     .unwrap();
//!
//! // The user with refreshed key is able to decrypt the newly encrypted header.
//! assert!(decrypt_hybrid_header::<Aes256GcmCrypto>(
//!     &user_key,
//!     &new_encrypted_header.header_bytes,
//! )
//! .is_ok());
//!
//! // But it cannot decrypt old ciphertexts
//! assert!(decrypt_hybrid_header::<Aes256GcmCrypto>(
//!     &user_key,
//!     &encrypted_header.header_bytes,
//! )
//! .is_err());
//! ```

pub mod api;
mod bytes_ser_de;
mod cover_crypt_core;
pub mod error;
pub mod interfaces;

pub use api::CoverCrypt;
pub use cover_crypt_core::{Encapsulation, MasterPrivateKey, PublicKey, UserPrivateKey};
pub use error::Error;