Skip to content

Commit 7f17f81

Browse files
Patrik-Stasmirgee
andauthored
Rename decrypted_payload, modify its format (#173)
* Keep breaking change on decrypted payload format Signed-off-by: Patrik Stas <patrik.stas@absa.africa> * Add messaging tests + JS fixes Signed-off-by: Patrik Stas <patrik.stas@absa.africa> * Fix compile error in test Signed-off-by: Patrik Stas <patrik.stas@absa.africa> * Fix test Signed-off-by: Patrik Stas <patrik.stas@absa.africa> * Rename decrypted_payload to decrypted_msg Signed-off-by: Patrik Stas <patrik.stas@absa.africa> * Fixes for nodejs tests Signed-off-by: Patrik Stas <patrik.stas@absa.africa> * Decrypt download_messages_v2 payload (#172) * Decrypt download_messages_v2 payload Signed-off-by: Miroslav Kovar <miroslavkovar@protonmail.com> * Add downloadReceivedMessagesV2 test to agent-core Signed-off-by: Miroslav Kovar <miroslavkovar@protonmail.com> Co-authored-by: Miroslav Kovar <miroslavkovar@protonmail.com>
1 parent 84ec0b6 commit 7f17f81

File tree

11 files changed

+126
-40
lines changed

11 files changed

+126
-40
lines changed

agents/node/vcxagent-cli/vcxclient-interactive.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,7 @@ async function createInteractiveClient (agentName, seed, acceptTaa, rustLogLevel
3333
14: 'CONNECTIONS_INFO',
3434
20: 'GET_CREDENTIAL_OFFERS',
3535
30: 'SEND_MESSAGE',
36-
31: 'GET_MESSAGE'
36+
31: 'GET_MESSAGE',
3737
32: 'GET_MESSAGE_V2'
3838
}
3939

agents/node/vcxagent-core/demo/alice.js

Lines changed: 11 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -78,9 +78,18 @@ async function runAlice (options) {
7878
await vcxAgent.serviceProver.sendDisclosedProofAndProgress(disclosedProofId, connectionId)
7979
logger.info('Faber received the proof')
8080

81-
const msgs = await vcxAgent.serviceConnections.getMessagesV2(connectionId)
82-
logger.debug(`Alice received messages: ${JSON.stringify(msgs, null, 2)}`)
81+
const msgs = await vcxAgent.serviceConnections.getMessages(connectionId)
8382
assert(msgs.length === 5)
83+
assert(msgs[0].uid)
84+
assert(msgs[0].statusCode)
85+
assert(msgs[0].decryptedMsg)
86+
const payload = JSON.parse(msgs[0].decryptedMsg)
87+
assert(payload["@id"])
88+
assert(payload["@type"])
89+
90+
const msgs2 = await vcxAgent.serviceConnections.getMessagesV2(connectionId)
91+
logger.debug(`Alice received messages: ${JSON.stringify(msgs2, null, 2)}`)
92+
assert(msgs2.length === 5)
8493

8594
await vcxAgent.agentShutdownVcx()
8695
process.exit(0)

agents/node/vcxagent-core/package.json

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -35,9 +35,10 @@
3535
"demo:faber:verify": "node demo/faber-verify-signature.js",
3636
"test:legacy:integration": "node demo/integration-test.js",
3737
"test:legacy:integration:revocation": "REVOCATION=true node demo/integration-test.js",
38-
"test:integration": "npm run test:integration:update-state && npm run test:integration:signing",
38+
"test:integration": "npm run test:integration:update-state && npm run test:integration:signing && npm run test:integration:messaging",
3939
"test:integration:update-state": "jest --forceExit --env=node --runInBand test/update-state-v2.spec.js",
40-
"test:integration:signing": "jest --forceExit --env=node --runInBand test/sign-verify.spec.js"
40+
"test:integration:signing": "jest --forceExit --env=node --runInBand test/sign-verify.spec.js",
41+
"test:integration:messaging": "jest --forceExit --env=node --runInBand test/sign-messaging.spec.js"
4142
},
4243
"dependencies": {
4344
"ffi-napi": "^2.4.7",

agents/node/vcxagent-core/src/services/service-connections.js

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -111,7 +111,7 @@ module.exports.createServiceConnections = function createServiceConnections ({ l
111111

112112
async function getMessages (connectionId, filterStatuses = [], filterUids = []) {
113113
const pwDid = await getConnectionPwDid(connectionId)
114-
return getMessagesForPwDid(pwDid, [], filterStatuses, filterUids)
114+
return getMessagesForPwDid(pwDid, filterStatuses, filterUids)
115115
}
116116

117117
async function getState (connectionId) {
@@ -137,7 +137,7 @@ module.exports.createServiceConnections = function createServiceConnections ({ l
137137

138138
async function getMessagesV2 (connectionId, filterStatuses = [], filterUids = []) {
139139
const connection = await getVcxConnection(connectionId)
140-
return getMessagesForConnection([connection], [], [])
140+
return getMessagesForConnection([connection], filterStatuses, filterUids)
141141
}
142142

143143
return {
Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
/* eslint-env jest */
2+
require('jest')
3+
const { createPairedAliceAndFaber } = require('./utils/utils')
4+
const { initRustapi } = require('../src/index')
5+
6+
beforeAll(async () => {
7+
jest.setTimeout(1000 * 60 * 4)
8+
await initRustapi(process.env.VCX_LOG_LEVEL || 'vcx=error')
9+
})
10+
11+
describe('test messaging', () => {
12+
it('downloadReceivedMessages: Alice should send message and Faber download it', async () => {
13+
const { alice, faber } = await createPairedAliceAndFaber()
14+
await alice.sendMessage('Hello Faber')
15+
const msgs = await faber.downloadReceivedMessages()
16+
expect(msgs.length).toBe(1)
17+
expect(msgs[0].uid).toBeDefined()
18+
expect(msgs[0].statusCode).toBe('MS-103')
19+
const payload = JSON.parse(msgs[0].decryptedMsg)
20+
expect(payload['@id']).toBeDefined()
21+
expect(payload['@type']).toBeDefined()
22+
expect(payload.content).toBe('Hello Faber')
23+
})
24+
25+
it('downloadReceivedMessagesV2: Alice should send message and Faber download it ', async () => {
26+
const { alice, faber } = await createPairedAliceAndFaber()
27+
await alice.sendMessage('Hello Faber')
28+
const msgs = await faber.downloadReceivedMessagesV2()
29+
expect(msgs.length).toBe(1)
30+
expect(msgs[0].uid).toBeDefined()
31+
expect(msgs[0].statusCode).toBe('MS-103')
32+
const payload = JSON.parse(msgs[0].decryptedMsg)
33+
expect(payload['@id']).toBeDefined()
34+
expect(payload['@type']).toBeDefined()
35+
expect(payload.content).toBe('Hello Faber')
36+
})
37+
})

agents/node/vcxagent-core/test/utils/alice.js

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -91,7 +91,15 @@ module.exports.createAlice = async function createAlice () {
9191
return signatureBase64
9292
}
9393

94+
async function sendMessage (message) {
95+
logger.info('Alice is going to send message')
96+
await vcxAgent.agentInitVcx()
97+
await vcxAgent.serviceConnections.sendMessage(connectionId, message)
98+
await vcxAgent.agentShutdownVcx()
99+
}
100+
94101
return {
102+
sendMessage,
95103
signData,
96104
acceptInvite,
97105
updateConnection,

agents/node/vcxagent-core/test/utils/faber.js

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -135,7 +135,25 @@ module.exports.createFaber = async function createFaber () {
135135
return isValid
136136
}
137137

138+
async function downloadReceivedMessages () {
139+
logger.info('Faber is going to download messages using getMessages')
140+
await vcxAgent.agentInitVcx()
141+
const agencyMessages = await vcxAgent.serviceConnections.getMessages(connectionId, ["MS-103"])
142+
await vcxAgent.agentShutdownVcx()
143+
return agencyMessages
144+
}
145+
146+
async function downloadReceivedMessagesV2 () {
147+
logger.info('Faber is going to download messages using getMessagesV2')
148+
await vcxAgent.agentInitVcx()
149+
const agencyMessages = await vcxAgent.serviceConnections.getMessagesV2(connectionId, ["MS-103"])
150+
await vcxAgent.agentShutdownVcx()
151+
return agencyMessages
152+
}
153+
138154
return {
155+
downloadReceivedMessages,
156+
downloadReceivedMessagesV2,
139157
verifySignature,
140158
createInvite,
141159
updateConnection,

libvcx/src/aries/handlers/connection/mod.rs

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,6 @@ pub mod tests {
3131
use aries::test::{Alice, Faber};
3232

3333
use super::*;
34-
use serde_json::Value;
3534

3635
#[test]
3736
#[cfg(feature = "aries")]
@@ -148,9 +147,8 @@ pub mod tests {
148147

149148
let messages: Vec<MessageByConnection> = download_messages_noauth(None, Some(vec!["MS-103".to_string()]), None).unwrap();
150149
let message: Message = messages[0].msgs[0].clone();
151-
let msg_wrapper: Value = ::serde_json::from_str(&message.decrypted_payload.unwrap()).unwrap();
152-
let msg_aries = msg_wrapper["@msg"].as_str().unwrap();
153-
let _payload: aries::messages::issuance::credential_offer::CredentialOffer = ::serde_json::from_str(msg_aries).unwrap();
150+
let decrypted_msg = message.decrypted_msg.unwrap();
151+
let _payload: aries::messages::issuance::credential_offer::CredentialOffer = ::serde_json::from_str(&decrypted_msg).unwrap();
154152

155153
::connection::update_message_status(alice.connection_handle, message.uid).unwrap();
156154
}

libvcx/src/aries/mod.rs

Lines changed: 11 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -112,7 +112,7 @@ pub mod test {
112112
#[derive(Debug)]
113113
pub struct VcxAgencyMessage {
114114
uid: String,
115-
decrypted_payload: String,
115+
decrypted_msg: String,
116116
}
117117

118118
fn determine_message_type(a2a_message: A2AMessage) -> PayloadKinds {
@@ -132,21 +132,23 @@ pub mod test {
132132
)
133133
}
134134

135+
fn str_message_to_payload_type(message: &str) -> VcxResult<PayloadKinds> {
136+
let a2a_message = str_message_to_a2a_message(message)?;
137+
Ok(determine_message_type(a2a_message))
138+
}
139+
135140
fn download_message(did: String, filter_msg_type: PayloadKinds) -> VcxAgencyMessage {
136141
let mut messages = ::messages::get_message::download_messages_noauth(Some(vec![did]), Some(vec![String::from("MS-103")]), None).unwrap();
137142
assert_eq!(1, messages.len());
138143
let messages = messages.pop().unwrap();
139144

140145
for message in messages.msgs.into_iter() {
141-
let decrypted_payload = &message.decrypted_payload.unwrap();
142-
let msg_wrapper: Value = serde_json::from_str(decrypted_payload).unwrap();
143-
let msg_content = msg_wrapper["@msg"].as_str().unwrap();
144-
let a2a_message = str_message_to_a2a_message(msg_content).unwrap();
145-
let msg_type = determine_message_type(a2a_message);
146+
let decrypted_msg = &message.decrypted_msg.unwrap();
147+
let msg_type = str_message_to_payload_type(decrypted_msg).unwrap();
146148
if filter_msg_type == msg_type {
147149
return VcxAgencyMessage {
148150
uid: message.uid,
149-
decrypted_payload: msg_content.into(),
151+
decrypted_msg: decrypted_msg.clone(),
150152
};
151153
}
152154
}
@@ -694,7 +696,7 @@ pub mod test {
694696
{
695697
let message = alice.download_message(PayloadKinds::CredOffer);
696698

697-
alice.credential_handle = ::credential::credential_create_with_offer("test", &message.decrypted_payload).unwrap();
699+
alice.credential_handle = ::credential::credential_create_with_offer("test", &message.decrypted_msg).unwrap();
698700

699701
::connection::update_message_status(alice.connection_handle, message.uid).unwrap();
700702

@@ -712,7 +714,7 @@ pub mod test {
712714
{
713715
let agency_msg = alice.download_message(PayloadKinds::ProofRequest);
714716

715-
alice.presentation_handle = ::disclosed_proof::create_proof("test", &agency_msg.decrypted_payload).unwrap();
717+
alice.presentation_handle = ::disclosed_proof::create_proof("test", &agency_msg.decrypted_msg).unwrap();
716718

717719
::connection::update_message_status(alice.connection_handle, agency_msg.uid).unwrap();
718720

libvcx/src/connection.rs

Lines changed: 14 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -290,9 +290,13 @@ pub fn download_messages(conn_handles: Vec<u32>, status_codes: Option<Vec<Messag
290290
for conn_handle in conn_handles {
291291
let msg_by_conn = CONNECTION_MAP.get(
292292
conn_handle, |connection| {
293+
let expected_sender_vk = connection.remote_vk()?;
293294
let msgs = connection
294295
.agent_info()
295-
.download_encrypted_messages(uids.clone(), status_codes.clone())?;
296+
.download_encrypted_messages(uids.clone(), status_codes.clone())?
297+
.iter()
298+
.map(|msg| msg.decrypt_auth(&expected_sender_vk))
299+
.collect::<VcxResult<Vec<Message>>>()?;
296300
Ok(MessageByConnection{ pairwise_did: connection.agent_info().clone().pw_did, msgs })
297301
}
298302
)?;
@@ -637,21 +641,21 @@ pub mod tests {
637641
let all_messages = download_messages_noauth(None, None, None).unwrap();
638642
assert_eq!(all_messages.len(), 1);
639643
assert_eq!(all_messages[0].msgs.len(), 3);
640-
assert!(all_messages[0].msgs[0].decrypted_payload.is_some());
641-
assert!(all_messages[0].msgs[1].decrypted_payload.is_some());
644+
assert!(all_messages[0].msgs[0].decrypted_msg.is_some());
645+
assert!(all_messages[0].msgs[1].decrypted_msg.is_some());
642646

643647
let received = download_messages_noauth(None, Some(vec![MessageStatusCode::Received.to_string()]), None).unwrap();
644648
assert_eq!(received.len(), 1);
645649
assert_eq!(received[0].msgs.len(), 2);
646-
assert!(received[0].msgs[0].decrypted_payload.is_some());
650+
assert!(received[0].msgs[0].decrypted_msg.is_some());
647651
assert_eq!(received[0].msgs[0].status_code, MessageStatusCode::Received);
648-
assert!(received[0].msgs[1].decrypted_payload.is_some());
652+
assert!(received[0].msgs[1].decrypted_msg.is_some());
649653

650654
// there should be messages in "Reviewed" status connections/1.0/response from Aries-Faber connection protocol
651655
let reviewed = download_messages_noauth(None, Some(vec![MessageStatusCode::Reviewed.to_string()]), None).unwrap();
652656
assert_eq!(reviewed.len(), 1);
653657
assert_eq!(reviewed[0].msgs.len(), 1);
654-
assert!(reviewed[0].msgs[0].decrypted_payload.is_some());
658+
assert!(reviewed[0].msgs[0].decrypted_msg.is_some());
655659
assert_eq!(reviewed[0].msgs[0].status_code, MessageStatusCode::Reviewed);
656660

657661
let rejected = download_messages_noauth(None, Some(vec![MessageStatusCode::Rejected.to_string()]), None).unwrap();
@@ -661,10 +665,8 @@ pub mod tests {
661665
let specific = download_messages_noauth(None, None, Some(vec![received[0].msgs[0].uid.clone()])).unwrap();
662666
assert_eq!(specific.len(), 1);
663667
assert_eq!(specific[0].msgs.len(), 1);
664-
let msg = specific[0].msgs[0].decrypted_payload.clone().unwrap();
665-
let msg_wrapper_value: Value = serde_json::from_str(&msg).unwrap();
666-
assert!(msg_wrapper_value["@msg"].is_string());
667-
let msg_aries_value: Value = serde_json::from_str(&msg_wrapper_value["@msg"].as_str().unwrap()).unwrap();
668+
let msg = specific[0].msgs[0].decrypted_msg.clone().unwrap();
669+
let msg_aries_value: Value = serde_json::from_str(&msg).unwrap();
668670
assert!(msg_aries_value.is_object());
669671
assert!(msg_aries_value["@id"].is_string());
670672
assert!(msg_aries_value["@type"].is_string());
@@ -712,11 +714,11 @@ pub mod tests {
712714
let consumer1_received_msgs = download_messages([institution_to_consumer1].to_vec(), Some(vec![MessageStatusCode::Received]), None).unwrap();
713715
assert_eq!(consumer1_received_msgs.len(), 1);
714716
assert_eq!(consumer1_received_msgs[0].msgs.len(), 1);
715-
assert!(consumer1_received_msgs[0].msgs[0].payload.is_some());
717+
assert!(consumer1_received_msgs[0].msgs[0].decrypted_msg.is_some());
716718

717719
let consumer1_reviewed_msgs = download_messages([institution_to_consumer1].to_vec(), Some(vec![MessageStatusCode::Reviewed]), None).unwrap();
718720
assert_eq!(consumer1_reviewed_msgs.len(), 1);
719721
assert_eq!(consumer1_reviewed_msgs[0].msgs.len(), 1);
720-
assert!(consumer1_reviewed_msgs[0].msgs[0].payload.is_some());
722+
assert!(consumer1_reviewed_msgs[0].msgs[0].decrypted_msg.is_some());
721723
}
722724
}

libvcx/src/messages/get_message.rs

Lines changed: 19 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -268,7 +268,7 @@ pub struct Message {
268268
#[serde(skip_deserializing)]
269269
pub delivery_details: Vec<DeliveryDetails>,
270270
#[serde(skip_serializing_if = "Option::is_none")]
271-
pub decrypted_payload: Option<String>,
271+
pub decrypted_msg: Option<String>,
272272
}
273273

274274
#[macro_export]
@@ -288,20 +288,31 @@ impl Message {
288288

289289
pub fn decrypt_noauth(&self) -> Message {
290290
let mut new_message = self.clone();
291-
if let Ok(decrypted_msg) = self._decrypt_v3_message() {
292-
new_message.decrypted_payload = Some(decrypted_msg);
291+
if let Ok(decrypted_msg) = self._noauth_decrypt_v3_message() {
292+
new_message.decrypted_msg = Some(decrypted_msg);
293293
} else {
294-
new_message.decrypted_payload = None;
294+
new_message.decrypted_msg = None;
295295
}
296296
new_message.payload = None;
297297
new_message
298298
}
299299

300-
fn _decrypt_v3_message(&self) -> VcxResult<String> {
300+
pub fn decrypt_auth(&self, expected_sender_vk: &str) -> VcxResult<Message> {
301+
let mut new_message = self.clone();
302+
let decrypted_msg = self._auth_decrypt_v3_message(expected_sender_vk)?;
303+
new_message.decrypted_msg = Some(decrypted_msg);
304+
new_message.payload = None;
305+
Ok(new_message)
306+
}
307+
308+
fn _noauth_decrypt_v3_message(&self) -> VcxResult<String> {
301309
let a2a_message = EncryptionEnvelope::anon_unpack(self.payload()?)?;
302-
// todo: this awkward return value is here just to keep backwards comptability
303-
// todo: we should make breaking change and simplify content of Message.decrypted_payload
304-
Ok(json!({"@msg": json!(a2a_message).to_string()}).to_string())
310+
Ok(json!(&a2a_message).to_string())
311+
}
312+
313+
fn _auth_decrypt_v3_message(&self, expected_sender_vk: &str) -> VcxResult<String> {
314+
let a2a_message = EncryptionEnvelope::auth_unpack(self.payload()?, &expected_sender_vk)?;
315+
Ok(json!(&a2a_message).to_string())
305316
}
306317
}
307318

0 commit comments

Comments
 (0)