Skip to content

Commit b989a0c

Browse files
committed
Removes chrono and usages of DateTime<Utc> and replaces them withtime::OffsetDateTime.
This change should not have any semantic meaning and is being done to address RUSTSEC-2020-0071 (see #244) and RUSTSEC-20200159 (see #245). This is a breaking API change because some result types include create/updated timestamps. Consumers of the library will need to add a direct dependency on `time`. Note that `chrono` already uses `time` internally, so this change should not bloat transitive dependencies. For those needing serialization support of `OffsetDateTime` timestamps, the `time` crate offers this support with the `serde` feature flag. One small point of friction here is rfc3339 support. `time` has this support on [a branch](time-rs/time#387) that is blocked on a rust feature hitting stable, so I copied in a few lines of code from that branch to support deserializing rfc3339 timestamps.
1 parent 7363592 commit b989a0c

File tree

10 files changed

+210
-112
lines changed

10 files changed

+210
-112
lines changed

Cargo.toml

Lines changed: 14 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,13 @@ license = "AGPL-3.0-only"
77
repository = "https://github.com/IronCoreLabs/ironoxide"
88
documentation = "https://docs.rs/ironoxide"
99
categories = [ "cryptography" ]
10-
keywords = [ "cryptography", "proxy-re-encryption", "PRE", "ECC", "transform-encryption" ]
10+
keywords = [
11+
"cryptography",
12+
"proxy-re-encryption",
13+
"PRE",
14+
"ECC",
15+
"transform-encryption",
16+
]
1117
description = "A pure-Rust SDK for accessing IronCore's privacy platform"
1218
edition = "2018"
1319

@@ -16,7 +22,6 @@ async-trait = "0.1.21"
1622
base64 = "0.13"
1723
base64-serde = "0.6.1"
1824
bytes = "1"
19-
chrono = { version = "0.4", features = [ "serde" ] }
2025
dashmap = "4"
2126
futures = "0.3.1"
2227
hex = "0.4"
@@ -34,8 +39,13 @@ recrypt = "0.12"
3439
regex = "1.4"
3540
reqwest = { version = "0.11", features = [ "json" ], default-features = false }
3641
ring = { version = "0.16", features = [ "std" ] }
37-
serde = { version = "1.0.123", features = [ "derive" ] }
42+
serde = { version = "1.0.126", features = [ "derive" ] }
3843
serde_json = "1"
44+
time = { version = "0.3", features = [
45+
"std",
46+
"serde-human-readable",
47+
"parsing",
48+
] }
3949
tokio = { version = "1", features = [ "time" ] }
4050
url = "2.2"
4151
vec1 = "1.6"
@@ -96,4 +106,4 @@ name = "ironoxide_bench"
96106
harness = false
97107

98108
[package.metadata.docs.rs]
99-
all-features = true
109+
all-features = true

src/internal.rs

Lines changed: 8 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,6 @@ use crate::internal::{
77
rest::{Authorization, IronCoreRequest, SignatureUrlString},
88
user_api::UserId,
99
};
10-
use chrono::{DateTime, Utc};
1110
use futures::Future;
1211
use lazy_static::lazy_static;
1312
use log::error;
@@ -27,10 +26,12 @@ use std::{
2726
result::Result,
2827
sync::{Mutex, MutexGuard},
2928
};
29+
use time::OffsetDateTime;
3030

3131
pub mod document_api;
3232
pub mod group_api;
3333
mod rest;
34+
mod serde_rfc3339;
3435
pub mod user_api;
3536

3637
lazy_static! {
@@ -279,6 +280,8 @@ pub fn validate_name(name: &str, name_type: &str) -> Result<String, IronOxideErr
279280
}
280281

281282
pub mod auth_v2 {
283+
use time::OffsetDateTime;
284+
282285
use super::*;
283286

284287
/// API Auth version 2.
@@ -287,11 +290,11 @@ pub mod auth_v2 {
287290
/// Step 2 is done via `finish_with` as a request is being sent out and the bytes of the body are available.
288291
pub struct AuthV2Builder<'a> {
289292
pub(in crate::internal::auth_v2) req_auth: &'a RequestAuth,
290-
pub(in crate::internal::auth_v2) timestamp: DateTime<Utc>,
293+
pub(in crate::internal::auth_v2) timestamp: OffsetDateTime,
291294
}
292295

293296
impl<'a> AuthV2Builder<'a> {
294-
pub fn new(req_auth: &'a RequestAuth, timestamp: DateTime<Utc>) -> AuthV2Builder {
297+
pub fn new(req_auth: &'a RequestAuth, timestamp: OffsetDateTime) -> AuthV2Builder {
295298
AuthV2Builder {
296299
req_auth,
297300
timestamp,
@@ -335,7 +338,7 @@ pub struct RequestAuth {
335338
impl RequestAuth {
336339
pub fn create_signature_v2<'a>(
337340
&'a self,
338-
current_time: DateTime<Utc>,
341+
current_time: OffsetDateTime,
339342
sig_url: SignatureUrlString,
340343
method: Method,
341344
body: Option<&'a [u8]>,
@@ -1197,7 +1200,7 @@ pub(crate) mod tests {
11971200
};
11981201
let recrypt = recrypt::api::Recrypt::new();
11991202
let (_, pub_key) = recrypt.generate_key_pair()?;
1200-
let time = chrono::Utc::now();
1203+
let time = OffsetDateTime::now_utc();
12011204
let create_gmr = |id: GroupId, needs_rotation: Option<bool>| {
12021205
create_group_meta_result(
12031206
id,

src/internal/document_api.rs

Lines changed: 13 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,6 @@ use crate::{
1919
},
2020
DeviceSigningKeyPair, PolicyCache,
2121
};
22-
use chrono::{DateTime, Utc};
2322
use futures::{try_join, Future};
2423
use hex::encode;
2524
use itertools::{Either, Itertools};
@@ -39,6 +38,7 @@ use std::{
3938
ops::DerefMut,
4039
sync::Mutex,
4140
};
41+
use time::OffsetDateTime;
4242

4343
mod requests;
4444

@@ -240,11 +240,11 @@ impl DocumentListMeta {
240240
&self.0.association.typ
241241
}
242242
/// Date and time when the document was created
243-
pub fn created(&self) -> &DateTime<Utc> {
243+
pub fn created(&self) -> &OffsetDateTime {
244244
&self.0.created
245245
}
246246
/// Date and time when the document was last updated
247-
pub fn last_updated(&self) -> &DateTime<Utc> {
247+
pub fn last_updated(&self) -> &OffsetDateTime {
248248
&self.0.updated
249249
}
250250
}
@@ -279,11 +279,11 @@ impl DocumentMetadataResult {
279279
self.0.name.as_ref()
280280
}
281281
/// Date and time when the document was created
282-
pub fn created(&self) -> &DateTime<Utc> {
282+
pub fn created(&self) -> &OffsetDateTime {
283283
&self.0.created
284284
}
285285
/// Date and time when the document was last updated
286-
pub fn last_updated(&self) -> &DateTime<Utc> {
286+
pub fn last_updated(&self) -> &OffsetDateTime {
287287
&self.0.updated
288288
}
289289
/// How the requesting user has access to the document
@@ -370,8 +370,8 @@ impl DocumentEncryptUnmanagedResult {
370370
pub struct DocumentEncryptResult {
371371
id: DocumentId,
372372
name: Option<DocumentName>,
373-
updated: DateTime<Utc>,
374-
created: DateTime<Utc>,
373+
updated: OffsetDateTime,
374+
created: OffsetDateTime,
375375
encrypted_data: Vec<u8>,
376376
grants: Vec<UserOrGroup>,
377377
access_errs: Vec<DocAccessEditErr>,
@@ -390,11 +390,11 @@ impl DocumentEncryptResult {
390390
self.name.as_ref()
391391
}
392392
/// Date and time when the document was created
393-
pub fn created(&self) -> &DateTime<Utc> {
393+
pub fn created(&self) -> &OffsetDateTime {
394394
&self.created
395395
}
396396
/// Date and time when the document was last updated
397-
pub fn last_updated(&self) -> &DateTime<Utc> {
397+
pub fn last_updated(&self) -> &OffsetDateTime {
398398
&self.updated
399399
}
400400
/// Users and groups the document was successfully encrypted to
@@ -413,8 +413,8 @@ impl DocumentEncryptResult {
413413
pub struct DocumentDecryptResult {
414414
id: DocumentId,
415415
name: Option<DocumentName>,
416-
updated: DateTime<Utc>,
417-
created: DateTime<Utc>,
416+
updated: OffsetDateTime,
417+
created: OffsetDateTime,
418418
decrypted_data: Vec<u8>,
419419
}
420420
impl DocumentDecryptResult {
@@ -431,11 +431,11 @@ impl DocumentDecryptResult {
431431
self.name.as_ref()
432432
}
433433
/// Date and time when the document was created
434-
pub fn created(&self) -> &DateTime<Utc> {
434+
pub fn created(&self) -> &OffsetDateTime {
435435
&self.created
436436
}
437437
/// Date and time when the document was last updated
438-
pub fn last_updated(&self) -> &DateTime<Utc> {
438+
pub fn last_updated(&self) -> &OffsetDateTime {
439439
&self.updated
440440
}
441441
}

src/internal/document_api/requests.rs

Lines changed: 23 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -11,9 +11,9 @@ use crate::internal::{
1111
user_api::UserId,
1212
IronOxideErr, RequestAuth, RequestErrorCode,
1313
};
14-
use chrono::{DateTime, Utc};
1514
use serde::{Deserialize, Serialize};
1615
use std::convert::{TryFrom, TryInto};
16+
use time::OffsetDateTime;
1717

1818
#[derive(Clone, Debug, Eq, Hash, PartialEq, Serialize, Deserialize)]
1919
pub struct Association {
@@ -130,8 +130,10 @@ pub struct DocumentMetaApiResponse {
130130
pub association: Association,
131131
pub visible_to: DocumentVisibility,
132132
pub encrypted_symmetric_key: TransformedEncryptedValue,
133-
pub updated: DateTime<Utc>,
134-
pub created: DateTime<Utc>,
133+
#[serde(with = "crate::internal::serde_rfc3339")]
134+
pub updated: OffsetDateTime,
135+
#[serde(with = "crate::internal::serde_rfc3339")]
136+
pub created: OffsetDateTime,
135137
}
136138

137139
pub mod document_list {
@@ -147,8 +149,10 @@ pub mod document_list {
147149
pub id: DocumentId,
148150
pub name: Option<DocumentName>,
149151
pub association: Association,
150-
pub created: DateTime<Utc>,
151-
pub updated: DateTime<Utc>,
152+
#[serde(with = "crate::internal::serde_rfc3339")]
153+
pub created: OffsetDateTime,
154+
#[serde(with = "crate::internal::serde_rfc3339")]
155+
pub updated: OffsetDateTime,
152156
}
153157

154158
/// Make GET request to document list endpoint for the current user/device context
@@ -159,7 +163,7 @@ pub mod document_list {
159163
.get(
160164
"documents",
161165
RequestErrorCode::DocumentList,
162-
AuthV2Builder::new(auth, Utc::now()),
166+
AuthV2Builder::new(auth, OffsetDateTime::now_utc()),
163167
)
164168
.await
165169
}
@@ -176,7 +180,7 @@ pub mod document_get {
176180
.get(
177181
&format!("documents/{}", rest::url_encode(&id.0)),
178182
RequestErrorCode::DocumentGet,
179-
AuthV2Builder::new(auth, Utc::now()),
183+
AuthV2Builder::new(auth, OffsetDateTime::now_utc()),
180184
)
181185
.await
182186
}
@@ -194,7 +198,7 @@ pub mod edek_transform {
194198
"edeks/transform",
195199
edek_bytes,
196200
RequestErrorCode::EdekTransform,
197-
AuthV2Builder::new(auth, Utc::now()),
201+
AuthV2Builder::new(auth, OffsetDateTime::now_utc()),
198202
)
199203
.await
200204
}
@@ -227,14 +231,15 @@ pub mod document_create {
227231
pub(crate) id: DocumentId,
228232
pub(crate) value: DocumentCreateValue,
229233
}
230-
231234
#[derive(Clone, Debug, Deserialize)]
232235
#[serde(rename_all = "camelCase")]
233236
pub struct DocumentCreateResponse {
234237
pub(crate) id: DocumentId,
235238
pub(crate) name: Option<DocumentName>,
236-
pub(crate) updated: DateTime<Utc>,
237-
pub(crate) created: DateTime<Utc>,
239+
#[serde(with = "crate::internal::serde_rfc3339")]
240+
pub(crate) updated: OffsetDateTime,
241+
#[serde(with = "crate::internal::serde_rfc3339")]
242+
pub(crate) created: OffsetDateTime,
238243
pub(crate) shared_with: Vec<AccessGrant>,
239244
}
240245

@@ -259,7 +264,7 @@ pub mod document_create {
259264
"documents",
260265
&req,
261266
RequestErrorCode::DocumentCreate,
262-
AuthV2Builder::new(auth, Utc::now()),
267+
AuthV2Builder::new(auth, OffsetDateTime::now_utc()),
263268
)
264269
.await
265270
}
@@ -310,7 +315,7 @@ pub mod policy_get {
310315
"policies",
311316
&query_params,
312317
RequestErrorCode::PolicyGet,
313-
AuthV2Builder::new(auth, Utc::now()),
318+
AuthV2Builder::new(auth, OffsetDateTime::now_utc()),
314319
)
315320
.await
316321
}
@@ -334,7 +339,7 @@ pub mod document_update {
334339
&format!("documents/{}", rest::url_encode(&id.0)),
335340
&DocumentUpdateRequest { name },
336341
RequestErrorCode::DocumentUpdate,
337-
AuthV2Builder::new(auth, Utc::now()),
342+
AuthV2Builder::new(auth, OffsetDateTime::now_utc()),
338343
)
339344
.await
340345
}
@@ -464,7 +469,7 @@ pub mod document_access {
464469
&format!("documents/{}/access", rest::url_encode(id.id())),
465470
&req,
466471
RequestErrorCode::DocumentGrantAccess,
467-
AuthV2Builder::new(auth, Utc::now()),
472+
AuthV2Builder::new(auth, OffsetDateTime::now_utc()),
468473
)
469474
.await
470475
}
@@ -481,15 +486,14 @@ pub mod document_access {
481486
user_or_groups: revoke_list,
482487
},
483488
RequestErrorCode::DocumentRevokeAccess,
484-
AuthV2Builder::new(auth, Utc::now()),
489+
AuthV2Builder::new(auth, OffsetDateTime::now_utc()),
485490
)
486491
.await
487492
}
488493
}
489494

490495
#[cfg(test)]
491496
mod tests {
492-
use chrono::TimeZone;
493497

494498
use super::*;
495499

@@ -498,8 +502,8 @@ mod tests {
498502
fn document_item_serde_format_is_expected() {
499503
use document_list::DocumentListApiResponseItem;
500504

501-
let created = Utc.timestamp_millis(1_551_461_529_000);
502-
let updated = Utc.timestamp_millis(1_551_461_529_001);
505+
let created = OffsetDateTime::from_unix_timestamp_nanos(1_551_461_529_000_000).unwrap();
506+
let updated = OffsetDateTime::from_unix_timestamp_nanos(1_551_461_529_001_000).unwrap();
503507
let item = DocumentListApiResponseItem {
504508
id: DocumentId("my_id".to_string()),
505509
name: None,

0 commit comments

Comments
 (0)