Change "client key" to "client id" (#3130)
In #3118 @ryneeverett mentioned that "key" suggests that this is a secret, when in truth it's just a user identifier. So "ID" is a better word for it than "key".
This commit is contained in:
committed by
GitHub
parent
8097e28318
commit
7f68441916
@@ -16,8 +16,8 @@ pub enum ServerConfig {
|
||||
/// Sync server "origin"; a URL with schema and hostname but no path or trailing `/`
|
||||
origin: String,
|
||||
|
||||
/// Client Key to identify and authenticate this replica to the server
|
||||
client_key: Uuid,
|
||||
/// Client ID to identify and authenticate this replica to the server
|
||||
client_id: Uuid,
|
||||
|
||||
/// Private encryption secret used to encrypt all data sent to the server. This can
|
||||
/// be any suitably un-guessable string of bytes.
|
||||
@@ -32,9 +32,9 @@ impl ServerConfig {
|
||||
ServerConfig::Local { server_dir } => Box::new(LocalServer::new(server_dir)?),
|
||||
ServerConfig::Remote {
|
||||
origin,
|
||||
client_key,
|
||||
client_id,
|
||||
encryption_secret,
|
||||
} => Box::new(RemoteServer::new(origin, client_key, encryption_secret)?),
|
||||
} => Box::new(RemoteServer::new(origin, client_id, encryption_secret)?),
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
@@ -12,23 +12,23 @@ const TASK_APP_ID: u8 = 1;
|
||||
|
||||
/// An Cryptor stores a secret and allows sealing and unsealing. It derives a key from the secret,
|
||||
/// which takes a nontrivial amount of time, so it should be created once and re-used for the given
|
||||
/// client_key.
|
||||
/// client_id.
|
||||
pub(super) struct Cryptor {
|
||||
key: aead::LessSafeKey,
|
||||
rng: rand::SystemRandom,
|
||||
}
|
||||
|
||||
impl Cryptor {
|
||||
pub(super) fn new(client_key: Uuid, secret: &Secret) -> Result<Self> {
|
||||
pub(super) fn new(client_id: Uuid, secret: &Secret) -> Result<Self> {
|
||||
Ok(Cryptor {
|
||||
key: Self::derive_key(client_key, secret)?,
|
||||
key: Self::derive_key(client_id, secret)?,
|
||||
rng: rand::SystemRandom::new(),
|
||||
})
|
||||
}
|
||||
|
||||
/// Derive a key as specified for version 1. Note that this may take 10s of ms.
|
||||
fn derive_key(client_key: Uuid, secret: &Secret) -> Result<aead::LessSafeKey> {
|
||||
let salt = digest::digest(&digest::SHA256, client_key.as_bytes());
|
||||
fn derive_key(client_id: Uuid, secret: &Secret) -> Result<aead::LessSafeKey> {
|
||||
let salt = digest::digest(&digest::SHA256, client_id.as_bytes());
|
||||
|
||||
let mut key_bytes = vec![0u8; aead::CHACHA20_POLY1305.key_len()];
|
||||
pbkdf2::derive(
|
||||
@@ -268,10 +268,10 @@ mod test {
|
||||
fn round_trip_bad_key() {
|
||||
let version_id = Uuid::new_v4();
|
||||
let payload = b"HISTORY REPEATS ITSELF".to_vec();
|
||||
let client_key = Uuid::new_v4();
|
||||
let client_id = Uuid::new_v4();
|
||||
|
||||
let secret = Secret(b"SEKRIT".to_vec());
|
||||
let cryptor = Cryptor::new(client_key, &secret).unwrap();
|
||||
let cryptor = Cryptor::new(client_id, &secret).unwrap();
|
||||
|
||||
let unsealed = Unsealed {
|
||||
version_id,
|
||||
@@ -280,7 +280,7 @@ mod test {
|
||||
let sealed = cryptor.seal(unsealed).unwrap();
|
||||
|
||||
let secret = Secret(b"DIFFERENT_SECRET".to_vec());
|
||||
let cryptor = Cryptor::new(client_key, &secret).unwrap();
|
||||
let cryptor = Cryptor::new(client_id, &secret).unwrap();
|
||||
assert!(cryptor.unseal(sealed).is_err());
|
||||
}
|
||||
|
||||
@@ -288,10 +288,10 @@ mod test {
|
||||
fn round_trip_bad_version() {
|
||||
let version_id = Uuid::new_v4();
|
||||
let payload = b"HISTORY REPEATS ITSELF".to_vec();
|
||||
let client_key = Uuid::new_v4();
|
||||
let client_id = Uuid::new_v4();
|
||||
|
||||
let secret = Secret(b"SEKRIT".to_vec());
|
||||
let cryptor = Cryptor::new(client_key, &secret).unwrap();
|
||||
let cryptor = Cryptor::new(client_id, &secret).unwrap();
|
||||
|
||||
let unsealed = Unsealed {
|
||||
version_id,
|
||||
@@ -303,13 +303,13 @@ mod test {
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn round_trip_bad_client_key() {
|
||||
fn round_trip_bad_client_id() {
|
||||
let version_id = Uuid::new_v4();
|
||||
let payload = b"HISTORY REPEATS ITSELF".to_vec();
|
||||
let client_key = Uuid::new_v4();
|
||||
let client_id = Uuid::new_v4();
|
||||
|
||||
let secret = Secret(b"SEKRIT".to_vec());
|
||||
let cryptor = Cryptor::new(client_key, &secret).unwrap();
|
||||
let cryptor = Cryptor::new(client_id, &secret).unwrap();
|
||||
|
||||
let unsealed = Unsealed {
|
||||
version_id,
|
||||
@@ -317,8 +317,8 @@ mod test {
|
||||
};
|
||||
let sealed = cryptor.seal(unsealed).unwrap();
|
||||
|
||||
let client_key = Uuid::new_v4();
|
||||
let cryptor = Cryptor::new(client_key, &secret).unwrap();
|
||||
let client_id = Uuid::new_v4();
|
||||
let cryptor = Cryptor::new(client_id, &secret).unwrap();
|
||||
assert!(cryptor.unseal(sealed).is_err());
|
||||
}
|
||||
|
||||
@@ -340,13 +340,13 @@ mod test {
|
||||
|
||||
#[test]
|
||||
fn good() {
|
||||
let (version_id, client_key, encryption_secret) = defaults();
|
||||
let (version_id, client_id, encryption_secret) = defaults();
|
||||
let sealed = Sealed {
|
||||
version_id,
|
||||
payload: include_bytes!("test-good.data").to_vec(),
|
||||
};
|
||||
|
||||
let cryptor = Cryptor::new(client_key, &Secret(encryption_secret)).unwrap();
|
||||
let cryptor = Cryptor::new(client_id, &Secret(encryption_secret)).unwrap();
|
||||
let unsealed = cryptor.unseal(sealed).unwrap();
|
||||
|
||||
assert_eq!(unsealed.payload, b"SUCCESS");
|
||||
@@ -355,61 +355,61 @@ mod test {
|
||||
|
||||
#[test]
|
||||
fn bad_version_id() {
|
||||
let (version_id, client_key, encryption_secret) = defaults();
|
||||
let (version_id, client_id, encryption_secret) = defaults();
|
||||
let sealed = Sealed {
|
||||
version_id,
|
||||
payload: include_bytes!("test-bad-version-id.data").to_vec(),
|
||||
};
|
||||
|
||||
let cryptor = Cryptor::new(client_key, &Secret(encryption_secret)).unwrap();
|
||||
let cryptor = Cryptor::new(client_id, &Secret(encryption_secret)).unwrap();
|
||||
assert!(cryptor.unseal(sealed).is_err());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn bad_client_key() {
|
||||
let (version_id, client_key, encryption_secret) = defaults();
|
||||
fn bad_client_id() {
|
||||
let (version_id, client_id, encryption_secret) = defaults();
|
||||
let sealed = Sealed {
|
||||
version_id,
|
||||
payload: include_bytes!("test-bad-client-key.data").to_vec(),
|
||||
payload: include_bytes!("test-bad-client-id.data").to_vec(),
|
||||
};
|
||||
|
||||
let cryptor = Cryptor::new(client_key, &Secret(encryption_secret)).unwrap();
|
||||
let cryptor = Cryptor::new(client_id, &Secret(encryption_secret)).unwrap();
|
||||
assert!(cryptor.unseal(sealed).is_err());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn bad_secret() {
|
||||
let (version_id, client_key, encryption_secret) = defaults();
|
||||
let (version_id, client_id, encryption_secret) = defaults();
|
||||
let sealed = Sealed {
|
||||
version_id,
|
||||
payload: include_bytes!("test-bad-secret.data").to_vec(),
|
||||
};
|
||||
|
||||
let cryptor = Cryptor::new(client_key, &Secret(encryption_secret)).unwrap();
|
||||
let cryptor = Cryptor::new(client_id, &Secret(encryption_secret)).unwrap();
|
||||
assert!(cryptor.unseal(sealed).is_err());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn bad_version() {
|
||||
let (version_id, client_key, encryption_secret) = defaults();
|
||||
let (version_id, client_id, encryption_secret) = defaults();
|
||||
let sealed = Sealed {
|
||||
version_id,
|
||||
payload: include_bytes!("test-bad-version.data").to_vec(),
|
||||
};
|
||||
|
||||
let cryptor = Cryptor::new(client_key, &Secret(encryption_secret)).unwrap();
|
||||
let cryptor = Cryptor::new(client_id, &Secret(encryption_secret)).unwrap();
|
||||
assert!(cryptor.unseal(sealed).is_err());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn bad_app_id() {
|
||||
let (version_id, client_key, encryption_secret) = defaults();
|
||||
let (version_id, client_id, encryption_secret) = defaults();
|
||||
let sealed = Sealed {
|
||||
version_id,
|
||||
payload: include_bytes!("test-bad-app-id.data").to_vec(),
|
||||
};
|
||||
|
||||
let cryptor = Cryptor::new(client_key, &Secret(encryption_secret)).unwrap();
|
||||
let cryptor = Cryptor::new(client_id, &Secret(encryption_secret)).unwrap();
|
||||
assert!(cryptor.unseal(sealed).is_err());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
# This file generates test-encrypted.data. To run it:
|
||||
# - pip install cryptography pbkdf2
|
||||
# - python taskchampion/src/server/generate-test-data.py taskchampion/src/server/
|
||||
# - python taskchampion/taskchampion/src/server/generate-test-data.py taskchampion/taskchampion/src/server/
|
||||
|
||||
import os
|
||||
import hashlib
|
||||
@@ -12,15 +12,15 @@ import uuid
|
||||
from cryptography.hazmat.primitives.ciphers.aead import ChaCha20Poly1305
|
||||
|
||||
# these values match values used in the rust tests
|
||||
client_key = "0666d464-418a-4a08-ad53-6f15c78270cd"
|
||||
client_id = "0666d464-418a-4a08-ad53-6f15c78270cd"
|
||||
encryption_secret = b"b4a4e6b7b811eda1dc1a2693ded"
|
||||
version_id = "b0517957-f912-4d49-8330-f612e73030c4"
|
||||
|
||||
def gen(
|
||||
version_id=version_id, client_key=client_key, encryption_secret=encryption_secret,
|
||||
version_id=version_id, client_id=client_id, encryption_secret=encryption_secret,
|
||||
app_id=1, version=1):
|
||||
# first, generate the encryption key
|
||||
salt = hashlib.sha256(uuid.UUID(client_key).bytes).digest()
|
||||
salt = hashlib.sha256(uuid.UUID(client_id).bytes).digest()
|
||||
key = pbkdf2.PBKDF2(
|
||||
encryption_secret,
|
||||
salt,
|
||||
@@ -61,8 +61,8 @@ def main():
|
||||
with open(os.path.join(dir, 'test-bad-version-id.data'), "wb") as f:
|
||||
f.write(gen(version_id=uuid.uuid4().hex))
|
||||
|
||||
with open(os.path.join(dir, 'test-bad-client-key.data'), "wb") as f:
|
||||
f.write(gen(client_key=uuid.uuid4().hex))
|
||||
with open(os.path.join(dir, 'test-bad-client-id.data'), "wb") as f:
|
||||
f.write(gen(client_id=uuid.uuid4().hex))
|
||||
|
||||
with open(os.path.join(dir, 'test-bad-secret.data'), "wb") as f:
|
||||
f.write(gen(encryption_secret=b"xxxxxxxxxxxxxxxxxxxxx"))
|
||||
|
||||
@@ -10,7 +10,7 @@ use super::crypto::{Cryptor, Sealed, Secret, Unsealed};
|
||||
|
||||
pub struct RemoteServer {
|
||||
origin: String,
|
||||
client_key: Uuid,
|
||||
client_id: Uuid,
|
||||
cryptor: Cryptor,
|
||||
agent: ureq::Agent,
|
||||
}
|
||||
@@ -25,18 +25,18 @@ const SNAPSHOT_CONTENT_TYPE: &str = "application/vnd.taskchampion.snapshot";
|
||||
/// taskchampion-sync-server).
|
||||
impl RemoteServer {
|
||||
/// Construct a new RemoteServer. The `origin` is the sync server's protocol and hostname
|
||||
/// without a trailing slash, such as `https://tcsync.example.com`. Pass a client_key to
|
||||
/// without a trailing slash, such as `https://tcsync.example.com`. Pass a client_id to
|
||||
/// identify this client to the server. Multiple replicas synchronizing the same task history
|
||||
/// should use the same client_key.
|
||||
/// should use the same client_id.
|
||||
pub fn new(
|
||||
origin: String,
|
||||
client_key: Uuid,
|
||||
client_id: Uuid,
|
||||
encryption_secret: Vec<u8>,
|
||||
) -> Result<RemoteServer> {
|
||||
Ok(RemoteServer {
|
||||
origin,
|
||||
client_key,
|
||||
cryptor: Cryptor::new(client_key, &Secret(encryption_secret.to_vec()))?,
|
||||
client_id,
|
||||
cryptor: Cryptor::new(client_id, &Secret(encryption_secret.to_vec()))?,
|
||||
agent: ureq::AgentBuilder::new()
|
||||
.timeout_connect(Duration::from_secs(10))
|
||||
.timeout_read(Duration::from_secs(60))
|
||||
@@ -86,7 +86,7 @@ impl Server for RemoteServer {
|
||||
.agent
|
||||
.post(&url)
|
||||
.set("Content-Type", HISTORY_SEGMENT_CONTENT_TYPE)
|
||||
.set("X-Client-Key", &self.client_key.to_string())
|
||||
.set("X-Client-Id", &self.client_id.to_string())
|
||||
.send_bytes(sealed.as_ref())
|
||||
{
|
||||
Ok(resp) => {
|
||||
@@ -115,7 +115,7 @@ impl Server for RemoteServer {
|
||||
match self
|
||||
.agent
|
||||
.get(&url)
|
||||
.set("X-Client-Key", &self.client_key.to_string())
|
||||
.set("X-Client-Id", &self.client_id.to_string())
|
||||
.call()
|
||||
{
|
||||
Ok(resp) => {
|
||||
@@ -148,7 +148,7 @@ impl Server for RemoteServer {
|
||||
.agent
|
||||
.post(&url)
|
||||
.set("Content-Type", SNAPSHOT_CONTENT_TYPE)
|
||||
.set("X-Client-Key", &self.client_key.to_string())
|
||||
.set("X-Client-Id", &self.client_id.to_string())
|
||||
.send_bytes(sealed.as_ref())
|
||||
.map(|_| ())?)
|
||||
}
|
||||
@@ -158,7 +158,7 @@ impl Server for RemoteServer {
|
||||
match self
|
||||
.agent
|
||||
.get(&url)
|
||||
.set("X-Client-Key", &self.client_key.to_string())
|
||||
.set("X-Client-Id", &self.client_id.to_string())
|
||||
.call()
|
||||
{
|
||||
Ok(resp) => {
|
||||
|
||||
@@ -1,2 +1,2 @@
|
||||
#§$á
|
||||
†—Õ^~B>n)j›i†¯1—î9™|µœÓ~
|
||||
®
|
||||
<EFBFBD>KŸo]æâʶ£‘†‘McØ\ï©QL)cHÂ;ÚÎ-:
|
||||
@@ -0,0 +1 @@
|
||||
%<25>ۇ <09><07><>ko¹<6F>{hكb<D983><62><EFBFBD>
|
||||
@@ -1 +0,0 @@
|
||||
<01>ΝA4φ―Γθ
|
||||
@@ -1 +1 @@
|
||||
/}ådE°‡dIcÁXéè-‡!V°Û%è4îáòd]³ÃÇ}
|
||||
κsq<0F><>nΟΐk,Βν\‹ΕΘ;W¶<΄'
|
||||
@@ -1 +1 @@
|
||||
lΰζδa|‚ο@Ο<>S_‚¬…γzέV9£q¦Ρ…‘)+¦…
|
||||
ñ±Ÿâ–ajJ›šÕ·ïq\IF4¤ó<C2A4>YÓ£
|
||||
@@ -1 +1 @@
|
||||
c╙╤TH╗Гp>╔╚Ф╨╕m4О╧к~в1╣0P░IЖ╢W╒
|
||||
cR<06>ùË|¯|iKoÌÀ˜³+t•U|Ñ™ï˜& —BIŸ·3
|
||||
@@ -1 +1 @@
|
||||
pÑ¿µÒŸ½V²ûÝäToë"}cT·äY7Æ ˆÀ@ÙdLTý`Ò
|
||||
PRÇojÇ—Þgs²&vMØYÔn<>œ?ƒÛcå¼~:œ
|
||||
Reference in New Issue
Block a user