SROS2 Broadcast Encryption System Design
Random Ideas / Brainstorming
[21/05/2021]
- Maintain one keystore that contains public key for all users
- Each node should have access to its own public key (cert) and private key
- To-dos: understand existing x509 key encryption/decryption. Source: Github Repo on M2Crypto
[22/05/2021]
- Datatype handling: in ROS2, the datatype of a publisher/subscriber should be pre-defined. However, the transmitted message cannot be in random datatype. In case that publishers and subscribers both know the datatype (by default), a robust handler for all types of messages should be identified.
[25/05/2021]
- Need to clearly handle different types of data in ROS2. Need a good parser.
- Want to understand how the data can be parsed to different types of messages by ROS2. After receiving the raw bytes, we probably need to do the same thing. Check [Design Ideas] point 4.
- Need to fix the parsing issue in Encryption module.
[26/05/2021] Important Updates
- After testing, ROS2 does not support native bytestring. Therefore, a bytestring to string encoding conversion is done before sending the data. Due to this consideration, we convert the transformed data to a StringList (custom ROS2 data type)
[16/06/2021] Design test benchmarks. The benchmark together with the installation procedure can be found at: https://github.com/ros2/performance_test. Need to examine how to get this benchmark work with SROS and how to use custom encryption layer.
[01/07/2021] Design the test environment. This part is described in details in section Test Environment Design.
[29/10/2021] The design, implementation as well as experiments are completed and submitted to USENIX 2022.
Design Ideas
One centralized keystore list: contain all the nodes and corresponding public key. In this specific implementations, two public key lists should be maintained. One is the original x509 certificate system adopted by ROS2, another is the signature verification system adopted by broadcast encryption (for current implementation we use ECDSA). The sample file structure is shown below:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20Keystore
--> public_keys
--> x509: {id: cert, id: cert, id: cert}
--> ECDSA: {id: key, id: key, id: key}
## Below is ROS2 native implementation
--> Enclave
--> enclave1
--> publisher_node
--> public_key # used for broadcast encryption
--> private_key # used for broadcast encryption
--> x509_cert
--> x509_key
--> permission.xml
--> permission.p7s
--> subscriber_node
...
--> enclave2
...
--> Keystore_certs
Each node has access to its private keys, including x509 and ECDSA
For the message communicates between nodes, they should be firstly encrypted. The encryption design is discussed in the next section.
A data parser is used to parse different ROS2 msg into bytes
Pseudocode as below.
Publisher:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24class MinimalPublisher(Node):
def __init__(self):
super().__init__('minimal_publisher')
# self.publisher_ = self.create_publisher(String, 'topic', 10)
>> self.publisher_ = self.create_publisher(Byte: encrypted_msg, 'topic', 10)
timer_period = 0.5 # seconds
self.timer = self.create_timer(timer_period, self.timer_callback)
self.i = 0
def timer_callback(self):
msg = String()
msg.data = 'Hello World: %d' % self.i
>> encrypted_msg = encrypt(msg) # in String
>> self.publisher_.publish(encrypted_msg)
self.get_logger().info('Publishing: "%s"' % msg.data)
self.i += 1And subscriber:
1
2
3
4
5
6
7
8
9
10
11
12
13
14class MinimalSubscriber(Node):
def __init__(self):
super().__init__('minimal_subscriber')
self.subscription = self.create_subscription(
Byte,
'topic',
self.listener_callback,
10)
self.subscription # prevent unused variable warning
def listener_callback(self, encrypted_msg):
msg = decrypt(encrypted_msg) # in the right format as it should be, using pickle
self.get_logger().info('I heard: "%s"' % msg.data)Probably Need to use a serialization method to handle the data. The pseudocode of encryption/decryption is shown below:
1
2
3
4
5
6
7
8
9def Encrypt(msg):
byte_data = pickle.dump(msg)
encrypted_msg = broadcast_encrypt(byte_data) # note that this is still in String
return byte_data
def Decrypt(msg):
pickled_data = broadcast_decrypt(byte_data) # pickle String
msg = pickle.load(pickled_data) # in the original preferred format
return msgIn this case, parsing is not an issue, since the transmitted data can be transmitted in byte-array. Now the only consideration is performance. Will test it out in implementation.
Package Structure
Pseudocode:
1 | class BroadcastEncryption: |
Installation Guide (Sample Version)
Create custom message type StringArray in ROS2. Follow this tutorial
1
2
3
4
5
6# in ./src directory
ros2 pkg create --build-type ament_cmake tutorial_interfaces
# move to tutorial_interfaces directory
mkdir msg
# move to msg directory, create StringArray.msg with content
strin
Performance Benchmark Design
To showcase the performance of the proposed method, we can use the benchmark cases widely accepted in the industry, such as:
- https://github.com/irobot-ros/ros2-performance and the related papers as a start.
- https://gitlab.com/ApexAI/performance_test, https://www.rti.com/products/performance.
The second one is officially referred by RTI Connext DDS implementation, which makes it more convincing.
The general idea is to test the latency of different publish/subscribe behaviors defined by the benchmark communication framework.
The performance benchmark with SROS set is achieved thanks to the support from Gitlab community. The details can be found here: https://gitlab.com/ApexAI/performance_test/-/issues/122
Test Environment Design
The goal is to establish a test environment to demonstrate the possible attacks, and show that the proposed solution can resolve the issues.
Currently we see ROS2 RMF is a good example of developing and testing multi-robots in a real-world like environment. Demo Hotel World is a good starting point.
To configure SROS in this example, we propose to set RMW_SECURITY_STRATEGY
to false
to avoid excessive complex rules. We only limit the critical topics in this test environment.