V0.6.0 Arroyo Toad
Added the capability to sign and verify P521 Signature
This commit is contained in:
parent
6859e27368
commit
ad4fd555f1
36
LICENSE
36
LICENSE
@ -1,18 +1,18 @@
|
|||||||
LICENSE
|
LICENSE
|
||||||
=======
|
=======
|
||||||
|
|
||||||
Permission to use, copy, modify, and distribute this software and its
|
Permission to use, copy, modify, and distribute this software and its
|
||||||
documentation for any purpose and without fee is hereby granted, provided
|
documentation for any purpose and without fee is hereby granted, provided
|
||||||
that the original copyright notices appear in all copies and that both
|
that the original copyright notices appear in all copies and that both
|
||||||
copyright notice and this permission notice appear in supporting
|
copyright notice and this permission notice appear in supporting
|
||||||
documentation, and that the name of the author not be used in advertising
|
documentation, and that the name of the author not be used in advertising
|
||||||
or publicity pertaining to distribution of the software without specific
|
or publicity pertaining to distribution of the software without specific
|
||||||
prior written permission.
|
prior written permission.
|
||||||
|
|
||||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
||||||
THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||||
FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
||||||
DEALINGS IN THE SOFTWARE.
|
DEALINGS IN THE SOFTWARE.
|
||||||
|
|||||||
24
Package.resolved
Normal file
24
Package.resolved
Normal file
@ -0,0 +1,24 @@
|
|||||||
|
{
|
||||||
|
"originHash" : "dc0be3b6ca36aebf9cc5cf891bb7e7064d6b816c6ad89f60f5647f097455aa46",
|
||||||
|
"pins" : [
|
||||||
|
{
|
||||||
|
"identity" : "swift-asn1",
|
||||||
|
"kind" : "remoteSourceControl",
|
||||||
|
"location" : "https://github.com/apple/swift-asn1.git",
|
||||||
|
"state" : {
|
||||||
|
"revision" : "7faebca1ea4f9aaf0cda1cef7c43aecd2311ddf6",
|
||||||
|
"version" : "1.3.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"identity" : "swift-crypto",
|
||||||
|
"kind" : "remoteSourceControl",
|
||||||
|
"location" : "https://github.com/apple/swift-crypto.git",
|
||||||
|
"state" : {
|
||||||
|
"branch" : "main",
|
||||||
|
"revision" : "dc4c2c14e7ff95ee3aa8d3c2a217a248f51d3688"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"version" : 3
|
||||||
|
}
|
||||||
@ -1,24 +1,32 @@
|
|||||||
// swift-tools-version: 6.0
|
// swift-tools-version: 6.0
|
||||||
// The swift-tools-version declares the minimum version of Swift required to build this package.
|
// The swift-tools-version declares the minimum version of Swift required to build this package.
|
||||||
|
|
||||||
import PackageDescription
|
import PackageDescription
|
||||||
|
|
||||||
let package = Package(
|
let package = Package(
|
||||||
name: "MessageUtils",
|
name: "MessageUtils",
|
||||||
products: [
|
products: [
|
||||||
// Products define the executables and libraries a package produces, making them visible to other packages.
|
// Products define the executables and libraries a package produces, making them visible to other packages.
|
||||||
.library(
|
.library(
|
||||||
name: "MessageUtils",
|
name: "MessageUtils",
|
||||||
targets: ["MessageUtils"]),
|
targets: ["MessageUtils"]),
|
||||||
],
|
],
|
||||||
targets: [
|
dependencies: [
|
||||||
// Targets are the basic building blocks of a package, defining a module or a test suite.
|
.package(url: "https://github.com/apple/swift-crypto.git", branch: "main"),
|
||||||
// Targets can depend on other targets in this package and products from dependencies.
|
|
||||||
.target(
|
],
|
||||||
name: "MessageUtils"),
|
targets: [
|
||||||
.testTarget(
|
// Targets are the basic building blocks of a package, defining a module or a test suite.
|
||||||
name: "MessageUtilsTests",
|
// Targets can depend on other targets in this package and products from dependencies.
|
||||||
dependencies: ["MessageUtils"]
|
.target(
|
||||||
),
|
name: "MessageUtils",
|
||||||
]
|
dependencies: [
|
||||||
)
|
.product(name: "Crypto", package: "swift-crypto"),
|
||||||
|
]
|
||||||
|
),
|
||||||
|
.testTarget(
|
||||||
|
name: "MessageUtilsTests",
|
||||||
|
dependencies: ["MessageUtils"]
|
||||||
|
),
|
||||||
|
]
|
||||||
|
)
|
||||||
|
|||||||
0
Private/.gitkeep
Normal file
0
Private/.gitkeep
Normal file
16
Private/cert.pem
Normal file
16
Private/cert.pem
Normal file
@ -0,0 +1,16 @@
|
|||||||
|
-----BEGIN CERTIFICATE-----
|
||||||
|
MIICeTCCAdqgAwIBAgIUeKyiiDJdVGH3ParIry5vn/YGnaowCgYIKoZIzj0EAwIw
|
||||||
|
TjELMAkGA1UEBhMCSVQxDTALBgNVBAgMBEJhcmkxDTALBgNVBAcMBEJhcmkxITAf
|
||||||
|
BgNVBAoMGEludGVybmV0IFdpZGdpdHMgUHR5IEx0ZDAeFw0yNDEyMDIxNjM0NDVa
|
||||||
|
Fw0yNTAxMDExNjM0NDVaME4xCzAJBgNVBAYTAklUMQ0wCwYDVQQIDARCYXJpMQ0w
|
||||||
|
CwYDVQQHDARCYXJpMSEwHwYDVQQKDBhJbnRlcm5ldCBXaWRnaXRzIFB0eSBMdGQw
|
||||||
|
gZswEAYHKoZIzj0CAQYFK4EEACMDgYYABAAAfWnGEUMElY/XIWUTPvX65HX3N5Ik
|
||||||
|
JKPdVFzDRtaTHRJKnEEvU7Z5iLAT9NpbVfCabvQXKo7LD5sjoJ1ZpSVcogDgCFCo
|
||||||
|
pmVin2ZLs5lyMtaetpVDH8m+AIlRQkkuGmkasM+OV62kzSoHl/CL4eNz1xXwqsPt
|
||||||
|
oBgvPiRFxNIE/0dz96NTMFEwHQYDVR0OBBYEFKW5mYrSXJn68diXLDjhbiEGAxJu
|
||||||
|
MB8GA1UdIwQYMBaAFKW5mYrSXJn68diXLDjhbiEGAxJuMA8GA1UdEwEB/wQFMAMB
|
||||||
|
Af8wCgYIKoZIzj0EAwIDgYwAMIGIAkIAhVgtxgnZd6KeefLjZ6Mazgr5xLDcAHyI
|
||||||
|
NsKtTw3YzT/Pztnk2ccV+NyDZyoTG72lHoPMTiB5mRSUTqORg59XQTkCQgDqHRoN
|
||||||
|
tRQlPWY3abohilRRdvYZrsoPR8FzB/M4KxT0nk10jc1wtosQ7l/XZGcKe8/k+iVs
|
||||||
|
HC5CsESzsvnp+Qslyw==
|
||||||
|
-----END CERTIFICATE-----
|
||||||
7
Private/privateKey.pem
Normal file
7
Private/privateKey.pem
Normal file
@ -0,0 +1,7 @@
|
|||||||
|
-----BEGIN EC PRIVATE KEY-----
|
||||||
|
MIHcAgEBBEIBAQAy+3ElWUTttb9xxVDshJlGt/clGdhPkp76aJ3LJySugsnC8RRO
|
||||||
|
UracnWQi2A+XnEI1ZskzYAFUfh7G5o5ViDygBwYFK4EEACOhgYkDgYYABAAAfWnG
|
||||||
|
EUMElY/XIWUTPvX65HX3N5IkJKPdVFzDRtaTHRJKnEEvU7Z5iLAT9NpbVfCabvQX
|
||||||
|
Ko7LD5sjoJ1ZpSVcogDgCFCopmVin2ZLs5lyMtaetpVDH8m+AIlRQkkuGmkasM+O
|
||||||
|
V62kzSoHl/CL4eNz1xXwqsPtoBgvPiRFxNIE/0dz9w==
|
||||||
|
-----END EC PRIVATE KEY-----
|
||||||
8
Private/privateKey_ASN1.pem
Normal file
8
Private/privateKey_ASN1.pem
Normal file
@ -0,0 +1,8 @@
|
|||||||
|
-----BEGIN PRIVATE KEY-----
|
||||||
|
MIHuAgEAMBAGByqGSM49AgEGBSuBBAAjBIHWMIHTAgEBBEIBAQAy+3ElWUTttb9x
|
||||||
|
xVDshJlGt/clGdhPkp76aJ3LJySugsnC8RROUracnWQi2A+XnEI1ZskzYAFUfh7G
|
||||||
|
5o5ViDyhgYkDgYYABAAAfWnGEUMElY/XIWUTPvX65HX3N5IkJKPdVFzDRtaTHRJK
|
||||||
|
nEEvU7Z5iLAT9NpbVfCabvQXKo7LD5sjoJ1ZpSVcogDgCFCopmVin2ZLs5lyMtae
|
||||||
|
tpVDH8m+AIlRQkkuGmkasM+OV62kzSoHl/CL4eNz1xXwqsPtoBgvPiRFxNIE/0dz
|
||||||
|
9w==
|
||||||
|
-----END PRIVATE KEY-----
|
||||||
BIN
Private/signedMessage/Message.bin
Normal file
BIN
Private/signedMessage/Message.bin
Normal file
Binary file not shown.
@ -1,4 +1,4 @@
|
|||||||
public enum DeviceType: UInt8 {
|
public enum DeviceType: UInt8 {
|
||||||
case EDGE_SENSOR = 0
|
case EDGE_SENSOR = 0
|
||||||
case SCANNER_SENSOR = 1
|
case SCANNER_SENSOR = 1
|
||||||
}
|
}
|
||||||
@ -1,8 +1,8 @@
|
|||||||
public enum MessageType: UInt8 {
|
public enum MessageType: UInt8 {
|
||||||
case KEEPALIVE = 0
|
case KEEPALIVE = 0
|
||||||
case DATA = 1
|
case DATA = 1
|
||||||
case INFO = 2
|
case INFO = 2
|
||||||
case WARNING = 50
|
case WARNING = 50
|
||||||
case ERROR = 100
|
case ERROR = 100
|
||||||
case CRITICAL = 255
|
case CRITICAL = 255
|
||||||
}
|
}
|
||||||
@ -1,3 +1,3 @@
|
|||||||
public enum SignType: UInt32 {
|
public enum SignType: UInt32 {
|
||||||
case P521 = 10
|
case P521 = 10
|
||||||
}
|
}
|
||||||
@ -1,13 +1,13 @@
|
|||||||
public enum SerializationError : Error {
|
public enum SerializationError : Error {
|
||||||
|
|
||||||
case SIGNATURE_NOT_SUPPORTED
|
case SIGNATURE_NOT_SUPPORTED
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public enum CommonError : Error {
|
public enum CommonError : Error {
|
||||||
case SIGNATURE_NOT_SUPPORTED
|
case SIGNATURE_NOT_SUPPORTED
|
||||||
}
|
}
|
||||||
|
|
||||||
public enum DeserializationError: Error {
|
public enum DeserializationError: Error {
|
||||||
case UNMATCHING_SIGNATURE_TYPE
|
case UNMATCHING_SIGNATURE_TYPE
|
||||||
}
|
}
|
||||||
@ -1,203 +1,213 @@
|
|||||||
// The Swift Programming Language
|
// The Swift Programming Language
|
||||||
// https://docs.swift.org/swift-book
|
// https://docs.swift.org/swift-book
|
||||||
import Foundation
|
|
||||||
|
import Foundation
|
||||||
public func serializeV1(msg: Message) throws -> Data {
|
import Crypto
|
||||||
|
|
||||||
let MESSAGE_CAPACITY: Int = try countBytes(msg: msg)
|
public func serializeV1(msg: MessageP) -> Data {
|
||||||
|
|
||||||
var serializedData: Data = Data(count: MESSAGE_CAPACITY)
|
let MESSAGE_CAPACITY: Int = countBytes(msg: msg)
|
||||||
|
|
||||||
// Serialize Header
|
var serializedData: Data = Data(count: MESSAGE_CAPACITY)
|
||||||
|
|
||||||
// UGLY: extrapolate in functions
|
// Serialize Header
|
||||||
serializedData[0] = msg.version
|
|
||||||
serializedData[1] = msg.messageType.rawValue
|
// UGLY: extrapolate in functions
|
||||||
serializedData[2] = msg.devType.rawValue
|
serializedData[0] = msg.version
|
||||||
serializedData[3] = msg.RESERVED
|
serializedData[1] = msg.messageType.rawValue
|
||||||
serializedData[4...7] = msg.signType.rawValue.data
|
serializedData[2] = msg.devType.rawValue
|
||||||
// First 8 bytes
|
serializedData[3] = msg.RESERVED
|
||||||
|
serializedData[4...7] = msg.signType.rawValue.data
|
||||||
serializedData[8...15] = msg.timestamp.data
|
// First 8 bytes
|
||||||
// 8 Bytes
|
|
||||||
|
serializedData[8...15] = msg.timestamp.data
|
||||||
serializedData[16...31] = msg.devID.data
|
// 8 Bytes
|
||||||
// 16 bytes
|
|
||||||
|
serializedData[16...31] = msg.devID.data
|
||||||
serializedData[32...39] = msg.location.x.data
|
// 16 bytes
|
||||||
// 8 Bytes
|
|
||||||
|
serializedData[32...39] = msg.location.x.data
|
||||||
serializedData[40...47] = msg.location.y.data
|
// 8 Bytes
|
||||||
// 8 Bytes
|
|
||||||
|
serializedData[40...47] = msg.location.y.data
|
||||||
serializedData[48...55] = msg.location.z.data
|
// 8 Bytes
|
||||||
// 8 Bytes
|
|
||||||
|
serializedData[48...55] = msg.location.z.data
|
||||||
var index = 56
|
// 8 Bytes
|
||||||
|
|
||||||
for field in msg.fields {
|
var index = 56
|
||||||
serializedData[index...(index + 3)] = UInt32(field.key.count).data
|
|
||||||
serializedData[(index + 4)...(index + 7)] = UInt32(field.key.count).data
|
for field in msg.fields {
|
||||||
|
|
||||||
index += 8
|
serializedData[index..<(index + 4)] = UInt32(field.key.count).data
|
||||||
|
serializedData[(index + 4)..<(index + 8)] = UInt32(field.value.count).data
|
||||||
serializedData[index..<(index + field.key.count)] = Data(field.key)
|
|
||||||
|
index += 8
|
||||||
index += field.key.count
|
|
||||||
|
serializedData[index..<(index + field.key.count)] = Data(field.key)
|
||||||
serializedData[index..<(index + field.value.count)] = Data(field.value)
|
|
||||||
|
index += field.key.count
|
||||||
index += field.value.count
|
|
||||||
}
|
serializedData[index..<(index + field.value.count)] = Data(field.value)
|
||||||
|
|
||||||
let paddingBytes = (8 - (index % 8)) % 8
|
index += field.value.count
|
||||||
|
}
|
||||||
serializedData[index..<(index + paddingBytes)] = Data(count: paddingBytes)
|
|
||||||
index += paddingBytes
|
let paddingBytes = (8 - (index % 8)) % 8
|
||||||
|
|
||||||
// Add STOP FIELDS
|
serializedData[index..<(index + paddingBytes)] = Data(count: paddingBytes)
|
||||||
serializedData[index..<(index + 8)] = UInt64(0).data
|
index += paddingBytes
|
||||||
print(UInt64(0).data.base64EncodedString())
|
|
||||||
index += 8
|
// Add STOP FIELDS
|
||||||
serializedData[index..<serializedData.count] = Data(msg.signature)
|
serializedData[index..<(index + 8)] = UInt64(0).data
|
||||||
|
|
||||||
if serializedData.count % 8 != 0 {
|
return serializedData
|
||||||
print(serializedData.count % 8)
|
}
|
||||||
print(MESSAGE_CAPACITY % 8)
|
|
||||||
}
|
public func signMessage(msgData: Data, signType: SignType, key: P521.Signing.PrivateKey) throws -> [UInt8] {
|
||||||
|
let signatureBytes = try signatureBytes(signature: signType)
|
||||||
return serializedData
|
|
||||||
}
|
// UGLY We are hypothesisying that signType is P521
|
||||||
|
let signature = try signP521(object: msgData, key: key).map { value in
|
||||||
public func derializeV1(serializedData: Data) throws -> Message {
|
return value
|
||||||
|
}
|
||||||
// Serialize Header
|
|
||||||
|
return signature
|
||||||
// UGLY: extrapolate in functions
|
|
||||||
let version: UInt8 = serializedData[0]
|
}
|
||||||
let messageType: MessageType = MessageType(rawValue: serializedData[1])!
|
|
||||||
let devType: DeviceType = DeviceType(rawValue: serializedData[2])!
|
|
||||||
let RESERVED: UInt8 = serializedData[3]
|
public func verifyMessageSignature(message: SignedMessage, key: P521.Signing.PublicKey) throws -> Bool {
|
||||||
let signType: SignType = SignType(rawValue: serializedData[4...7].uint32)!
|
// UGLY Assuming P521 Signature
|
||||||
// First 8 bytes
|
|
||||||
|
let msgData = serializeV1(msg: message)
|
||||||
let signBytes = try signatureBytes(signature: signType)
|
return try verifySignatureP521(signature: Data(message.signature), object: msgData, key: key)
|
||||||
|
|
||||||
let timestamp = serializedData[8...15].timestamp
|
}
|
||||||
// 8 Bytes
|
|
||||||
|
public func deserializeV1(serializedData: Data) throws -> SignedMessage {
|
||||||
let devID = serializedData[16...31].uint128
|
|
||||||
// 16 bytes
|
// Serialize Header
|
||||||
|
|
||||||
let locationX = serializedData[32...39].uint64
|
// UGLY: extrapolate in functions
|
||||||
// 8 Bytes
|
let version: UInt8 = serializedData[0]
|
||||||
|
let messageType: MessageType = MessageType(rawValue: serializedData[1])!
|
||||||
let locationY = serializedData[40...47].uint64
|
let devType: DeviceType = DeviceType(rawValue: serializedData[2])!
|
||||||
// 8 Bytes
|
let RESERVED: UInt8 = serializedData[3]
|
||||||
|
let signType: SignType = SignType(rawValue: serializedData[4...7].uint32)!
|
||||||
let locationZ = serializedData[48...55].uint64
|
// First 8 bytes
|
||||||
// 8 Bytes
|
|
||||||
|
let signBytes = try signatureBytes(signature: signType)
|
||||||
var index = 56
|
|
||||||
|
let timestamp = serializedData[8...15].timestamp
|
||||||
// Deserializing Fields
|
// 8 Bytes
|
||||||
var MORE_FIELDS = true
|
|
||||||
var fields: [Field] = []
|
let devID = serializedData[16...31].uint128
|
||||||
|
// 16 bytes
|
||||||
while MORE_FIELDS {
|
|
||||||
|
let locationX = serializedData[32...39].uint64
|
||||||
let nextChunk = serializedData[index..<(index + 8)]
|
// 8 Bytes
|
||||||
let fieldKeyCount = serializedData[index...(index + 4)].uint32
|
|
||||||
let fieldValueCount = serializedData[(index + 4)..<(index + 8)].uint32
|
let locationY = serializedData[40...47].uint64
|
||||||
|
// 8 Bytes
|
||||||
index += 8
|
|
||||||
|
let locationZ = serializedData[48...55].uint64
|
||||||
let a = nextChunk.uint64
|
// 8 Bytes
|
||||||
|
|
||||||
if nextChunk.uint64 == 0 {
|
var index = 56
|
||||||
MORE_FIELDS = false
|
|
||||||
continue
|
// Deserializing Fields
|
||||||
}
|
var MORE_FIELDS = true
|
||||||
|
var fields: [Field] = []
|
||||||
let key = serializedData[index..<(index + Int(fieldKeyCount))].map { value in
|
|
||||||
return value
|
while MORE_FIELDS {
|
||||||
}
|
|
||||||
index += Int(fieldKeyCount)
|
let nextChunk = serializedData[index..<(index + 8)]
|
||||||
let value = serializedData[index..<(index + Int(fieldValueCount))].map { value in
|
|
||||||
return value
|
let a = nextChunk.map { value in
|
||||||
}
|
return value
|
||||||
index += Int(fieldValueCount)
|
}
|
||||||
|
|
||||||
fields.append(Field(key: key, value: value))
|
if nextChunk.uint64 == 0 {
|
||||||
|
MORE_FIELDS = false
|
||||||
}
|
continue
|
||||||
|
}
|
||||||
let paddingBytes = (8 - (index % 8)) % 8
|
|
||||||
|
let fieldKeyCount = serializedData[index..<(index + 4)].uint32
|
||||||
// Skip padding bytes
|
let fieldValueCount = serializedData[(index + 4)..<(index + 8)].uint32
|
||||||
index += paddingBytes
|
|
||||||
|
index += 8
|
||||||
let signature = serializedData[index..<serializedData.count].map { value in
|
|
||||||
return value
|
let key = serializedData[index..<(index + Int(fieldKeyCount))].map { value in
|
||||||
}
|
return value
|
||||||
|
}
|
||||||
|
index += Int(fieldKeyCount)
|
||||||
|
let value = serializedData[index..<(index + Int(fieldValueCount))].map { value in
|
||||||
// Sanity check signature with signatureType
|
return value
|
||||||
if signature.count != signBytes {
|
}
|
||||||
throw DeserializationError.UNMATCHING_SIGNATURE_TYPE
|
index += Int(fieldValueCount)
|
||||||
}
|
|
||||||
|
fields.append(Field(key: key, value: value))
|
||||||
return Message(
|
|
||||||
version: version,
|
}
|
||||||
messageType: messageType,
|
|
||||||
devType: devType,
|
let paddingBytes = (8 - (index % 8)) % 8
|
||||||
RESERVED: RESERVED,
|
|
||||||
signType: signType,
|
// Skip padding bytes
|
||||||
timestamp: timestamp,
|
index += paddingBytes + 8
|
||||||
devID: devID,
|
|
||||||
location: Location(x: locationX, y: locationY, z: locationZ),
|
let signature = serializedData[index..<serializedData.count].map { value in
|
||||||
fields: fields,
|
return value
|
||||||
signature: signature
|
}
|
||||||
)
|
|
||||||
}
|
// Sanity check signature with signatureType
|
||||||
|
if signature.count != signBytes {
|
||||||
public func countBytes(msg: Message) throws -> Int {
|
throw DeserializationError.UNMATCHING_SIGNATURE_TYPE
|
||||||
|
}
|
||||||
///
|
|
||||||
/// Author: Christian Risi
|
return SignedMessage(
|
||||||
///
|
version: version,
|
||||||
/// This is computed as all the bits for the fixed fields
|
messageType: messageType,
|
||||||
///
|
devType: devType,
|
||||||
/// In this case we have:
|
RESERVED: RESERVED,
|
||||||
/// - 4 B --> Generic Info
|
signType: signType,
|
||||||
/// - 4 B --> Timestamp
|
timestamp: timestamp,
|
||||||
/// - 8 B --> Device ID
|
devID: devID,
|
||||||
/// - 12 B --> Device Location
|
location: Location(x: locationX, y: locationY, z: locationZ),
|
||||||
/// - 8 B --> FIELDS STOP
|
fields: fields,
|
||||||
let INITIAL_CAPACITY_BYTES: Int = 36
|
signature: signature
|
||||||
let FIELD_HEADER_CAPACITY_BYTES: Int = 4
|
)
|
||||||
|
}
|
||||||
var fieldReveservedCapacity: Int = 0
|
|
||||||
|
public func countBytes(msg: MessageP) -> Int {
|
||||||
for field in msg.fields {
|
|
||||||
fieldReveservedCapacity += FIELD_HEADER_CAPACITY_BYTES + field.key.count + field.value.count
|
///
|
||||||
}
|
/// Author: Christian Risi
|
||||||
|
///
|
||||||
// UGLY: We are assuming P521 signature
|
/// This is computed as all the bits for the fixed fields
|
||||||
let SIGNATURE_CAPACITY_BYTES: Int = try signatureBytes(signature: msg.signType)
|
///
|
||||||
|
let INITIAL_CAPACITY_BYTES: Int = 56
|
||||||
return (INITIAL_CAPACITY_BYTES + fieldReveservedCapacity + SIGNATURE_CAPACITY_BYTES)
|
let FIELD_HEADER_CAPACITY_BYTES: Int = 8
|
||||||
|
|
||||||
}
|
var fieldReveservedCapacity: Int = 0
|
||||||
|
|
||||||
public func signatureBytes(signature: SignType) throws -> Int {
|
for field in msg.fields {
|
||||||
switch signature {
|
fieldReveservedCapacity += FIELD_HEADER_CAPACITY_BYTES + field.key.count + field.value.count
|
||||||
|
}
|
||||||
case .P521:
|
|
||||||
return 132
|
fieldReveservedCapacity += (8 - (fieldReveservedCapacity % 8)) % 8 + 8
|
||||||
|
|
||||||
default:
|
return INITIAL_CAPACITY_BYTES + fieldReveservedCapacity
|
||||||
throw CommonError.SIGNATURE_NOT_SUPPORTED
|
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
public func signatureBytes(signature: SignType) throws -> Int {
|
||||||
|
switch signature {
|
||||||
|
|
||||||
|
case .P521:
|
||||||
|
return 132
|
||||||
|
|
||||||
|
default:
|
||||||
|
throw CommonError.SIGNATURE_NOT_SUPPORTED
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
@ -1,8 +1,8 @@
|
|||||||
import Foundation
|
import Foundation
|
||||||
|
|
||||||
public struct Field {
|
public struct Field {
|
||||||
|
|
||||||
public let key: [UInt8]
|
public let key: [UInt8]
|
||||||
public let value: [UInt8]
|
public let value: [UInt8]
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,7 +1,7 @@
|
|||||||
public struct Location {
|
public struct Location {
|
||||||
|
|
||||||
public let x: UInt64
|
public let x: UInt64
|
||||||
public let y: UInt64
|
public let y: UInt64
|
||||||
public let z: UInt64
|
public let z: UInt64
|
||||||
|
|
||||||
}
|
}
|
||||||
@ -1,37 +1,71 @@
|
|||||||
import Foundation
|
import Foundation
|
||||||
|
|
||||||
public struct Message{
|
public struct Message : MessageP{
|
||||||
|
|
||||||
public let version: UInt8
|
public let version: UInt8
|
||||||
public let messageType: MessageType
|
public let messageType: MessageType
|
||||||
public let devType: DeviceType
|
public let devType: DeviceType
|
||||||
public let RESERVED: UInt8
|
public let RESERVED: UInt8
|
||||||
public let signType: SignType
|
public let signType: SignType
|
||||||
|
|
||||||
public let timestamp : Date
|
public let timestamp : Date
|
||||||
public let devID : UInt128
|
public let devID : UInt128
|
||||||
public let location: Location
|
public let location: Location
|
||||||
public let fields: [Field]
|
public let fields: [Field]
|
||||||
public let signature: [UInt8]
|
|
||||||
|
|
||||||
|
public func toString() -> String{
|
||||||
public func toString() -> String{
|
var description = ""
|
||||||
var description = ""
|
description += "MESSAGE -------\n"
|
||||||
description += "MESSAGE -------\n"
|
description += "V: \t\(self.version)\n"
|
||||||
description += "V: \t\(self.version)\n"
|
description += "Message Type: \t\(self.messageType.rawValue)\n"
|
||||||
description += "Message Type: \t\(self.messageType.rawValue)\n"
|
description += "Device Type: \t\(self.devType.rawValue)\n"
|
||||||
description += "Device Type: \t\(self.devType.rawValue)\n"
|
description += "RESERVED: \t\(self.RESERVED)\n"
|
||||||
description += "RESERVED: \t\(self.RESERVED)\n"
|
description += "Signature Type: \t\(self.signType.rawValue)\n"
|
||||||
description += "Signature Type: \t\(self.signType.rawValue)\n"
|
description += "Timestamp: \t\(self.timestamp)\n"
|
||||||
description += "Timestamp: \t\(self.timestamp)\n"
|
description += "Device ID: \t\(self.devID)\n"
|
||||||
description += "Device ID: \t\(self.devID)\n"
|
description += "Location: \tX: \(self.location.x)\tY: \(self.location.y)\tZ: \(self.location.z)\n"
|
||||||
description += "Location: \tX: \(self.location.x)\tY: \(self.location.y)\tZ: \(self.location.z)\n"
|
description += "Fields: \n"
|
||||||
description += "Fields: \n"
|
for field in self.fields {
|
||||||
for field in self.fields {
|
description += "\t\(String(data: Data(field.key), encoding: .ascii) ?? "UNABLE TO DECODE"): \(String(data: Data(field.value), encoding: .ascii) ?? "UNABLE TO DECODE")\n"
|
||||||
description += "\t\(String(data: Data(field.key), encoding: .ascii) ?? "UNABLE TO DECODE"): \(String(data: Data(field.value), encoding: .ascii) ?? "UNABLE TO DECODE")"
|
}
|
||||||
}
|
|
||||||
description += "Signature: \t\(self.signature)\n"
|
return description
|
||||||
|
}
|
||||||
return description
|
}
|
||||||
}
|
|
||||||
|
public struct SignedMessage : MessageP {
|
||||||
|
|
||||||
|
public let version: UInt8
|
||||||
|
public let messageType: MessageType
|
||||||
|
public let devType: DeviceType
|
||||||
|
public let RESERVED: UInt8
|
||||||
|
public let signType: SignType
|
||||||
|
|
||||||
|
public let timestamp : Date
|
||||||
|
public let devID : UInt128
|
||||||
|
public let location: Location
|
||||||
|
public let fields: [Field]
|
||||||
|
public let signature: [UInt8]
|
||||||
|
|
||||||
|
|
||||||
|
public func toString() -> String{
|
||||||
|
var description = ""
|
||||||
|
description += "MESSAGE -------\n"
|
||||||
|
description += "V: \t\(self.version)\n"
|
||||||
|
description += "Message Type: \t\(self.messageType.rawValue)\n"
|
||||||
|
description += "Device Type: \t\(self.devType.rawValue)\n"
|
||||||
|
description += "RESERVED: \t\(self.RESERVED)\n"
|
||||||
|
description += "Signature Type: \t\(self.signType.rawValue)\n"
|
||||||
|
description += "Timestamp: \t\(self.timestamp)\n"
|
||||||
|
description += "Device ID: \t\(self.devID)\n"
|
||||||
|
description += "Location: \tX: \(self.location.x)\tY: \(self.location.y)\tZ: \(self.location.z)\n"
|
||||||
|
description += "Fields: \n"
|
||||||
|
for field in self.fields {
|
||||||
|
description += "\t\(String(data: Data(field.key), encoding: .ascii) ?? "UNABLE TO DECODE"): \(String(data: Data(field.value), encoding: .ascii) ?? "UNABLE TO DECODE")\n"
|
||||||
|
}
|
||||||
|
description += "Signature: \t\(self.signature)\n"
|
||||||
|
|
||||||
|
return description
|
||||||
|
}
|
||||||
}
|
}
|
||||||
58
Sources/MessageUtils/Utils/CryptoUtils/Security.swift
Normal file
58
Sources/MessageUtils/Utils/CryptoUtils/Security.swift
Normal file
@ -0,0 +1,58 @@
|
|||||||
|
import Crypto // Equivalent to CryptoKit (more or less)
|
||||||
|
import Foundation
|
||||||
|
|
||||||
|
|
||||||
|
// ------------------
|
||||||
|
// --- Sign ---------
|
||||||
|
// ------------------
|
||||||
|
public func signP521(object: Data, key: P521.Signing.PrivateKey)throws -> Data {
|
||||||
|
return try key.signature<Data>(for: object).rawRepresentation
|
||||||
|
|
||||||
|
}
|
||||||
|
/*
|
||||||
|
public func sign<T>(object: T, key: P521.Signing.PrivateKey) throws -> String {
|
||||||
|
|
||||||
|
var _object = object
|
||||||
|
let data: Data = Data(bytes: &_object, count: MemoryLayout<T>.stride)
|
||||||
|
|
||||||
|
} */
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
// ------------------
|
||||||
|
// --- Decrypt ------
|
||||||
|
// ------------------
|
||||||
|
public func verifySignatureP521(signature: Data, object: Data, key: P521.Signing.PublicKey) throws -> Bool {
|
||||||
|
|
||||||
|
let ecdsa: P521.Signing.ECDSASignature
|
||||||
|
|
||||||
|
do {
|
||||||
|
ecdsa = try P521.Signing.ECDSASignature(rawRepresentation: signature)
|
||||||
|
} catch {
|
||||||
|
throw SecurityError.NotDecodableError
|
||||||
|
}
|
||||||
|
|
||||||
|
return key.isValidSignature<Data>(ecdsa, for: object)
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
// ------------------
|
||||||
|
// --- PEM 2 Key ----
|
||||||
|
// ------------------
|
||||||
|
public func pem2key(filePath: String) throws -> P521.Signing.PrivateKey {
|
||||||
|
|
||||||
|
let pemURL: URL = URL(filePath: filePath)
|
||||||
|
|
||||||
|
return try pem2key(filePem: pemURL)
|
||||||
|
}
|
||||||
|
|
||||||
|
public func pem2key(filePem: URL) throws -> P521.Signing.PrivateKey {
|
||||||
|
|
||||||
|
let fileString: String = try String(contentsOf: filePem, encoding: String.Encoding.utf8)
|
||||||
|
return try pem2key(pemString: fileString)
|
||||||
|
}
|
||||||
|
|
||||||
|
public func pem2key(pemString: String) throws -> P521.Signing.PrivateKey {
|
||||||
|
return try P521.Signing.PrivateKey(pemRepresentation: pemString)
|
||||||
|
}
|
||||||
@ -0,0 +1,4 @@
|
|||||||
|
enum SecurityError: Error {
|
||||||
|
case NotEncodableError
|
||||||
|
case NotDecodableError
|
||||||
|
}
|
||||||
@ -1,5 +1,5 @@
|
|||||||
import Foundation
|
import Foundation
|
||||||
|
|
||||||
public protocol DataCompatibleP {
|
public protocol DataCompatibleP {
|
||||||
var data : Data {get}
|
var data : Data {get}
|
||||||
}
|
}
|
||||||
@ -1,32 +1,32 @@
|
|||||||
import Foundation
|
import Foundation
|
||||||
|
|
||||||
public extension Data {
|
public extension Data {
|
||||||
|
|
||||||
var uint8 : UInt8 {
|
var uint8 : UInt8 {
|
||||||
return self.withUnsafeBytes{ $0.bindMemory(to: UInt8.self) }[0]
|
return self.withUnsafeBytes{ $0.bindMemory(to: UInt8.self) }[0]
|
||||||
}
|
}
|
||||||
|
|
||||||
var uint16: UInt16 {
|
var uint16: UInt16 {
|
||||||
return self.withUnsafeBytes{ $0.bindMemory(to: UInt16.self) }[0]
|
return self.withUnsafeBytes{ $0.bindMemory(to: UInt16.self) }[0]
|
||||||
}
|
}
|
||||||
|
|
||||||
var uint32: UInt32 {
|
var uint32: UInt32 {
|
||||||
return self.withUnsafeBytes{ $0.bindMemory(to: UInt32.self) }[0]
|
return self.withUnsafeBytes{ $0.bindMemory(to: UInt32.self) }[0]
|
||||||
}
|
}
|
||||||
|
|
||||||
var uint64: UInt64 {
|
var uint64: UInt64 {
|
||||||
return self.withUnsafeBytes{ $0.bindMemory(to: UInt64.self) }[0]
|
return self.withUnsafeBytes{ $0.bindMemory(to: UInt64.self) }[0]
|
||||||
}
|
}
|
||||||
|
|
||||||
var uint128: UInt128 {
|
var uint128: UInt128 {
|
||||||
return self.withUnsafeBytes{ $0.bindMemory(to: UInt128.self) }[0]
|
return self.withUnsafeBytes{ $0.bindMemory(to: UInt128.self) }[0]
|
||||||
}
|
}
|
||||||
|
|
||||||
var uint: UInt {
|
var uint: UInt {
|
||||||
return self.withUnsafeBytes{ $0.bindMemory(to: UInt.self) }[0]
|
return self.withUnsafeBytes{ $0.bindMemory(to: UInt.self) }[0]
|
||||||
}
|
}
|
||||||
|
|
||||||
var timestamp: Date {
|
var timestamp: Date {
|
||||||
return self.withUnsafeBytes{ $0.bindMemory(to: Date.self) }[0]
|
return self.withUnsafeBytes{ $0.bindMemory(to: Date.self) }[0]
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -1,52 +1,61 @@
|
|||||||
# Message Structure
|
# Message Structure
|
||||||
```
|
## Possible Improvements
|
||||||
+-+ 64 - bits---+----------------+-------------+----------------+-----------------------+
|
As for now, we are not having a max abount of bytes the message may have,
|
||||||
|0| Version 7 | Message Type 8 | Dev Type 8 | RESERVED 16 | Sign Type 32 |
|
so we are relying on the ability of the receiver to dynamically allocate a buffer for the message.
|
||||||
+-+-------------+----------------+-------------+----------------+-----------------------+
|
|
||||||
| Timestamp 64 |
|
However, we could add a field to tell a PRIORI the length of the whole message.
|
||||||
+---------------------------------------------------------------------------------------+
|
|
||||||
| DevID 128 bits |
|
Probably we would use between 8 B or 24 B to put this info
|
||||||
| |
|
|
||||||
+---------------------------------------------------------------------------------------+
|
(This won't be a 2.0 version, as this is not a final document yet)
|
||||||
| Location 192 bits |
|
```
|
||||||
| |
|
+-+ 64 - bits---+----------------+-------------+----------------+-----------------------+
|
||||||
| |
|
|0| Version 7 | Message Type 8 | Dev Type 8 | RESERVED 16 | Sign Type 32 |
|
||||||
+---------------------------------------------------------------------------------------+
|
+-+-------------+----------------+-------------+----------------+-----------------------+
|
||||||
\ /
|
| Timestamp 64 |
|
||||||
| Fields -----------------------------------------------------------------------------|
|
+---------------------------------------------------------------------------------------+
|
||||||
/ \
|
| DevID 128 bits |
|
||||||
+---------------------------------------------------------------------------------------+
|
| |
|
||||||
| 0 Padding 64 - n |
|
+---------------------------------------------------------------------------------------+
|
||||||
+---------------------------------------------------------------------------------------+
|
| Location 192 bits |
|
||||||
| Signature up to-512 bits |
|
| |
|
||||||
| |
|
| |
|
||||||
| |
|
+---------------------------------------------------------------------------------------+
|
||||||
| |
|
\ /
|
||||||
| |
|
| Fields -----------------------------------------------------------------------------|
|
||||||
| |
|
/ \
|
||||||
| |
|
+---------------------------------------------------------------------------------------+
|
||||||
| |
|
| 0 Padding 64 - n |
|
||||||
+---------------------------------------------------------------------------------------+
|
+---------------------------------------------------------------------------------------+
|
||||||
```
|
| Signature up to-512 bits |
|
||||||
|
| |
|
||||||
# Fields
|
| |
|
||||||
each field can be at most 8 * 2^32 bits of length:
|
| |
|
||||||
- 34359738368 bits
|
| |
|
||||||
- 4294967296 Bytes
|
| |
|
||||||
|
| |
|
||||||
## Key
|
| |
|
||||||
**MUST** be a `String`
|
+---------------------------------------------------------------------------------------+
|
||||||
|
```
|
||||||
## Value
|
|
||||||
It's up to the Application to decide whether the value is
|
# Fields
|
||||||
a string or another type of datum
|
each field can be at most 8 * 2^32 bits of length:
|
||||||
|
- 34359738368 bits
|
||||||
```
|
- 4294967296 Bytes
|
||||||
+-- 64 - bits--------------------------+----------------------------------------+
|
|
||||||
| Key-Length 32 | Value-Length 32 |
|
## Key
|
||||||
+--------------------------------------+----------------------------------------+
|
**MUST** be a `String`
|
||||||
\ Key /
|
|
||||||
|-----------------------------------------------------------------------------|
|
## Value
|
||||||
/ Value \
|
It's up to the Application to decide whether the value is
|
||||||
+-------------------------------------------------------------------------------+
|
a string or another type of datum
|
||||||
|
|
||||||
|
```
|
||||||
|
+-- 64 - bits--------------------------+----------------------------------------+
|
||||||
|
| Key-Length 32 | Value-Length 32 |
|
||||||
|
+--------------------------------------+----------------------------------------+
|
||||||
|
\ Key /
|
||||||
|
|-----------------------------------------------------------------------------|
|
||||||
|
/ Value \
|
||||||
|
+-------------------------------------------------------------------------------+
|
||||||
```
|
```
|
||||||
16
Sources/MessageUtils/Utils/MessageP.swift
Normal file
16
Sources/MessageUtils/Utils/MessageP.swift
Normal file
@ -0,0 +1,16 @@
|
|||||||
|
import Foundation
|
||||||
|
|
||||||
|
public protocol MessageP {
|
||||||
|
var version: UInt8 {get}
|
||||||
|
var messageType: MessageType {get}
|
||||||
|
var devType: DeviceType {get}
|
||||||
|
var RESERVED: UInt8 {get}
|
||||||
|
var signType: SignType {get}
|
||||||
|
|
||||||
|
var timestamp: Date {get}
|
||||||
|
var devID: UInt128 {get}
|
||||||
|
var location: Location {get}
|
||||||
|
var fields: [Field] {get}
|
||||||
|
|
||||||
|
func toString() -> String
|
||||||
|
}
|
||||||
@ -1,43 +1,43 @@
|
|||||||
import Foundation
|
import Foundation
|
||||||
|
|
||||||
extension UInt8: DataCompatibleP {
|
extension UInt8: DataCompatibleP {
|
||||||
public var data: Data {
|
public var data: Data {
|
||||||
var obj = self
|
var obj = self
|
||||||
return Data(bytes: &obj, count: MemoryLayout<Self>.stride)
|
return Data(bytes: &obj, count: MemoryLayout<Self>.stride)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
extension UInt16: DataCompatibleP {
|
extension UInt16: DataCompatibleP {
|
||||||
public var data: Data {
|
public var data: Data {
|
||||||
var obj = self
|
var obj = self
|
||||||
return Data(bytes: &obj, count: MemoryLayout<Self>.stride)
|
return Data(bytes: &obj, count: MemoryLayout<Self>.stride)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
extension UInt32: DataCompatibleP {
|
extension UInt32: DataCompatibleP {
|
||||||
public var data: Data {
|
public var data: Data {
|
||||||
var obj = self
|
var obj = self
|
||||||
return Data(bytes: &obj, count: MemoryLayout<Self>.stride)
|
return Data(bytes: &obj, count: MemoryLayout<Self>.stride)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
extension UInt64: DataCompatibleP {
|
extension UInt64: DataCompatibleP {
|
||||||
public var data: Data {
|
public var data: Data {
|
||||||
var obj = self
|
var obj = self
|
||||||
return Data(bytes: &obj, count: MemoryLayout<Self>.stride)
|
return Data(bytes: &obj, count: MemoryLayout<Self>.stride)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
extension UInt128: DataCompatibleP {
|
extension UInt128: DataCompatibleP {
|
||||||
public var data: Data {
|
public var data: Data {
|
||||||
var obj = self
|
var obj = self
|
||||||
return Data(bytes: &obj, count: MemoryLayout<Self>.stride)
|
return Data(bytes: &obj, count: MemoryLayout<Self>.stride)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
extension Date: DataCompatibleP {
|
extension Date: DataCompatibleP {
|
||||||
public var data: Data {
|
public var data: Data {
|
||||||
var obj = self
|
var obj = self
|
||||||
return Data(bytes: &obj, count: MemoryLayout<Self>.stride)
|
return Data(bytes: &obj, count: MemoryLayout<Self>.stride)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,87 +1,120 @@
|
|||||||
import Foundation
|
import Foundation
|
||||||
|
|
||||||
import Testing
|
import Testing
|
||||||
@testable import MessageUtils
|
|
||||||
|
@testable import MessageUtils
|
||||||
|
|
||||||
|
@Test func serializeMessage() async throws {
|
||||||
@Test func serializeMessage() async throws {
|
// Write your test here and use APIs like `#expect(...)` to check expected conditions.
|
||||||
// Write your test here and use APIs like `#expect(...)` to check expected conditions.
|
let msg = SignedMessage(
|
||||||
let msg = Message(
|
version: 1,
|
||||||
version: 1,
|
messageType: .KEEPALIVE,
|
||||||
messageType: .KEEPALIVE,
|
devType: .EDGE_SENSOR,
|
||||||
devType: .EDGE_SENSOR,
|
RESERVED: 0,
|
||||||
RESERVED: 0,
|
signType: .P521,
|
||||||
signType: .P521,
|
timestamp: Date(),
|
||||||
timestamp: Date(),
|
devID: 1,
|
||||||
devID: 1,
|
location: Location(x: 10, y: 20, z: 1),
|
||||||
location: Location(x: 10,y: 20,z: 1),
|
fields: [],
|
||||||
fields: [],
|
signature: Array(repeating: 255, count: 132)
|
||||||
signature: Array(repeating: 255, count: 132)
|
)
|
||||||
)
|
|
||||||
|
let data = try serializeV1(msg: msg)
|
||||||
let data = try serializeV1(msg: msg)
|
|
||||||
|
}
|
||||||
}
|
@Test func serializeMessageWithField() async throws {
|
||||||
|
// Write your test here and use APIs like `#expect(...)` to check expected conditions.
|
||||||
|
let msg = Message(
|
||||||
@Test func serializeMessageWithField() async throws {
|
version: 1,
|
||||||
// Write your test here and use APIs like `#expect(...)` to check expected conditions.
|
messageType: .KEEPALIVE,
|
||||||
let msg = Message(
|
devType: .EDGE_SENSOR,
|
||||||
version: 1,
|
RESERVED: 0,
|
||||||
messageType: .KEEPALIVE,
|
signType: .P521,
|
||||||
devType: .EDGE_SENSOR,
|
timestamp: Date(),
|
||||||
RESERVED: 0,
|
devID: 1,
|
||||||
signType: .P521,
|
location: Location(x: 10, y: 20, z: 1),
|
||||||
timestamp: Date(),
|
fields: [
|
||||||
devID: 1,
|
Field(key: Array("valueOfLife".utf8), value: Array("42".utf8)),
|
||||||
location: Location(x: 10,y: 20,z: 1),
|
Field(key: Array("valueOfLife".utf8), value: Array("42".utf8)),
|
||||||
fields: [
|
]
|
||||||
Field(key: Array("valueOfLife".utf8), value: Array("42".utf8)),
|
)
|
||||||
Field(key: Array("valueOfLife".utf8), value: Array("42".utf8))
|
|
||||||
],
|
let data = try serializeV1(msg: msg)
|
||||||
signature: Array(repeating: 255, count: 132)
|
|
||||||
)
|
}
|
||||||
|
@Test func serializeDeserializeMessage() async throws {
|
||||||
let data = try serializeV1(msg: msg)
|
let keyPath = "./Private/privateKey.pem"
|
||||||
|
let key = try pem2key(filePath: keyPath)
|
||||||
}
|
let publicKey = key.publicKey
|
||||||
|
|
||||||
@Test func serializeDeserializeMessage() async throws {
|
// Write your test here and use APIs like `#expect(...)` to check expected conditions.
|
||||||
// Write your test here and use APIs like `#expect(...)` to check expected conditions.
|
let msg = Message(
|
||||||
let msg = Message(
|
version: 1,
|
||||||
version: 1,
|
messageType: .KEEPALIVE,
|
||||||
messageType: .KEEPALIVE,
|
devType: .EDGE_SENSOR,
|
||||||
devType: .EDGE_SENSOR,
|
RESERVED: 0,
|
||||||
RESERVED: 0,
|
signType: .P521,
|
||||||
signType: .P521,
|
timestamp: Date(),
|
||||||
timestamp: Date(),
|
devID: 1,
|
||||||
devID: 1,
|
location: Location(x: 10, y: 20, z: 1),
|
||||||
location: Location(x: 10,y: 20,z: 1),
|
fields: [
|
||||||
fields: [
|
Field(key: Array("valueOfLife".utf8), value: Array("42".utf8)),
|
||||||
Field(key: Array("valueOfLife".utf8), value: Array("42".utf8)),
|
Field(key: Array("valueOfLife".utf8), value: Array("42".utf8)),
|
||||||
Field(key: Array("valueOfLife".utf8), value: Array("42".utf8))
|
Field(key: Array("69".utf8), value: Array("Nice".utf8)),
|
||||||
],
|
Field(key: Array("valueOfLife".utf8), value: Array("42".utf8)),
|
||||||
signature: Array(repeating: 255, count: 132)
|
Field(key: Array("Live Love".utf8), value: Array("Laugh".utf8)),
|
||||||
)
|
]
|
||||||
|
)
|
||||||
print(msg.toString())
|
|
||||||
|
print(msg.toString())
|
||||||
let data = try serializeV1(msg: msg)
|
|
||||||
|
var data = serializeV1(msg: msg)
|
||||||
let bytes = data.map { value in
|
|
||||||
return value
|
let bytes = data.map { value in
|
||||||
}
|
return value
|
||||||
|
}
|
||||||
|
|
||||||
|
let actualBytes = countBytes(msg: msg)
|
||||||
print(bytes.count % 8 == 0)
|
|
||||||
|
print("Number of Bytes for the message: \(bytes.count)")
|
||||||
|
print("Number of Computed Bytes: \(actualBytes)")
|
||||||
let msg2 = try derializeV1(serializedData: data)
|
|
||||||
print(msg2.toString())
|
let signature = try signMessage(msgData: data, signType: msg.signType, key: key)
|
||||||
|
data.append(contentsOf: signature)
|
||||||
|
|
||||||
}
|
let msg2 = try deserializeV1(serializedData: data)
|
||||||
|
let authenticMessage = try verifyMessageSignature(message: msg2, key: publicKey)
|
||||||
|
|
||||||
|
#expect(authenticMessage, "If this is not true, then we are doing some deserialization errors")
|
||||||
|
print(msg2.toString())
|
||||||
|
|
||||||
|
}
|
||||||
|
@Test func serializeMessageForLaterUse() async throws {
|
||||||
|
// Write your test here and use APIs like `#expect(...)` to check expected conditions.
|
||||||
|
|
||||||
|
let keyPath = "./Private/privateKey.pem"
|
||||||
|
let key = try pem2key(filePath: keyPath)
|
||||||
|
|
||||||
|
let msg = Message(
|
||||||
|
version: 1,
|
||||||
|
messageType: .KEEPALIVE,
|
||||||
|
devType: .EDGE_SENSOR,
|
||||||
|
RESERVED: 0,
|
||||||
|
signType: .P521,
|
||||||
|
timestamp: Date(),
|
||||||
|
devID: 1,
|
||||||
|
location: Location(x: 10, y: 20, z: 1),
|
||||||
|
fields: [
|
||||||
|
Field(key: Array("valueOfLife".utf8), value: Array("42".utf8)),
|
||||||
|
Field(key: Array("Live Love".utf8), value: Array("Laugh".utf8)),
|
||||||
|
]
|
||||||
|
)
|
||||||
|
|
||||||
|
var data = try serializeV1(msg: msg)
|
||||||
|
|
||||||
|
let signature = try signMessage(msgData: data, signType: msg.signType, key: key)
|
||||||
|
data.append(Data(signature))
|
||||||
|
|
||||||
|
try data.write(to: URL(filePath: "./Private/signedMessage/Message.bin"))
|
||||||
|
|
||||||
|
}
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user