Added initial support for signature

This commit is contained in:
Christian Risi 2024-12-02 19:15:12 +01:00
parent 44d6d9a84f
commit 0eb4c0069e
16 changed files with 285 additions and 8 deletions

View File

@ -9,7 +9,9 @@
"customizations": {
"vscode": {
"extensions": [
"sswg.swift-lang"
"sswg.swift-lang",
"fabiospampinato.vscode-highlight",
"fabiospampinato.vscode-todo-plus"
]
}
},

24
Package.resolved Normal file
View File

@ -0,0 +1,24 @@
{
"originHash" : "a49eafc65c63e9300677cadad384d86aab484d1c10a415ec467d840aff87c075",
"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
}

View File

@ -10,20 +10,29 @@ let package = Package(
.library(
name: "IoT-Simulator-Core",
targets: ["IoT-Simulator-Core"]
),
.library(name: "RandomCpp", targets: ["RandomCpp"])
),
.library(
name: "RandomCpp",
targets: ["RandomCpp"]
),
],
dependencies: [],
dependencies: [
.package(url: "https://github.com/apple/swift-crypto.git", branch: "main"),
],
targets: [
// Targets are the basic building blocks of a package, defining a module or a test suite.
// Targets can depend on other targets in this package and products from dependencies.
.target(
name: "RandomCpp"
),
.target(
name: "IoT-Simulator-Core",
dependencies: [
"RandomCpp",
.product(name: "Crypto", package: "swift-crypto"),
],
swiftSettings: [
.interoperabilityMode(.Cxx)

16
Private/cert.pem Normal file
View 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
View 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-----

View 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-----

View File

@ -0,0 +1,2 @@
openssl ecparam -name secp521r1 -genkey -noout -out privateKey.pem
openssl req -x509 -sha256 -key privateKey.pem -out cert.pem -nodes

View File

@ -0,0 +1,73 @@
/* public class EdgeDevice : EdgeDeviceP {
public let deviceID: String
public let deviceType: DeviceType
public let dataType: DataType
public var disconnected: Bool
public var compromised: Bool
public var dutyCicle: UInt
public var sensors: [Int: Sensor]
public var privateKey: [UInt8]
private var numberOfSensors: Int {
get{
return sensors.count
}
}
public init(
deviceID: String,
dataType: DataType,
disconnected: Bool,
dutyCicle: UInt,
sensors: [Int: Sensor]
) {
self.deviceID = deviceID
self.deviceType = DeviceType.EdgeDevice
self.dataType = dataType
self.disconnected = disconnected
self.compromised = false
self.dutyCicle = dutyCicle
self.sensors = sensors
}
public func addSensor(sensor: Sensor) {
self.sensors[numberOfSensors + 1] = sensor
}
public func removeSensor(id: Int) {
self.sensors.removeValue(forKey: id)
}
public func work(envrionment: PhysicalEnvironment) {
// UGLY: In case I have some optimization problems, fix here
var values: [Float] = []
for sensor in sensors {
values.append(
sensor.value.read(envrionment).value
)
}
// Todo: START Remove this and Add Vincenzo's implementation
let avg : Float = meanValue(values: values)
let std_dev : Float = standardDeviation(values: values)
// Todo: END Add Vincenzo's implementation
return Message(
msgType: MessageType,
timestamp: Date,
deviceID: String,
location: Location3D,
fields: [Field],
signature: [UInt8]
)
}
} */

View File

@ -59,6 +59,7 @@ public class RealSensor: Sensor {
private var _meanNoise: Float
private var _stdNoise: Float
private let _quantizationBits: Int
// TODO: add a generator of GaussianRNG
//private var gaussianNoise:
public init(
@ -90,7 +91,7 @@ public class RealSensor: Sensor {
override public func read(_ environment: PhysicalEnvironment) -> PhysicalData {
let value: PhysicalData = super.read(environment)
// TODO Add gaussian error here
return value
}

View File

@ -1,3 +1,4 @@
public class Field {
public let key: String

View File

@ -0,0 +1,4 @@
enum SecurityError: Error {
case NotEncodableError
case NotDecodableError
}

View File

@ -1,11 +1,13 @@
public protocol EdgeDevice {
public protocol EdgeDeviceP {
var deviceID : String {get}
var deviceType : DeviceType {get}
var dataType : DataType {get}
var disconnected : Bool {get set}
var compromised : Bool {get set}
var dutyCicle : UInt {get set}
var privateKey: [UInt8] {get}
func work() -> Message
func work(envrionment: PhysicalEnvironment) -> Message
}

View File

@ -0,0 +1,55 @@
import Crypto // Equivalent to CryptoKit (more or less)
import Foundation
// ------------------
// --- Sign ---------
// ------------------
public func sign(string: String, key: P521.Signing.PrivateKey) throws -> String {
let data = Data(string.utf8)
return try key.signature<Data>(for: data).rawRepresentation
}
// ------------------
// --- Decrypt ------
// ------------------
public func verify(signature: String, string: String, key: P521.Signing.PublicKey) throws -> Bool {
let data = Data(string.utf8)
let ecdsa: P521.Signing.ECDSASignature
do {
let bytes = ecdsa
ecdsa = try P521.Signing.ECDSASignature(rawRepresentation: signature)
} catch {
throw SecurityError.NotDecodableError
}
return key.isValidSignature<Data>(ecdsa, for: data)
}
// ------------------
// --- 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)
}

View File

@ -0,0 +1,28 @@
import Foundation
public func meanValue<Numerical: FloatingPoint>(values: [Numerical]) -> Numerical{
var avg : Numerical = 0
for i in 0..<values.count {
avg += values[i]
}
return avg / Numerical(values.count)
}
// UGLY Find a way to implement power protocol, if issues with optimization
public func standardDeviation<Numerical: FloatingPoint>(values: [Numerical]) -> Numerical{
let avg : Numerical = meanValue(values: values)
var summatory: Numerical = 0
for i in 0..<values.count {
let intermediate = (values[i] - avg)
summatory += (intermediate * intermediate)
}
return sqrt(
summatory / Numerical(values.count)
)
}

View File

@ -1,9 +1,11 @@
import Testing
import RandomCpp
import Foundation
import SwiftASN1
@testable import IoT_Simulator_Core
@Test func example() async throws {
@Test func workingGeneratorTest() async throws {
// Write your test here and use APIs like `#expect(...)` to check expected conditions.
var a = GaussianRNG(10, 0.5)
@ -11,3 +13,46 @@ import RandomCpp
print(a.generate())
}
}
@Test func pemDecoded() async throws {
/*
Even though here you would expect both texts to be equal,
the openssl generated one (the raw string) is ANSI x9.62
while ours (the one made with the library) is ASN.1
When inspected with openssl, both curves where identical,
so no need to be worried
*/
let keyPath = "./Private/privateKey.pem"
let url = URL(filePath: keyPath)
let pemString = try String(contentsOf: url, encoding: String.Encoding.utf8)
let key = try pem2key(filePath: keyPath)
print(pemString)
print(key.pemRepresentation)
}
@Test func sign() async throws {
let keyPath = "./Private/privateKey.pem"
let key = try pem2key(filePath: keyPath)
let obj = [1, 2, 3]
let signature = try sign(object: obj, key: key)
}
@Test func verifySignature() async throws {
let keyPath = "./Private/privateKey.pem"
let key = try pem2key(filePath: keyPath)
let obj = "[1, 2, 3]"
let signature = try sign(object: obj, key: key)
}