diff --git a/Cargo.toml b/Cargo.toml index c6d525e..8bad12b 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -4,19 +4,10 @@ members = [ "signer", "broker", "parser", - "auther", "tester", ] exclude = [ "sphinx-key", - "crypter", - "crypter-ffi", "persister", ] - -[patch.crates-io] -# updates the "rand" create to use esp RNG -getrandom = { version = "0.2", git = "https://github.com/esp-rs-compat/getrandom.git" } -secp256k1 = { git = "https://github.com/Evanfeenstra/rust-secp256k1", branch = "v0.22.0-new-rand" } -lightning = { git = "https://github.com/Evanfeenstra/rust-lightning", branch = "v0.0.108-branch" } diff --git a/auther/Cargo.toml b/auther/Cargo.toml deleted file mode 100644 index 224546b..0000000 --- a/auther/Cargo.toml +++ /dev/null @@ -1,18 +0,0 @@ -[package] -name = "sphinx-key-auther" -version = "0.1.0" -authors = ["Evan Feenstra "] -edition = "2018" - -[dependencies] -secp256k1 = { version = "0.22.0", default-features = false, features = ["std", "rand-std", "bitcoin_hashes"] } -anyhow = {version = "1", features = ["backtrace"]} -log = "0.4" -base64 = { version = "0.13.0" } - -[features] -default = [ "no-std", "secp-recovery", "secp-lowmemory" ] -no-std = ["secp256k1/alloc"] -secp-lowmemory = ["secp256k1/lowmemory"] -secp-recovery = ["secp256k1/recovery"] -rand = ["secp256k1/rand-std"] \ No newline at end of file diff --git a/auther/src/lib.rs b/auther/src/lib.rs deleted file mode 100644 index 650590a..0000000 --- a/auther/src/lib.rs +++ /dev/null @@ -1,161 +0,0 @@ -use anyhow::anyhow; -use anyhow::Result; -use base64::{decode_config, encode_config, URL_SAFE}; -use secp256k1::ecdsa::Signature; -use secp256k1::hashes::sha256d::Hash as Sha256dHash; -use secp256k1::hashes::Hash; -use secp256k1::{Message, PublicKey, Secp256k1, SecretKey}; -use std::convert::TryInto; - -pub struct Token(u64); - -fn now() -> u64 { - use std::time::{SystemTime, UNIX_EPOCH}; - let start = SystemTime::now(); - let since_the_epoch = start - .duration_since(UNIX_EPOCH) - .expect("Time went backwards"); - since_the_epoch.as_nanos() as u64 -} - -pub fn u64_to_bytes(input: u64) -> [u8; 8] { - input.to_le_bytes() -} -pub fn bytes_to_u64(bytes: [u8; 8]) -> u64 { - u64::from_le_bytes(bytes) -} - -pub fn base64_encode(input: &Vec) -> String { - encode_config(input, URL_SAFE) -} -pub fn base64_decode(input: &str) -> Result> { - let r = decode_config(input, URL_SAFE)?; - Ok(r) -} - -impl Token { - pub fn new() -> Self { - Self(now()) - } - pub fn from_bytes(bytes: [u8; 8]) -> Self { - Self(bytes_to_u64(bytes)) - } - pub fn from_base64(s: &str) -> Result { - if s.len() < 8 { - return Err(anyhow!("too short slice".to_string())); - } - let bytes = base64_decode(s)?; - let ts: [u8; 8] = bytes[..8].try_into()?; - Ok(Self(bytes_to_u64(ts))) - } - pub fn expected_len(&self) -> usize { - 73 - } - pub fn sign(&self, secret_key: &SecretKey) -> Result> { - let mut ts = u64_to_bytes(self.0).to_vec(); - let sig = self.sign_message(&ts, secret_key)?; - println!("tts {:?}", ts); - ts.extend(sig); - assert_eq!(ts.len(), self.expected_len()); - Ok(ts) - } - pub fn verify(&self, sig: Vec, public_key: &PublicKey) -> Result<()> { - // remove ts - // let (msg, sig) = input.split_at(8); - let msg = u64_to_bytes(self.0); - self.verify_message(&msg.to_vec(), &sig.to_vec(), public_key) - } - /// Sign a Lightning message - pub fn sign_message(&self, message: &Vec, secret_key: &SecretKey) -> Result> { - let encmsg = self.lightning_hash(message)?; - let secp_ctx = Secp256k1::signing_only(); - let sig = secp_ctx.sign_ecdsa_recoverable(&encmsg, &secret_key); - let (rid, sig) = sig.serialize_compact(); - let mut res = sig.to_vec(); - res.push(rid.to_i32() as u8); - Ok(res) - } - /// Verify a Lightning message - pub fn verify_message( - &self, - message: &Vec, - sig: &Vec, - public_key: &PublicKey, - ) -> Result<()> { - let secp_ctx = Secp256k1::verification_only(); - let encmsg = self.lightning_hash(message)?; - // remove the rid - let s = Signature::from_compact(&sig[..64])?; - secp_ctx.verify_ecdsa(&encmsg, &s, public_key)?; - Ok(()) - } - /// hash lightning message - pub fn lightning_hash(&self, message: &Vec) -> Result { - let mut buffer = String::from("Lightning Signed Message:").into_bytes(); - buffer.extend(message); - let hash = Sha256dHash::hash(&buffer); - let encmsg = secp256k1::Message::from_slice(&hash[..])?; - Ok(encmsg) - } -} - -pub fn sign( - secp: &Secp256k1, - input: Vec, - secret_key: &SecretKey, -) -> Signature { - let message = hash_message(input); - secp.sign_ecdsa(&message, &secret_key) -} - -pub fn hash_message(input: Vec) -> Message { - let hash = Sha256dHash::hash(&input); - Message::from_slice(&hash[..]).expect("encmsg failed") -} - -#[cfg(test)] -mod tests { - use crate::*; - use secp256k1::{PublicKey, Secp256k1, SecretKey}; - - fn secret_key() -> SecretKey { - SecretKey::from_slice(&[0xcd; 32]).expect("32 bytes, within curve order") - } - - #[test] - fn test_sign() { - let secp = Secp256k1::new(); - let sk = secret_key(); - let public_key = PublicKey::from_secret_key(&secp, &sk); - let input = vec![1, 2, 3]; - let message = hash_message(input); - let sig = sign(&secp, vec![1, 2, 3], &sk); - assert!(secp.verify_ecdsa(&message, &sig, &public_key).is_ok()); - } - - #[test] - fn test_token() { - let sk = secret_key(); - let t = Token::new(); - let res = t.sign(&sk).expect("couldnt make token"); - let secp = Secp256k1::new(); - let public_key = PublicKey::from_secret_key(&secp, &sk); - let (_, sig) = res.split_at(8); - t.verify(sig.to_vec(), &public_key).expect("couldnt verify"); - println!("token verified!"); - } - - #[test] - fn test_decode() { - let sk = secret_key(); - let secp = Secp256k1::new(); - let public_key = PublicKey::from_secret_key(&secp, &sk); - let s = "aHt45kxY9xZCMvT5du5mTw-jx3X2g0Eg7QhHTIi6rBRAFqY_syx1SzcSoriXyPIVCWdG6T0I8xKXSEnoeajFdwmtQbHqC_qfAQ=="; - let v = base64_decode(s).expect("couldnt decode"); - let (_, sig) = v.split_at(8); - let t = Token::from_base64(s).expect("couldnt parse base64"); - t.verify(sig.to_vec(), &public_key) - .expect("failed to verify"); - println!("decoded token verified!"); - } -} diff --git a/broker/Cargo.toml b/broker/Cargo.toml index 826a5f7..2f8618d 100644 --- a/broker/Cargo.toml +++ b/broker/Cargo.toml @@ -6,16 +6,16 @@ default-run = "sphinx-key-broker" # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html [dependencies] -vls-protocol = { git = "https://gitlab.com/Evanfeenstra/validating-lightning-signer", branch = "sphinx-key-1.2" } -vls-proxy = { git = "https://gitlab.com/Evanfeenstra/validating-lightning-signer", branch = "sphinx-key-1.2" } -vls-frontend = { git = "https://gitlab.com/Evanfeenstra/validating-lightning-signer", branch = "sphinx-key-1.2" } -vls-protocol-client = { git = "https://gitlab.com/Evanfeenstra/validating-lightning-signer", branch = "sphinx-key-1.2" } +vls-protocol = { git = "https://gitlab.com/lightning-signer/validating-lightning-signer.git" } +vls-proxy = { git = "https://gitlab.com/lightning-signer/validating-lightning-signer.git" } +vls-frontend = { git = "https://gitlab.com/lightning-signer/validating-lightning-signer.git" } +vls-protocol-client = { git = "https://gitlab.com/lightning-signer/validating-lightning-signer.git" } rumqttd = { git = "https://github.com/Evanfeenstra/rumqtt", branch = "metrics" } pretty_env_logger = "0.4.0" confy = "0.4.0" tokio = { version = "1.4.0", features = ["rt", "rt-multi-thread", "macros"] } sphinx-key-parser = { path = "../parser" } -secp256k1 = { version = "0.20", features = ["rand-std", "bitcoin_hashes"] } +secp256k1 = { version = "0.24.0", features = ["rand-std", "bitcoin_hashes"] } anyhow = {version = "1", features = ["backtrace"]} log = "0.4" fern = { version = "0.6", features = ["colored"] } @@ -24,7 +24,7 @@ clap = "=3.0.0-beta.2" clap_derive = "=3.0.0-beta.5" chrono = "0.4" once_cell = "1.12.0" -bitcoin = "0.28.1" +bitcoin = "0.29.0" async-trait = "0.1" url = { version = "2.2" } diff --git a/crypter-ffi/.gitignore b/crypter-ffi/.gitignore deleted file mode 100644 index c05ac99..0000000 --- a/crypter-ffi/.gitignore +++ /dev/null @@ -1,2 +0,0 @@ -notes.md -src/crypter.uniffi.rs \ No newline at end of file diff --git a/crypter-ffi/Cargo.toml b/crypter-ffi/Cargo.toml deleted file mode 100644 index b7f4000..0000000 --- a/crypter-ffi/Cargo.toml +++ /dev/null @@ -1,31 +0,0 @@ -[package] -name = "crypter-ffi" -version = "0.1.0" -authors = ["Evan Feenstra "] -edition = "2018" - -[lib] -name = "crypter" -crate-type = ["staticlib", "cdylib"] - -[dependencies] -sphinx-key-crypter = { path = "../crypter" } -uniffi = "0.19.2" -hex = "0.4.3" -thiserror = "1.0.31" - -[build-dependencies] -uniffi_build = "0.19.2" - -[profile.release] -opt-level = 'z' # Optimize for size. -lto = true # Enable Link Time Optimization -codegen-units = 1 # Reduce number of codegen units to increase optimizations. -# panic = 'abort' # Abort on panic -debug = true # Enable debug symbols. For example, we can use `dwarfdump` to check crash traces. - -[patch.crates-io] -getrandom = { version = "0.2", git = "https://github.com/esp-rs-compat/getrandom.git" } -secp256k1 = { git = "https://github.com/Evanfeenstra/rust-secp256k1", branch = "v0.22.0-new-rand" } -lightning = { git = "https://github.com/Evanfeenstra/rust-lightning", branch = "v0.0.108-branch" } - diff --git a/crypter-ffi/build-kotlin.sh b/crypter-ffi/build-kotlin.sh deleted file mode 100755 index f342d91..0000000 --- a/crypter-ffi/build-kotlin.sh +++ /dev/null @@ -1,38 +0,0 @@ -echo "=> creating C FFI scaffolding" -uniffi-bindgen scaffolding src/crypter.udl - -echo "=> creating kotlin bindings" -uniffi-bindgen generate src/crypter.udl --language kotlin - -echo "=> renaming uniffi_crypter to crypter" -sed -i '' 's/return "uniffi_crypter"/return "crypter"/' src/uniffi/crypter/crypter.kt - -echo "=> building i686-linux-android" -cross build --target i686-linux-android --release -echo "=> building aarch64-linux-android" -cross build --target aarch64-linux-android --release -echo "=> building arm-linux-androideabi" -cross build --target arm-linux-androideabi --release -echo "=> building armv7-linux-androideabi" -cross build --target armv7-linux-androideabi --release -echo "=> building x86_64-linux-android" -cross build --target x86_64-linux-android --release - -echo "=> renaming files" - -mkdir -p target/out -mkdir -p target/out/x86 -mkdir -p target/out/arm64-v8a -mkdir -p target/out/armeabi -mkdir -p target/out/armeabi-v7a -mkdir -p target/out/x86_64 - -mv target/i686-linux-android/release/libcrypter.so target/out/x86/libcrypter.so -mv target/aarch64-linux-android/release/libcrypter.so target/out/arm64-v8a/libcrypter.so -mv target/arm-linux-androideabi/release/libcrypter.so target/out/armeabi/libcrypter.so -mv target/armv7-linux-androideabi/release/libcrypter.so target/out/armeabi-v7a/libcrypter.so -mv target/x86_64-linux-android/release/libcrypter.so target/out/x86_64/libcrypter.so - -zip -r target/kotlin-libraries.zip target/out - -echo "=> done!" diff --git a/crypter-ffi/build-swift.sh b/crypter-ffi/build-swift.sh deleted file mode 100755 index 3a4f653..0000000 --- a/crypter-ffi/build-swift.sh +++ /dev/null @@ -1,18 +0,0 @@ -echo "=> creating C FFI scaffolding" -uniffi-bindgen scaffolding src/crypter.udl - -echo "=> creating swift bindings" -uniffi-bindgen generate src/crypter.udl --language swift - -echo "=> creating swift bindings" -sed -i '' 's/module\ crypterFFI/framework\ module\ crypterFFI/' src/crypterFFI.modulemap - -echo "=> building x86_64-apple-ios" -cross build --target=x86_64-apple-ios --release -echo "=> building aarch64-apple-ios" -cross build --target=aarch64-apple-ios --release - -echo "=> combining into a universal lib" -lipo -create target/x86_64-apple-ios/release/libcrypter.a target/aarch64-apple-ios/release/libcrypter.a -output target/universal-crypter.a - -echo "=> done!" diff --git a/crypter-ffi/readme.md b/crypter-ffi/readme.md deleted file mode 100644 index fa4c784..0000000 --- a/crypter-ffi/readme.md +++ /dev/null @@ -1,23 +0,0 @@ -uniffi-bindgen --version - -should match the uniffi version in Cargo.toml - -### build the C ffi - -uniffi-bindgen scaffolding src/crypter.udl - -### kotlin - -rustup target add aarch64-linux-android armv7-linux-androideabi i686-linux-android x86_64-linux-android arm-linux-androideabi - -./build-kotlin.sh - -### swift - -rustup target add aarch64-apple-ios x86_64-apple-ios - -armv7-apple-ios -armv7s-apple-ios -i386-apple-ios - -./build-swift.sh diff --git a/crypter-ffi/src/crypter.swift b/crypter-ffi/src/crypter.swift deleted file mode 100644 index a7fbd98..0000000 --- a/crypter-ffi/src/crypter.swift +++ /dev/null @@ -1,512 +0,0 @@ -// This file was autogenerated by some hot garbage in the `uniffi` crate. -// Trust me, you don't want to mess with it! -import Foundation - -// Depending on the consumer's build setup, the low-level FFI code -// might be in a separate module, or it might be compiled inline into -// this module. This is a bit of light hackery to work with both. -#if canImport(crypterFFI) -import crypterFFI -#endif - -fileprivate extension RustBuffer { - // Allocate a new buffer, copying the contents of a `UInt8` array. - init(bytes: [UInt8]) { - let rbuf = bytes.withUnsafeBufferPointer { ptr in - RustBuffer.from(ptr) - } - self.init(capacity: rbuf.capacity, len: rbuf.len, data: rbuf.data) - } - - static func from(_ ptr: UnsafeBufferPointer) -> RustBuffer { - try! rustCall { ffi_crypter_9c38_rustbuffer_from_bytes(ForeignBytes(bufferPointer: ptr), $0) } - } - - // Frees the buffer in place. - // The buffer must not be used after this is called. - func deallocate() { - try! rustCall { ffi_crypter_9c38_rustbuffer_free(self, $0) } - } -} - -fileprivate extension ForeignBytes { - init(bufferPointer: UnsafeBufferPointer) { - self.init(len: Int32(bufferPointer.count), data: bufferPointer.baseAddress) - } -} - -// For every type used in the interface, we provide helper methods for conveniently -// lifting and lowering that type from C-compatible data, and for reading and writing -// values of that type in a buffer. - -// Helper classes/extensions that don't change. -// Someday, this will be in a libray of its own. - -fileprivate extension Data { - init(rustBuffer: RustBuffer) { - // TODO: This copies the buffer. Can we read directly from a - // Rust buffer? - self.init(bytes: rustBuffer.data!, count: Int(rustBuffer.len)) - } -} - -// A helper class to read values out of a byte buffer. -fileprivate class Reader { - let data: Data - var offset: Data.Index - - init(data: Data) { - self.data = data - self.offset = 0 - } - - // Reads an integer at the current offset, in big-endian order, and advances - // the offset on success. Throws if reading the integer would move the - // offset past the end of the buffer. - func readInt() throws -> T { - let range = offset...size - guard data.count >= range.upperBound else { - throw UniffiInternalError.bufferOverflow - } - if T.self == UInt8.self { - let value = data[offset] - offset += 1 - return value as! T - } - var value: T = 0 - let _ = withUnsafeMutableBytes(of: &value, { data.copyBytes(to: $0, from: range)}) - offset = range.upperBound - return value.bigEndian - } - - // Reads an arbitrary number of bytes, to be used to read - // raw bytes, this is useful when lifting strings - func readBytes(count: Int) throws -> Array { - let range = offset..<(offset+count) - guard data.count >= range.upperBound else { - throw UniffiInternalError.bufferOverflow - } - var value = [UInt8](repeating: 0, count: count) - value.withUnsafeMutableBufferPointer({ buffer in - data.copyBytes(to: buffer, from: range) - }) - offset = range.upperBound - return value - } - - // Reads a float at the current offset. - @inlinable - func readFloat() throws -> Float { - return Float(bitPattern: try readInt()) - } - - // Reads a float at the current offset. - @inlinable - func readDouble() throws -> Double { - return Double(bitPattern: try readInt()) - } - - // Indicates if the offset has reached the end of the buffer. - @inlinable - func hasRemaining() -> Bool { - return offset < data.count - } -} - -// A helper class to write values into a byte buffer. -fileprivate class Writer { - var bytes: [UInt8] - var offset: Array.Index - - init() { - self.bytes = [] - self.offset = 0 - } - - func writeBytes(_ byteArr: S) where S: Sequence, S.Element == UInt8 { - bytes.append(contentsOf: byteArr) - } - - // Writes an integer in big-endian order. - // - // Warning: make sure what you are trying to write - // is in the correct type! - func writeInt(_ value: T) { - var value = value.bigEndian - withUnsafeBytes(of: &value) { bytes.append(contentsOf: $0) } - } - - @inlinable - func writeFloat(_ value: Float) { - writeInt(value.bitPattern) - } - - @inlinable - func writeDouble(_ value: Double) { - writeInt(value.bitPattern) - } -} - -// Protocol for types that transfer other types across the FFI. This is -// analogous go the Rust trait of the same name. -fileprivate protocol FfiConverter { - associatedtype FfiType - associatedtype SwiftType - - static func lift(_ value: FfiType) throws -> SwiftType - static func lower(_ value: SwiftType) -> FfiType - static func read(from buf: Reader) throws -> SwiftType - static func write(_ value: SwiftType, into buf: Writer) -} - -// Types conforming to `Primitive` pass themselves directly over the FFI. -fileprivate protocol FfiConverterPrimitive: FfiConverter where FfiType == SwiftType { } - -extension FfiConverterPrimitive { - static func lift(_ value: FfiType) throws -> SwiftType { - return value - } - - static func lower(_ value: SwiftType) -> FfiType { - return value - } -} - -// Types conforming to `FfiConverterRustBuffer` lift and lower into a `RustBuffer`. -// Used for complex types where it's hard to write a custom lift/lower. -fileprivate protocol FfiConverterRustBuffer: FfiConverter where FfiType == RustBuffer {} - -extension FfiConverterRustBuffer { - static func lift(_ buf: RustBuffer) throws -> SwiftType { - let reader = Reader(data: Data(rustBuffer: buf)) - let value = try read(from: reader) - if reader.hasRemaining() { - throw UniffiInternalError.incompleteData - } - buf.deallocate() - return value - } - - static func lower(_ value: SwiftType) -> RustBuffer { - let writer = Writer() - write(value, into: writer) - return RustBuffer(bytes: writer.bytes) - } -} -// An error type for FFI errors. These errors occur at the UniFFI level, not -// the library level. -fileprivate enum UniffiInternalError: LocalizedError { - case bufferOverflow - case incompleteData - case unexpectedOptionalTag - case unexpectedEnumCase - case unexpectedNullPointer - case unexpectedRustCallStatusCode - case unexpectedRustCallError - case unexpectedStaleHandle - case rustPanic(_ message: String) - - public var errorDescription: String? { - switch self { - case .bufferOverflow: return "Reading the requested value would read past the end of the buffer" - case .incompleteData: return "The buffer still has data after lifting its containing value" - case .unexpectedOptionalTag: return "Unexpected optional tag; should be 0 or 1" - case .unexpectedEnumCase: return "Raw enum value doesn't match any cases" - case .unexpectedNullPointer: return "Raw pointer value was null" - case .unexpectedRustCallStatusCode: return "Unexpected RustCallStatus code" - case .unexpectedRustCallError: return "CALL_ERROR but no errorClass specified" - case .unexpectedStaleHandle: return "The object in the handle map has been dropped already" - case let .rustPanic(message): return message - } - } -} - -fileprivate let CALL_SUCCESS: Int8 = 0 -fileprivate let CALL_ERROR: Int8 = 1 -fileprivate let CALL_PANIC: Int8 = 2 - -fileprivate extension RustCallStatus { - init() { - self.init( - code: CALL_SUCCESS, - errorBuf: RustBuffer.init( - capacity: 0, - len: 0, - data: nil - ) - ) - } -} - -private func rustCall(_ callback: (UnsafeMutablePointer) -> T) throws -> T { - try makeRustCall(callback, errorHandler: { - $0.deallocate() - return UniffiInternalError.unexpectedRustCallError - }) -} - -private func rustCallWithError - (_ errorFfiConverter: F.Type, _ callback: (UnsafeMutablePointer) -> T) throws -> T - where F.SwiftType: Error, F.FfiType == RustBuffer - { - try makeRustCall(callback, errorHandler: { return try errorFfiConverter.lift($0) }) -} - -private func makeRustCall(_ callback: (UnsafeMutablePointer) -> T, errorHandler: (RustBuffer) throws -> Error) throws -> T { - var callStatus = RustCallStatus.init() - let returnedVal = callback(&callStatus) - switch callStatus.code { - case CALL_SUCCESS: - return returnedVal - - case CALL_ERROR: - throw try errorHandler(callStatus.errorBuf) - - case CALL_PANIC: - // When the rust code sees a panic, it tries to construct a RustBuffer - // with the message. But if that code panics, then it just sends back - // an empty buffer. - if callStatus.errorBuf.len > 0 { - throw UniffiInternalError.rustPanic(try FfiConverterString.lift(callStatus.errorBuf)) - } else { - callStatus.errorBuf.deallocate() - throw UniffiInternalError.rustPanic("Rust panic") - } - - default: - throw UniffiInternalError.unexpectedRustCallStatusCode - } -} - -// Public interface members begin here. - - -fileprivate struct FfiConverterString: FfiConverter { - typealias SwiftType = String - typealias FfiType = RustBuffer - - static func lift(_ value: RustBuffer) throws -> String { - defer { - value.deallocate() - } - if value.data == nil { - return String() - } - let bytes = UnsafeBufferPointer(start: value.data!, count: Int(value.len)) - return String(bytes: bytes, encoding: String.Encoding.utf8)! - } - - static func lower(_ value: String) -> RustBuffer { - return value.utf8CString.withUnsafeBufferPointer { ptr in - // The swift string gives us int8_t, we want uint8_t. - ptr.withMemoryRebound(to: UInt8.self) { ptr in - // The swift string gives us a trailing null byte, we don't want it. - let buf = UnsafeBufferPointer(rebasing: ptr.prefix(upTo: ptr.count - 1)) - return RustBuffer.from(buf) - } - } - } - - static func read(from buf: Reader) throws -> String { - let len: Int32 = try buf.readInt() - return String(bytes: try buf.readBytes(count: Int(len)), encoding: String.Encoding.utf8)! - } - - static func write(_ value: String, into buf: Writer) { - let len = Int32(value.utf8.count) - buf.writeInt(len) - buf.writeBytes(value.utf8) - } -} - - -public enum CrypterError { - - - - // Simple error enums only carry a message - case DerivePublicKey(message: String) - - // Simple error enums only carry a message - case DeriveSharedSecret(message: String) - - // Simple error enums only carry a message - case Encrypt(message: String) - - // Simple error enums only carry a message - case Decrypt(message: String) - - // Simple error enums only carry a message - case BadPubkey(message: String) - - // Simple error enums only carry a message - case BadSecret(message: String) - - // Simple error enums only carry a message - case BadNonce(message: String) - - // Simple error enums only carry a message - case BadCiper(message: String) - -} - -fileprivate struct FfiConverterTypeCrypterError: FfiConverterRustBuffer { - typealias SwiftType = CrypterError - - static func read(from buf: Reader) throws -> CrypterError { - let variant: Int32 = try buf.readInt() - switch variant { - - - - - case 1: return .DerivePublicKey( - message: try FfiConverterString.read(from: buf) - ) - - case 2: return .DeriveSharedSecret( - message: try FfiConverterString.read(from: buf) - ) - - case 3: return .Encrypt( - message: try FfiConverterString.read(from: buf) - ) - - case 4: return .Decrypt( - message: try FfiConverterString.read(from: buf) - ) - - case 5: return .BadPubkey( - message: try FfiConverterString.read(from: buf) - ) - - case 6: return .BadSecret( - message: try FfiConverterString.read(from: buf) - ) - - case 7: return .BadNonce( - message: try FfiConverterString.read(from: buf) - ) - - case 8: return .BadCiper( - message: try FfiConverterString.read(from: buf) - ) - - - default: throw UniffiInternalError.unexpectedEnumCase - } - } - - static func write(_ value: CrypterError, into buf: Writer) { - switch value { - - - - - case let .DerivePublicKey(message): - buf.writeInt(Int32(1)) - FfiConverterString.write(message, into: buf) - case let .DeriveSharedSecret(message): - buf.writeInt(Int32(2)) - FfiConverterString.write(message, into: buf) - case let .Encrypt(message): - buf.writeInt(Int32(3)) - FfiConverterString.write(message, into: buf) - case let .Decrypt(message): - buf.writeInt(Int32(4)) - FfiConverterString.write(message, into: buf) - case let .BadPubkey(message): - buf.writeInt(Int32(5)) - FfiConverterString.write(message, into: buf) - case let .BadSecret(message): - buf.writeInt(Int32(6)) - FfiConverterString.write(message, into: buf) - case let .BadNonce(message): - buf.writeInt(Int32(7)) - FfiConverterString.write(message, into: buf) - case let .BadCiper(message): - buf.writeInt(Int32(8)) - FfiConverterString.write(message, into: buf) - - - } - } -} - - -extension CrypterError: Equatable, Hashable {} - -extension CrypterError: Error { } - -public func pubkeyFromSecretKey(mySecretKey: String) throws -> String { - return try FfiConverterString.lift( - try - - rustCallWithError(FfiConverterTypeCrypterError.self) { - - crypter_9c38_pubkey_from_secret_key( - FfiConverterString.lower(mySecretKey), $0) -} - ) -} - - - -public func deriveSharedSecret(theirPubkey: String, mySecretKey: String) throws -> String { - return try FfiConverterString.lift( - try - - rustCallWithError(FfiConverterTypeCrypterError.self) { - - crypter_9c38_derive_shared_secret( - FfiConverterString.lower(theirPubkey), - FfiConverterString.lower(mySecretKey), $0) -} - ) -} - - - -public func encrypt(plaintext: String, secret: String, nonce: String) throws -> String { - return try FfiConverterString.lift( - try - - rustCallWithError(FfiConverterTypeCrypterError.self) { - - crypter_9c38_encrypt( - FfiConverterString.lower(plaintext), - FfiConverterString.lower(secret), - FfiConverterString.lower(nonce), $0) -} - ) -} - - - -public func decrypt(ciphertext: String, secret: String) throws -> String { - return try FfiConverterString.lift( - try - - rustCallWithError(FfiConverterTypeCrypterError.self) { - - crypter_9c38_decrypt( - FfiConverterString.lower(ciphertext), - FfiConverterString.lower(secret), $0) -} - ) -} - - - -/** - * Top level initializers and tear down methods. - * - * This is generated by uniffi. - */ -public enum CrypterLifecycle { - /** - * Initialize the FFI and Rust library. This should be only called once per application. - */ - func initialize() { - } -} \ No newline at end of file diff --git a/crypter-ffi/src/crypter.udl b/crypter-ffi/src/crypter.udl deleted file mode 100644 index ee14321..0000000 --- a/crypter-ffi/src/crypter.udl +++ /dev/null @@ -1,22 +0,0 @@ -[Error] -enum CrypterError { - "DerivePublicKey", - "DeriveSharedSecret", - "Encrypt", - "Decrypt", - "BadPubkey", - "BadSecret", - "BadNonce", - "BadCiper", -}; - -namespace crypter { - [Throws=CrypterError] - string pubkey_from_secret_key(string my_secret_key); - [Throws=CrypterError] - string derive_shared_secret(string their_pubkey, string my_secret_key); - [Throws=CrypterError] - string encrypt(string plaintext, string secret, string nonce); - [Throws=CrypterError] - string decrypt(string ciphertext, string secret); -}; \ No newline at end of file diff --git a/crypter-ffi/src/crypterFFI.h b/crypter-ffi/src/crypterFFI.h deleted file mode 100644 index 4cc0138..0000000 --- a/crypter-ffi/src/crypterFFI.h +++ /dev/null @@ -1,80 +0,0 @@ -// This file was autogenerated by some hot garbage in the `uniffi` crate. -// Trust me, you don't want to mess with it! - -#pragma once - -#include -#include - -// The following structs are used to implement the lowest level -// of the FFI, and thus useful to multiple uniffied crates. -// We ensure they are declared exactly once, with a header guard, UNIFFI_SHARED_H. -#ifdef UNIFFI_SHARED_H - // We also try to prevent mixing versions of shared uniffi header structs. - // If you add anything to the #else block, you must increment the version suffix in UNIFFI_SHARED_HEADER_V4 - #ifndef UNIFFI_SHARED_HEADER_V4 - #error Combining helper code from multiple versions of uniffi is not supported - #endif // ndef UNIFFI_SHARED_HEADER_V4 -#else -#define UNIFFI_SHARED_H -#define UNIFFI_SHARED_HEADER_V4 -// ⚠️ Attention: If you change this #else block (ending in `#endif // def UNIFFI_SHARED_H`) you *must* ⚠️ -// ⚠️ increment the version suffix in all instances of UNIFFI_SHARED_HEADER_V4 in this file. ⚠️ - -typedef struct RustBuffer -{ - int32_t capacity; - int32_t len; - uint8_t *_Nullable data; -} RustBuffer; - -typedef int32_t (*ForeignCallback)(uint64_t, int32_t, RustBuffer, RustBuffer *_Nonnull); - -typedef struct ForeignBytes -{ - int32_t len; - const uint8_t *_Nullable data; -} ForeignBytes; - -// Error definitions -typedef struct RustCallStatus { - int8_t code; - RustBuffer errorBuf; -} RustCallStatus; - -// ⚠️ Attention: If you change this #else block (ending in `#endif // def UNIFFI_SHARED_H`) you *must* ⚠️ -// ⚠️ increment the version suffix in all instances of UNIFFI_SHARED_HEADER_V4 in this file. ⚠️ -#endif // def UNIFFI_SHARED_H - -RustBuffer crypter_9c38_pubkey_from_secret_key( - RustBuffer my_secret_key, - RustCallStatus *_Nonnull out_status - ); -RustBuffer crypter_9c38_derive_shared_secret( - RustBuffer their_pubkey,RustBuffer my_secret_key, - RustCallStatus *_Nonnull out_status - ); -RustBuffer crypter_9c38_encrypt( - RustBuffer plaintext,RustBuffer secret,RustBuffer nonce, - RustCallStatus *_Nonnull out_status - ); -RustBuffer crypter_9c38_decrypt( - RustBuffer ciphertext,RustBuffer secret, - RustCallStatus *_Nonnull out_status - ); -RustBuffer ffi_crypter_9c38_rustbuffer_alloc( - int32_t size, - RustCallStatus *_Nonnull out_status - ); -RustBuffer ffi_crypter_9c38_rustbuffer_from_bytes( - ForeignBytes bytes, - RustCallStatus *_Nonnull out_status - ); -void ffi_crypter_9c38_rustbuffer_free( - RustBuffer buf, - RustCallStatus *_Nonnull out_status - ); -RustBuffer ffi_crypter_9c38_rustbuffer_reserve( - RustBuffer buf,int32_t additional, - RustCallStatus *_Nonnull out_status - ); diff --git a/crypter-ffi/src/crypterFFI.modulemap b/crypter-ffi/src/crypterFFI.modulemap deleted file mode 100644 index c87fd8b..0000000 --- a/crypter-ffi/src/crypterFFI.modulemap +++ /dev/null @@ -1,6 +0,0 @@ -// This file was autogenerated by some hot garbage in the `uniffi` crate. -// Trust me, you don't want to mess with it! -framework module crypterFFI { - header "crypterFFI.h" - export * -} \ No newline at end of file diff --git a/crypter-ffi/src/lib.rs b/crypter-ffi/src/lib.rs deleted file mode 100644 index 9fefccf..0000000 --- a/crypter-ffi/src/lib.rs +++ /dev/null @@ -1,121 +0,0 @@ -mod parse; - -use sphinx_key_crypter::chacha::{decrypt as chacha_decrypt, encrypt as chacha_encrypt}; -use sphinx_key_crypter::ecdh::derive_shared_secret_from_slice; -use sphinx_key_crypter::secp256k1::{PublicKey, Secp256k1, SecretKey}; - -include!("crypter.uniffi.rs"); - -pub type Result = std::result::Result; - -#[derive(Debug, thiserror::Error)] -pub enum CrypterError { - #[error("Failed to derive public key")] - DerivePublicKey, - #[error("Failed to derive shared secret")] - DeriveSharedSecret, - #[error("Failed to encrypt")] - Encrypt, - #[error("Failed to decrypt")] - Decrypt, - #[error("Bad pubkey")] - BadPubkey, - #[error("Bad secret")] - BadSecret, - #[error("Bad nonce")] - BadNonce, - #[error("Bad cipher")] - BadCiper, -} - -pub fn pubkey_from_secret_key(my_secret_key: String) -> Result { - let secret_key = parse::parse_secret_string(my_secret_key)?; - let sk = match SecretKey::from_slice(&secret_key[..]) { - Ok(s) => s, - Err(_) => return Err(CrypterError::BadSecret), - }; - let ctx = Secp256k1::new(); - let pk = PublicKey::from_secret_key(&ctx, &sk).serialize(); - Ok(hex::encode(pk)) -} - -// their_pubkey: 33 bytes -// my_secret_key: 32 bytes -// return shared secret: 32 bytes -pub fn derive_shared_secret(their_pubkey: String, my_secret_key: String) -> Result { - let pubkey = parse::parse_public_key_string(their_pubkey)?; - let secret_key = parse::parse_secret_string(my_secret_key)?; - let secret = match derive_shared_secret_from_slice(pubkey, secret_key) { - Ok(s) => s, - Err(_) => return Err(CrypterError::DeriveSharedSecret), - }; - Ok(hex::encode(secret)) -} - -// plaintext: 32 bytes -// secret: 32 bytes -// nonce: 8 bytes -// return ciphertext: 56 bytes -pub fn encrypt(plaintext: String, secret: String, nonce: String) -> Result { - let plain = parse::parse_secret_string(plaintext)?; - let sec = parse::parse_secret_string(secret)?; - let non = parse::parse_nonce_string(nonce)?; - let cipher = match chacha_encrypt(plain, sec, non) { - Ok(c) => c, - Err(_) => return Err(CrypterError::Encrypt), - }; - Ok(hex::encode(cipher)) -} - -// ciphertext: 56 bytes -// secret: 32 bytes -// return plaintext: 32 bytes -pub fn decrypt(ciphertext: String, secret: String) -> Result { - let cipher = parse::parse_cipher_string(ciphertext)?; - let sec = parse::parse_secret_string(secret)?; - let plain = match chacha_decrypt(cipher, sec) { - Ok(c) => c, - Err(_) => return Err(CrypterError::Decrypt), - }; - Ok(hex::encode(plain)) -} - -#[cfg(test)] -mod tests { - use crate::{decrypt, derive_shared_secret, encrypt, pubkey_from_secret_key, Result}; - - #[test] - fn test_crypter() -> Result<()> { - let sk1 = "86c8977989592a97beb409bc27fde76e981ce3543499fd61743755b832e92a3e"; - let pk1 = "0362a684901b8d065fb034bc44ea972619a409aeafc2a698016a74f6eee1008aca"; - - let sk2 = "21c2d41c7394b0a87dae89576bee2552aedb54a204cdcdbf5cdceb0b4c1c2a17"; - let pk2 = "027dd6297aff570a409fe05032b6e1dab39f309daa8c438a65c32e3d7b4722b7c3"; - - // derive shared secrets - let sec1 = derive_shared_secret(pk2.to_string(), sk1.to_string())?; - let sec2 = derive_shared_secret(pk1.to_string(), sk2.to_string())?; - assert_eq!(sec1, sec2); - - // encrypt plaintext with sec1 - let plaintext = "59ff446bec1d96dc7d1a69232cd69ca409e069294e983df7f1e3e5fb3c95c41c"; - let nonce = "0da01cc0c0a73ad3"; - let cipher = encrypt(plaintext.to_string(), sec1, nonce.to_string())?; - - // decrypt with sec2 - let plain = decrypt(cipher, sec2)?; - assert_eq!(plaintext, plain); - - println!("PLAINTEXT MATCHES!"); - Ok(()) - } - - #[test] - fn test_derive_pubkey() -> Result<()> { - let sk1 = "86c8977989592a97beb409bc27fde76e981ce3543499fd61743755b832e92a3e"; - let pk1 = "0362a684901b8d065fb034bc44ea972619a409aeafc2a698016a74f6eee1008aca"; - let pk = pubkey_from_secret_key(sk1.to_string())?; - assert_eq!(pk, pk1); - Ok(()) - } -} diff --git a/crypter-ffi/src/parse.rs b/crypter-ffi/src/parse.rs deleted file mode 100644 index 2b68409..0000000 --- a/crypter-ffi/src/parse.rs +++ /dev/null @@ -1,65 +0,0 @@ -use crate::{Result, CrypterError}; - -use sphinx_key_crypter::ecdh::PUBLIC_KEY_LEN; -use sphinx_key_crypter::chacha::{NONCE_END_LEN, KEY_LEN, CIPHER_LEN}; -use std::convert::TryInto; - -pub(crate) fn parse_secret_string(sk: String) -> Result<[u8; KEY_LEN]> { - if sk.len() != KEY_LEN * 2 { - return Err(CrypterError::BadSecret) - } - let secret_key_bytes: Vec = match hex::decode(sk) { - Ok(sk) => sk, - Err(_) => return Err(CrypterError::BadSecret), - }; - let secret_key: [u8; KEY_LEN] = match secret_key_bytes.try_into() { - Ok(sk) => sk, - Err(_) => return Err(CrypterError::BadSecret), - }; - Ok(secret_key) -} - -pub(crate) fn parse_public_key_string(pk: String) -> Result<[u8; PUBLIC_KEY_LEN]> { - if pk.len() != PUBLIC_KEY_LEN * 2 { - return Err(CrypterError::BadPubkey) - } - let pubkey_bytes: Vec = match hex::decode(pk) { - Ok(pk) => pk, - Err(_) => return Err(CrypterError::BadPubkey), - }; - let pubkey: [u8; PUBLIC_KEY_LEN] = match pubkey_bytes.try_into() { - Ok(pk) => pk, - Err(_) => return Err(CrypterError::BadPubkey), - }; - Ok(pubkey) -} - -pub(crate) fn parse_nonce_string(n: String) -> Result<[u8; NONCE_END_LEN]> { - if n.len() != NONCE_END_LEN * 2 { - return Err(CrypterError::BadNonce) - } - let nonce_bytes: Vec = match hex::decode(n) { - Ok(n) => n, - Err(_) => return Err(CrypterError::BadNonce), - }; - let nonce: [u8; NONCE_END_LEN] = match nonce_bytes.try_into() { - Ok(n) => n, - Err(_) => return Err(CrypterError::BadNonce), - }; - Ok(nonce) -} - -pub(crate) fn parse_cipher_string(c: String) -> Result<[u8; CIPHER_LEN]> { - if c.len() != CIPHER_LEN * 2 { - return Err(CrypterError::BadCiper) - } - let cipher_bytes: Vec = match hex::decode(c) { - Ok(n) => n, - Err(_) => return Err(CrypterError::BadCiper), - }; - let cipher: [u8; CIPHER_LEN] = match cipher_bytes.try_into() { - Ok(n) => n, - Err(_) => return Err(CrypterError::BadCiper), - }; - Ok(cipher) -} diff --git a/crypter-ffi/src/uniffi/crypter/crypter.kt b/crypter-ffi/src/uniffi/crypter/crypter.kt deleted file mode 100644 index 7f9ef3c..0000000 --- a/crypter-ffi/src/uniffi/crypter/crypter.kt +++ /dev/null @@ -1,435 +0,0 @@ -// This file was autogenerated by some hot garbage in the `uniffi` crate. -// Trust me, you don't want to mess with it! - -@file:Suppress("NAME_SHADOWING") - -package uniffi.crypter; - -// Common helper code. -// -// Ideally this would live in a separate .kt file where it can be unittested etc -// in isolation, and perhaps even published as a re-useable package. -// -// However, it's important that the detils of how this helper code works (e.g. the -// way that different builtin types are passed across the FFI) exactly match what's -// expected by the Rust code on the other side of the interface. In practice right -// now that means coming from the exact some version of `uniffi` that was used to -// compile the Rust component. The easiest way to ensure this is to bundle the Kotlin -// helpers directly inline like we're doing here. - -import com.sun.jna.Library -import com.sun.jna.Native -import com.sun.jna.Pointer -import com.sun.jna.Structure -import com.sun.jna.ptr.ByReference -import java.nio.ByteBuffer -import java.nio.ByteOrder - -// This is a helper for safely working with byte buffers returned from the Rust code. -// A rust-owned buffer is represented by its capacity, its current length, and a -// pointer to the underlying data. - -@Structure.FieldOrder("capacity", "len", "data") -open class RustBuffer : Structure() { - @JvmField var capacity: Int = 0 - @JvmField var len: Int = 0 - @JvmField var data: Pointer? = null - - class ByValue : RustBuffer(), Structure.ByValue - class ByReference : RustBuffer(), Structure.ByReference - - companion object { - internal fun alloc(size: Int = 0) = rustCall() { status -> - _UniFFILib.INSTANCE.ffi_crypter_9c38_rustbuffer_alloc(size, status).also { - if(it.data == null) { - throw RuntimeException("RustBuffer.alloc() returned null data pointer (size=${size})") - } - } - } - - internal fun free(buf: RustBuffer.ByValue) = rustCall() { status -> - _UniFFILib.INSTANCE.ffi_crypter_9c38_rustbuffer_free(buf, status) - } - } - - @Suppress("TooGenericExceptionThrown") - fun asByteBuffer() = - this.data?.getByteBuffer(0, this.len.toLong())?.also { - it.order(ByteOrder.BIG_ENDIAN) - } -} - -/** - * The equivalent of the `*mut RustBuffer` type. - * Required for callbacks taking in an out pointer. - * - * Size is the sum of all values in the struct. - */ -class RustBufferByReference : ByReference(16) { - /** - * Set the pointed-to `RustBuffer` to the given value. - */ - fun setValue(value: RustBuffer.ByValue) { - // NOTE: The offsets are as they are in the C-like struct. - val pointer = getPointer() - pointer.setInt(0, value.capacity) - pointer.setInt(4, value.len) - pointer.setPointer(8, value.data) - } -} - -// This is a helper for safely passing byte references into the rust code. -// It's not actually used at the moment, because there aren't many things that you -// can take a direct pointer to in the JVM, and if we're going to copy something -// then we might as well copy it into a `RustBuffer`. But it's here for API -// completeness. - -@Structure.FieldOrder("len", "data") -open class ForeignBytes : Structure() { - @JvmField var len: Int = 0 - @JvmField var data: Pointer? = null - - class ByValue : ForeignBytes(), Structure.ByValue -} -// The FfiConverter interface handles converter types to and from the FFI -// -// All implementing objects should be public to support external types. When a -// type is external we need to import it's FfiConverter. -public interface FfiConverter { - // Convert an FFI type to a Kotlin type - fun lift(value: FfiType): KotlinType - - // Convert an Kotlin type to an FFI type - fun lower(value: KotlinType): FfiType - - // Read a Kotlin type from a `ByteBuffer` - fun read(buf: ByteBuffer): KotlinType - - // Calculate bytes to allocate when creating a `RustBuffer` - // - // This must return at least as many bytes as the write() function will - // write. It can return more bytes than needed, for example when writing - // Strings we can't know the exact bytes needed until we the UTF-8 - // encoding, so we pessimistically allocate the largest size possible (3 - // bytes per codepoint). Allocating extra bytes is not really a big deal - // because the `RustBuffer` is short-lived. - fun allocationSize(value: KotlinType): Int - - // Write a Kotlin type to a `ByteBuffer` - fun write(value: KotlinType, buf: ByteBuffer) - - // Lower a value into a `RustBuffer` - // - // This method lowers a value into a `RustBuffer` rather than the normal - // FfiType. It's used by the callback interface code. Callback interface - // returns are always serialized into a `RustBuffer` regardless of their - // normal FFI type. - fun lowerIntoRustBuffer(value: KotlinType): RustBuffer.ByValue { - val rbuf = RustBuffer.alloc(allocationSize(value)) - try { - val bbuf = rbuf.data!!.getByteBuffer(0, rbuf.capacity.toLong()).also { - it.order(ByteOrder.BIG_ENDIAN) - } - write(value, bbuf) - rbuf.writeField("len", bbuf.position()) - return rbuf - } catch (e: Throwable) { - RustBuffer.free(rbuf) - throw e - } - } - - // Lift a value from a `RustBuffer`. - // - // This here mostly because of the symmetry with `lowerIntoRustBuffer()`. - // It's currently only used by the `FfiConverterRustBuffer` class below. - fun liftFromRustBuffer(rbuf: RustBuffer.ByValue): KotlinType { - val byteBuf = rbuf.asByteBuffer()!! - try { - val item = read(byteBuf) - if (byteBuf.hasRemaining()) { - throw RuntimeException("junk remaining in buffer after lifting, something is very wrong!!") - } - return item - } finally { - RustBuffer.free(rbuf) - } - } -} - -// FfiConverter that uses `RustBuffer` as the FfiType -public interface FfiConverterRustBuffer: FfiConverter { - override fun lift(value: RustBuffer.ByValue) = liftFromRustBuffer(value) - override fun lower(value: KotlinType) = lowerIntoRustBuffer(value) -} -// A handful of classes and functions to support the generated data structures. -// This would be a good candidate for isolating in its own ffi-support lib. -// Error runtime. -@Structure.FieldOrder("code", "error_buf") -internal open class RustCallStatus : Structure() { - @JvmField var code: Int = 0 - @JvmField var error_buf: RustBuffer.ByValue = RustBuffer.ByValue() - - fun isSuccess(): Boolean { - return code == 0 - } - - fun isError(): Boolean { - return code == 1 - } - - fun isPanic(): Boolean { - return code == 2 - } -} - -class InternalException(message: String) : Exception(message) - -// Each top-level error class has a companion object that can lift the error from the call status's rust buffer -interface CallStatusErrorHandler { - fun lift(error_buf: RustBuffer.ByValue): E; -} - -// Helpers for calling Rust -// In practice we usually need to be synchronized to call this safely, so it doesn't -// synchronize itself - -// Call a rust function that returns a Result<>. Pass in the Error class companion that corresponds to the Err -private inline fun rustCallWithError(errorHandler: CallStatusErrorHandler, callback: (RustCallStatus) -> U): U { - var status = RustCallStatus(); - val return_value = callback(status) - if (status.isSuccess()) { - return return_value - } else if (status.isError()) { - throw errorHandler.lift(status.error_buf) - } else if (status.isPanic()) { - // when the rust code sees a panic, it tries to construct a rustbuffer - // with the message. but if that code panics, then it just sends back - // an empty buffer. - if (status.error_buf.len > 0) { - throw InternalException(FfiConverterString.lift(status.error_buf)) - } else { - throw InternalException("Rust panic") - } - } else { - throw InternalException("Unknown rust call status: $status.code") - } -} - -// CallStatusErrorHandler implementation for times when we don't expect a CALL_ERROR -object NullCallStatusErrorHandler: CallStatusErrorHandler { - override fun lift(error_buf: RustBuffer.ByValue): InternalException { - RustBuffer.free(error_buf) - return InternalException("Unexpected CALL_ERROR") - } -} - -// Call a rust function that returns a plain value -private inline fun rustCall(callback: (RustCallStatus) -> U): U { - return rustCallWithError(NullCallStatusErrorHandler, callback); -} - -// Contains loading, initialization code, -// and the FFI Function declarations in a com.sun.jna.Library. -@Synchronized -private fun findLibraryName(componentName: String): String { - val libOverride = System.getProperty("uniffi.component.$componentName.libraryOverride") - if (libOverride != null) { - return libOverride - } - return "crypter" -} - -private inline fun loadIndirect( - componentName: String -): Lib { - return Native.load(findLibraryName(componentName), Lib::class.java) -} - -// A JNA Library to expose the extern-C FFI definitions. -// This is an implementation detail which will be called internally by the public API. - -internal interface _UniFFILib : Library { - companion object { - internal val INSTANCE: _UniFFILib by lazy { - loadIndirect<_UniFFILib>(componentName = "crypter") - - } - } - - fun crypter_9c38_pubkey_from_secret_key(`mySecretKey`: RustBuffer.ByValue, - _uniffi_out_err: RustCallStatus - ): RustBuffer.ByValue - - fun crypter_9c38_derive_shared_secret(`theirPubkey`: RustBuffer.ByValue,`mySecretKey`: RustBuffer.ByValue, - _uniffi_out_err: RustCallStatus - ): RustBuffer.ByValue - - fun crypter_9c38_encrypt(`plaintext`: RustBuffer.ByValue,`secret`: RustBuffer.ByValue,`nonce`: RustBuffer.ByValue, - _uniffi_out_err: RustCallStatus - ): RustBuffer.ByValue - - fun crypter_9c38_decrypt(`ciphertext`: RustBuffer.ByValue,`secret`: RustBuffer.ByValue, - _uniffi_out_err: RustCallStatus - ): RustBuffer.ByValue - - fun ffi_crypter_9c38_rustbuffer_alloc(`size`: Int, - _uniffi_out_err: RustCallStatus - ): RustBuffer.ByValue - - fun ffi_crypter_9c38_rustbuffer_from_bytes(`bytes`: ForeignBytes.ByValue, - _uniffi_out_err: RustCallStatus - ): RustBuffer.ByValue - - fun ffi_crypter_9c38_rustbuffer_free(`buf`: RustBuffer.ByValue, - _uniffi_out_err: RustCallStatus - ): Unit - - fun ffi_crypter_9c38_rustbuffer_reserve(`buf`: RustBuffer.ByValue,`additional`: Int, - _uniffi_out_err: RustCallStatus - ): RustBuffer.ByValue - - -} - -// Public interface members begin here. - - -public object FfiConverterString: FfiConverter { - // Note: we don't inherit from FfiConverterRustBuffer, because we use a - // special encoding when lowering/lifting. We can use `RustBuffer.len` to - // store our length and avoid writing it out to the buffer. - override fun lift(value: RustBuffer.ByValue): String { - try { - val byteArr = ByteArray(value.len) - value.asByteBuffer()!!.get(byteArr) - return byteArr.toString(Charsets.UTF_8) - } finally { - RustBuffer.free(value) - } - } - - override fun read(buf: ByteBuffer): String { - val len = buf.getInt() - val byteArr = ByteArray(len) - buf.get(byteArr) - return byteArr.toString(Charsets.UTF_8) - } - - override fun lower(value: String): RustBuffer.ByValue { - val byteArr = value.toByteArray(Charsets.UTF_8) - // Ideally we'd pass these bytes to `ffi_bytebuffer_from_bytes`, but doing so would require us - // to copy them into a JNA `Memory`. So we might as well directly copy them into a `RustBuffer`. - val rbuf = RustBuffer.alloc(byteArr.size) - rbuf.asByteBuffer()!!.put(byteArr) - return rbuf - } - - // We aren't sure exactly how many bytes our string will be once it's UTF-8 - // encoded. Allocate 3 bytes per unicode codepoint which will always be - // enough. - override fun allocationSize(value: String): Int { - val sizeForLength = 4 - val sizeForString = value.length * 3 - return sizeForLength + sizeForString - } - - override fun write(value: String, buf: ByteBuffer) { - val byteArr = value.toByteArray(Charsets.UTF_8) - buf.putInt(byteArr.size) - buf.put(byteArr) - } -} - - - - - -sealed class CrypterException(message: String): Exception(message) { - // Each variant is a nested class - // Flat enums carries a string error message, so no special implementation is necessary. - class DerivePublicKey(message: String) : CrypterException(message) - class DeriveSharedSecret(message: String) : CrypterException(message) - class Encrypt(message: String) : CrypterException(message) - class Decrypt(message: String) : CrypterException(message) - class BadPubkey(message: String) : CrypterException(message) - class BadSecret(message: String) : CrypterException(message) - class BadNonce(message: String) : CrypterException(message) - class BadCiper(message: String) : CrypterException(message) - - - companion object ErrorHandler : CallStatusErrorHandler { - override fun lift(error_buf: RustBuffer.ByValue): CrypterException = FfiConverterTypeCrypterError.lift(error_buf) - } -} - -public object FfiConverterTypeCrypterError : FfiConverterRustBuffer { - override fun read(buf: ByteBuffer): CrypterException { - - return when(buf.getInt()) { - 1 -> CrypterException.DerivePublicKey(FfiConverterString.read(buf)) - 2 -> CrypterException.DeriveSharedSecret(FfiConverterString.read(buf)) - 3 -> CrypterException.Encrypt(FfiConverterString.read(buf)) - 4 -> CrypterException.Decrypt(FfiConverterString.read(buf)) - 5 -> CrypterException.BadPubkey(FfiConverterString.read(buf)) - 6 -> CrypterException.BadSecret(FfiConverterString.read(buf)) - 7 -> CrypterException.BadNonce(FfiConverterString.read(buf)) - 8 -> CrypterException.BadCiper(FfiConverterString.read(buf)) - else -> throw RuntimeException("invalid error enum value, something is very wrong!!") - } - - } - - @Suppress("UNUSED_PARAMETER") - override fun allocationSize(value: CrypterException): Int { - throw RuntimeException("Writing Errors is not supported") - } - - @Suppress("UNUSED_PARAMETER") - override fun write(value: CrypterException, buf: ByteBuffer) { - throw RuntimeException("Writing Errors is not supported") - } - -} -@Throws(CrypterException::class) - -fun `pubkeyFromSecretKey`(`mySecretKey`: String): String { - return FfiConverterString.lift( - rustCallWithError(CrypterException) { _status -> - _UniFFILib.INSTANCE.crypter_9c38_pubkey_from_secret_key(FfiConverterString.lower(`mySecretKey`), _status) -}) -} - - -@Throws(CrypterException::class) - -fun `deriveSharedSecret`(`theirPubkey`: String, `mySecretKey`: String): String { - return FfiConverterString.lift( - rustCallWithError(CrypterException) { _status -> - _UniFFILib.INSTANCE.crypter_9c38_derive_shared_secret(FfiConverterString.lower(`theirPubkey`), FfiConverterString.lower(`mySecretKey`), _status) -}) -} - - -@Throws(CrypterException::class) - -fun `encrypt`(`plaintext`: String, `secret`: String, `nonce`: String): String { - return FfiConverterString.lift( - rustCallWithError(CrypterException) { _status -> - _UniFFILib.INSTANCE.crypter_9c38_encrypt(FfiConverterString.lower(`plaintext`), FfiConverterString.lower(`secret`), FfiConverterString.lower(`nonce`), _status) -}) -} - - -@Throws(CrypterException::class) - -fun `decrypt`(`ciphertext`: String, `secret`: String): String { - return FfiConverterString.lift( - rustCallWithError(CrypterException) { _status -> - _UniFFILib.INSTANCE.crypter_9c38_decrypt(FfiConverterString.lower(`ciphertext`), FfiConverterString.lower(`secret`), _status) -}) -} - - - - diff --git a/crypter/Cargo.toml b/crypter/Cargo.toml deleted file mode 100644 index 63c80f0..0000000 --- a/crypter/Cargo.toml +++ /dev/null @@ -1,23 +0,0 @@ -[package] -name = "sphinx-key-crypter" -version = "0.1.0" -authors = ["Evan Feenstra "] -edition = "2018" - -[dependencies] -anyhow = {version = "1", features = ["backtrace"]} -secp256k1 = { version = "0.22.0", features = ["std", "rand-std", "lowmemory"] } -rand = "0.8.5" - -[dependencies.lightning] -version = "0.0.108" -default-features = false -features = ["std", "grind_signatures"] - -# [dev-dependencies] - -[patch.crates-io] -getrandom = { version = "0.2", git = "https://github.com/esp-rs-compat/getrandom.git" } -secp256k1 = { git = "https://github.com/Evanfeenstra/rust-secp256k1", branch = "v0.22.0-new-rand" } -lightning = { git = "https://github.com/Evanfeenstra/rust-lightning", branch = "v0.0.108-branch" } - diff --git a/crypter/src/chacha.rs b/crypter/src/chacha.rs deleted file mode 100644 index fd03189..0000000 --- a/crypter/src/chacha.rs +++ /dev/null @@ -1,59 +0,0 @@ -use anyhow::anyhow; -use lightning::util::chacha20poly1305rfc::ChaCha20Poly1305RFC; - -pub const MSG_LEN: usize = 32; -pub const KEY_LEN: usize = 32; -pub const NONCE_END_LEN: usize = 8; -pub const TAG_LEN: usize = 16; -pub const CIPHER_LEN: usize = MSG_LEN + NONCE_END_LEN + TAG_LEN; - -pub fn encrypt( - plaintext: [u8; MSG_LEN], - key: [u8; KEY_LEN], - nonce_end: [u8; NONCE_END_LEN], -) -> anyhow::Result<[u8; CIPHER_LEN]> { - let mut nonce = [0; 4 + NONCE_END_LEN]; - nonce[4..].copy_from_slice(&nonce_end); - let mut chacha = ChaCha20Poly1305RFC::new(&key, &nonce, &[0; 0]); - let mut res = [0; MSG_LEN]; - let mut tag = [0; TAG_LEN]; - chacha.encrypt(&plaintext[..], &mut res[0..plaintext.len()], &mut tag); - let mut ret = [0; CIPHER_LEN]; - ret[..MSG_LEN].copy_from_slice(&res); - ret[MSG_LEN..MSG_LEN + NONCE_END_LEN].copy_from_slice(&nonce_end); - ret[MSG_LEN + NONCE_END_LEN..].copy_from_slice(&tag); - Ok(ret) -} - -pub fn decrypt(ciphertext: [u8; CIPHER_LEN], key: [u8; KEY_LEN]) -> anyhow::Result<[u8; MSG_LEN]> { - let mut nonce = [0; 4 + NONCE_END_LEN]; - nonce[4..].copy_from_slice(&ciphertext[MSG_LEN..MSG_LEN + NONCE_END_LEN]); - let mut tag = [0; TAG_LEN]; - tag.copy_from_slice(&ciphertext[MSG_LEN + NONCE_END_LEN..]); - let mut chacha2 = ChaCha20Poly1305RFC::new(&key, &nonce, &[0; 0]); - let mut dec = [0; MSG_LEN]; - let ok = chacha2.decrypt(&ciphertext[..MSG_LEN], &mut dec, &tag); - if ok { - Ok(dec) - } else { - Err(anyhow!("failed chacha authentication")) - } -} - -#[cfg(test)] -mod tests { - use crate::chacha::{decrypt, encrypt, KEY_LEN, MSG_LEN, NONCE_END_LEN}; - use rand::{rngs::OsRng, RngCore}; - - #[test] - fn test_chacha() -> anyhow::Result<()> { - let key = [9; KEY_LEN]; - let plaintext = [1; MSG_LEN]; - let mut nonce_end = [0; NONCE_END_LEN]; - OsRng.fill_bytes(&mut nonce_end); - let cipher = encrypt(plaintext, key, nonce_end)?; - let plain = decrypt(cipher, key)?; - assert_eq!(plaintext, plain); - Ok(()) - } -} diff --git a/crypter/src/ecdh.rs b/crypter/src/ecdh.rs deleted file mode 100644 index cc55641..0000000 --- a/crypter/src/ecdh.rs +++ /dev/null @@ -1,47 +0,0 @@ -use secp256k1::ecdh::SharedSecret; -use secp256k1::{SecretKey, PublicKey}; -use anyhow::Result; - -pub const PUBLIC_KEY_LEN: usize = 33; -pub const PRIVATE_KEY_LEN: usize = 32; -pub const SECRET_LEN: usize = 32; - -pub fn derive_shared_secret_from_slice(their_public_key: [u8; PUBLIC_KEY_LEN], my_private_key: [u8; PRIVATE_KEY_LEN]) -> Result<[u8; SECRET_LEN]> { - let public_key = PublicKey::from_slice(&their_public_key[..])?; - let private_key = SecretKey::from_slice(&my_private_key[..])?; - Ok(derive_shared_secret(&public_key, &private_key).secret_bytes()) -} - -pub fn derive_shared_secret(their_public_key: &PublicKey, my_private_key: &SecretKey) -> SharedSecret { - SharedSecret::new(their_public_key, my_private_key) -} - -#[cfg(test)] -mod tests { - use crate::ecdh::{derive_shared_secret, derive_shared_secret_from_slice}; - use rand::thread_rng; - use secp256k1::Secp256k1; - - #[test] - fn test_ecdh() -> anyhow::Result<()> { - let s = Secp256k1::new(); - let (sk1, pk1) = s.generate_keypair(&mut thread_rng()); - let (sk2, pk2) = s.generate_keypair(&mut thread_rng()); - let sec1 = derive_shared_secret(&pk2, &sk1); - let sec2 = derive_shared_secret(&pk1, &sk2); - assert_eq!(sec1, sec2); - Ok(()) - } - - #[test] - fn test_ecdh_from_slice() -> anyhow::Result<()> { - let s = Secp256k1::new(); - let (sk1, pk1) = s.generate_keypair(&mut thread_rng()); - let (sk2, pk2) = s.generate_keypair(&mut thread_rng()); - let sec1 = derive_shared_secret_from_slice(pk2.serialize(), sk1.secret_bytes())?; - let sec2 = derive_shared_secret_from_slice(pk1.serialize(), sk2.secret_bytes())?; - assert_eq!(sec1, sec2); - Ok(()) - } - -} \ No newline at end of file diff --git a/crypter/src/lib.rs b/crypter/src/lib.rs deleted file mode 100644 index e81c883..0000000 --- a/crypter/src/lib.rs +++ /dev/null @@ -1,38 +0,0 @@ -pub mod chacha; -pub mod ecdh; - -pub use secp256k1; - -#[cfg(test)] -mod tests { - use crate::chacha::{decrypt, encrypt, MSG_LEN, NONCE_END_LEN}; - use crate::ecdh::derive_shared_secret_from_slice; - use secp256k1::rand::{rngs::OsRng, thread_rng, RngCore}; - use secp256k1::Secp256k1; - - #[test] - fn test_crypter() -> anyhow::Result<()> { - // two keypairs - let s = Secp256k1::new(); - let (sk1, pk1) = s.generate_keypair(&mut thread_rng()); - let (sk2, pk2) = s.generate_keypair(&mut thread_rng()); - - // derive shared secrets - let sec1 = derive_shared_secret_from_slice(pk2.serialize(), sk1.secret_bytes())?; - let sec2 = derive_shared_secret_from_slice(pk1.serialize(), sk2.secret_bytes())?; - assert_eq!(sec1, sec2); - - // encrypt plaintext with sec1 - let plaintext = [1; MSG_LEN]; - let mut nonce_end = [0; NONCE_END_LEN]; - OsRng.fill_bytes(&mut nonce_end); - let cipher = encrypt(plaintext, sec1, nonce_end)?; - - // decrypt with sec2 - let plain = decrypt(cipher, sec2)?; - assert_eq!(plaintext, plain); - - println!("PLAINTEXT MATCHES!"); - Ok(()) - } -} diff --git a/parser/Cargo.toml b/parser/Cargo.toml index e126496..a6c9c26 100644 --- a/parser/Cargo.toml +++ b/parser/Cargo.toml @@ -4,7 +4,7 @@ version = "0.1.0" edition = "2021" [dependencies] -vls-protocol = { git = "https://gitlab.com/Evanfeenstra/validating-lightning-signer", branch = "sphinx-key-1.2" } +vls-protocol = { git = "https://gitlab.com/lightning-signer/validating-lightning-signer.git" } serde = { version = "1.0", default-features = false } serde_bolt = { version = "0.2", default-features = false } diff --git a/persister/Cargo.toml b/persister/Cargo.toml index 0e45ce8..3f53d64 100644 --- a/persister/Cargo.toml +++ b/persister/Cargo.toml @@ -6,7 +6,7 @@ edition = "2021" # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html [dependencies] -lightning-signer-server = { git = "https://gitlab.com/Evanfeenstra/validating-lightning-signer", branch = "sphinx-key-1.2", default-features = false, features = ["persist", "secp-lowmemory", "std"] } +lightning-signer-server = { git = "https://gitlab.com/lightning-signer/validating-lightning-signer.git", default-features = false, features = ["persist", "secp-lowmemory"] } serde = { version = "1.0.105" } hex = "0.4.3" fsdb = "0.1.11" diff --git a/persister/src/lib.rs b/persister/src/lib.rs index 3ce3246..8cc3c43 100644 --- a/persister/src/lib.rs +++ b/persister/src/lib.rs @@ -4,11 +4,11 @@ use lightning_signer::bitcoin::secp256k1::PublicKey; use lightning_signer::chain::tracker::ChainTracker; use lightning_signer::channel::{Channel, ChannelId, ChannelStub}; use lightning_signer::monitor::ChainMonitor; -use lightning_signer::node::NodeConfig; +use lightning_signer::node::{NodeConfig, NodeState as CoreNodeState}; use lightning_signer::persist::Persist; use lightning_signer::policy::validator::EnforcementState; use lightning_signer_server::persist::model::{ - AllowlistItemEntry, ChainTrackerEntry, ChannelEntry, NodeEntry, + AllowlistItemEntry, ChainTrackerEntry, ChannelEntry, NodeEntry, NodeStateEntry, }; use std::string::String; @@ -20,6 +20,7 @@ const FAT32_MAXFILENAMESIZE: usize = 8; pub struct FsPersister { nodes: Bucket, + states: Bucket, channels: DoubleBucket, allowlist: Bucket, chaintracker: Bucket, @@ -32,6 +33,7 @@ impl FsPersister { let max = Some(FAT32_MAXFILENAMESIZE); Self { nodes: db.bucket("nodes", max).expect("fail nodes"), + states: db.bucket("states", max).expect("fail states"), channels: db.double_bucket("channel", max).expect("fail channel"), allowlist: db.bucket("allowlis", max).expect("fail allowlis"), chaintracker: db.bucket("chaintra", max).expect("fail chaintra"), @@ -46,16 +48,24 @@ fn get_channel_key(channel_id: &[u8]) -> &[u8] { } impl Persist for FsPersister { - fn new_node(&self, node_id: &PublicKey, config: &NodeConfig, seed: &[u8]) { + fn new_node(&self, node_id: &PublicKey, config: &NodeConfig, state: &CoreNodeState, seed: &[u8]) { let pk = hex::encode(node_id.serialize()); - let entry = NodeEntry { + let state_entry = state.into(); + let _ = self.states.put(&pk, state_entry); + let node_entry = NodeEntry { seed: seed.to_vec(), key_derivation_style: config.key_derivation_style as u8, network: config.network.to_string(), }; - let _ = self.nodes.put(&pk, entry); + let _ = self.nodes.put(&pk, node_entry); let _ = self.pubkeys.put(&pk, node_id.clone()); } + fn update_node(&self, node_id: &PublicKey, state: &CoreNodeState) -> Result<(), ()> { + let pk = hex::encode(node_id.serialize()); + let state_entry = state.into(); + let _ = self.states.put(&pk, state_entry); + Ok(()) + } fn delete_node(&self, node_id: &PublicKey) { let pk = hex::encode(node_id.serialize()); // clear all channel entries within "pk" sub-bucket @@ -180,7 +190,24 @@ impl Persist for FsPersister { for pk in list { if let Ok(pubkey) = self.pubkeys.get(&pk) { if let Ok(node) = self.nodes.get(&pk) { - res.push((pubkey, node.into())); + if let Ok(state_entry) = self.states.get(&pk) { + let state = CoreNodeState { + invoices: Default::default(), + issued_invoices: Default::default(), + payments: Default::default(), + excess_amount: 0, + log_prefix: "".to_string(), + velocity_control: state_entry.velocity_control.into(), + + }; + let entry = CoreNodeEntry { + seed: node.seed, + key_derivation_style: node.key_derivation_style, + network: node.network, + state, + }; + res.push((pubkey, entry)); + } } } } diff --git a/signer/Cargo.toml b/signer/Cargo.toml index 85185ba..920d68c 100644 --- a/signer/Cargo.toml +++ b/signer/Cargo.toml @@ -7,7 +7,7 @@ edition = "2018" [dependencies] sphinx-key-parser = { path = "../parser" } sphinx-key-persister = { path = "../persister" } -vls-protocol-signer = { git = "https://gitlab.com/Evanfeenstra/validating-lightning-signer", branch = "sphinx-key-1.2", default-features = false, features = ["std", "secp-lowmemory"] } +vls-protocol-signer = { git = "https://gitlab.com/lightning-signer/validating-lightning-signer.git", default-features = false, features = ["std", "secp-lowmemory"] } anyhow = {version = "1", features = ["backtrace"]} log = "0.4" rand = { version = "0.8" } diff --git a/signer/src/lib.rs b/signer/src/lib.rs index 753a9d1..c328d3f 100644 --- a/signer/src/lib.rs +++ b/signer/src/lib.rs @@ -3,6 +3,11 @@ mod randomstartingtime; pub use vls_protocol_signer::lightning_signer; pub use vls_protocol_signer::vls_protocol; use lightning_signer::persist::Persist; +use lightning_signer::policy::simple_validator::{make_simple_policy, SimpleValidatorFactory}; +use lightning_signer::policy::filter::PolicyFilter; +use lightning_signer::node::NodeServices; +use lightning_signer::util::clock::StandardClock; +use lightning_signer::util::velocity::{VelocityControlIntervalType, VelocityControlSpec}; use randomstartingtime::RandomStartingTimeFactory; // use lightning_signer::persist::DummyPersister; use std::sync::Arc; @@ -24,29 +29,45 @@ pub const ROOT_STORE: &str = "/sdcard/store"; pub fn init(bytes: Vec, network: Network) -> anyhow::Result { // let persister: Arc = Arc::new(DummyPersister); - let persister: Arc = Arc::new(FsPersister::new(ROOT_STORE)); let mut md = MsgDriver::new(bytes); let (sequence, dbid) = read_serial_request_header(&mut md).expect("read init header"); assert_eq!(dbid, 0); assert_eq!(sequence, 0); let init: msgs::HsmdInit2 = msgs::read_message(&mut md).expect("failed to read init message"); log::info!("init {:?}", init); + + let seed = init.dev_seed.as_ref().map(|s| s.0).expect("no seed"); let allowlist = init .dev_allowlist .iter() .map(|s| from_wire_string(s)) .collect::>(); log::info!("allowlist {:?}", allowlist); - let seed = init.dev_seed.as_ref().map(|s| s.0).expect("no seed"); - let starting_time_factory = RandomStartingTimeFactory::new(); + let mut policy = make_simple_policy(network); + policy.filter = PolicyFilter::new_permissive(); + let velocity_spec = VelocityControlSpec { + limit: 10, + interval_type: VelocityControlIntervalType::Hourly, + }; + policy.global_velocity_control = velocity_spec; + let validator_factory = Arc::new(SimpleValidatorFactory::new_with_policy(policy)); + let random_time_factory = RandomStartingTimeFactory::new(); + let persister: Arc = Arc::new(FsPersister::new(ROOT_STORE)); + let clock = Arc::new(StandardClock()); + let services = NodeServices { + validator_factory, + starting_time_factory: random_time_factory, + persister, + clock, + }; + log::info!("create root handler now"); let root_handler = RootHandler::new( network, 0, Some(seed), - persister, allowlist, - &starting_time_factory, + services, ); log::info!("root_handler created"); let init_reply = root_handler diff --git a/signer/src/randomstartingtime.rs b/signer/src/randomstartingtime.rs index cd8354b..5fd17a8 100644 --- a/signer/src/randomstartingtime.rs +++ b/signer/src/randomstartingtime.rs @@ -1,6 +1,7 @@ use vls_protocol_signer::lightning_signer; use lightning_signer::signer::StartingTimeFactory; use rand::{rngs::OsRng, RngCore}; +use std::sync::Arc; /// A starting time factory which uses entropy from the RNG pub(crate) struct RandomStartingTimeFactory {} @@ -12,7 +13,7 @@ impl StartingTimeFactory for RandomStartingTimeFactory { } impl RandomStartingTimeFactory { - pub(crate) fn new() -> Box { - Box::new(RandomStartingTimeFactory {}) + pub(crate) fn new() -> Arc { + Arc::new(RandomStartingTimeFactory {}) } } diff --git a/sphinx-key/Cargo.lock b/sphinx-key/Cargo.lock index 9439b0c..742fae0 100644 --- a/sphinx-key/Cargo.lock +++ b/sphinx-key/Cargo.lock @@ -17,6 +17,17 @@ version = "1.0.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f26201604c87b1e01bd3d98f8d5d9a8fcbb815e8cedb41ffccbeb4bf593a35fe" +[[package]] +name = "aead" +version = "0.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5c192eb8f11fc081b0fe4259ba5af04217d4e0faddd02417310a927911abd7c8" +dependencies = [ + "crypto-common", + "generic-array", + "heapless", +] + [[package]] name = "ahash" version = "0.7.6" @@ -39,9 +50,9 @@ dependencies = [ [[package]] name = "anyhow" -version = "1.0.61" +version = "1.0.62" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "508b352bb5c066aac251f6daf6b36eccd03e8a88e8081cd44959ea277a3af9a8" +checksum = "1485d4d2cc45e7b201ee3767015c96faa5904387c9d87c6efdd0fb511f12d305" dependencies = [ "backtrace", ] @@ -127,9 +138,9 @@ checksum = "904dfeac50f3cdaba28fc6f57fdcddb75f49ed61346676a78c4ffe55877802fd" [[package]] name = "bech32" -version = "0.8.1" +version = "0.9.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cf9ff0bbfd639f15c74af777d81383cf53efb7c93613f6cab67c6c11e05bbf8b" +checksum = "d86b93f97252c47b41663388e6d155714a9d0c398b99f1005cbc5f978b29f445" [[package]] name = "bindgen" @@ -168,9 +179,9 @@ checksum = "dcb6dd1c2376d2e096796e234a70e17e94cc2d5d54ff8ce42b28cef1d0d359a4" [[package]] name = "bitcoin" -version = "0.28.1" +version = "0.29.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "05bba324e6baf655b882df672453dbbc527bc938cadd27750ae510aaccc3a66a" +checksum = "9cb36de3b18ad25f396f9168302e36fb7e1e8923298ab3127da252d288d5af9d" dependencies = [ "bech32", "bitcoin_hashes", @@ -180,9 +191,9 @@ dependencies = [ [[package]] name = "bitcoin_hashes" -version = "0.10.0" +version = "0.11.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "006cc91e1a1d99819bc5b8214be3555c1f0611b169f527a1fdc54ed1f2b745b0" +checksum = "90064b8dee6815a6470d60bad07bbbaee885c0e12d04177138fa3291a01b7bc4" dependencies = [ "serde", ] @@ -202,7 +213,7 @@ checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a" [[package]] name = "bolt-derive" version = "0.1.0" -source = "git+https://gitlab.com/Evanfeenstra/validating-lightning-signer?branch=sphinx-key-1.2#676614e29fb87fd33745761fbb6b6327edd8bae0" +source = "git+https://gitlab.com/lightning-signer/validating-lightning-signer.git#86552cd078cc4d423a175e9df5d5abc503096601" dependencies = [ "proc-macro2", "quote", @@ -220,9 +231,9 @@ dependencies = [ [[package]] name = "bumpalo" -version = "3.10.0" +version = "3.11.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "37ccbd214614c6783386c1af30caf03192f17891059cecc394b4fb119e363de3" +checksum = "c1ad822118d20d2c234f427000d5acc36eabe1e29a348c89b63dd60b13f28e5d" [[package]] name = "byteorder" @@ -299,12 +310,58 @@ version = "1.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" +[[package]] +name = "chacha20" +version = "0.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c7fc89c7c5b9e7a02dfe45cd2367bae382f9ed31c61ca8debe5f827c420a2f08" +dependencies = [ + "cfg-if", + "cipher", + "cpufeatures", +] + +[[package]] +name = "chacha20poly1305" +version = "0.10.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "10cd79432192d1c0f4e1a0fef9527696cc039165d729fb41b3f4f4f354c2dc35" +dependencies = [ + "aead", + "chacha20", + "cipher", + "poly1305", + "zeroize", +] + +[[package]] +name = "chrono" +version = "0.4.22" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bfd4d1b31faaa3a89d7934dbded3111da0d2ef28e3ebccdb4f0179f5929d1ef1" +dependencies = [ + "num-integer", + "num-traits", + "serde", +] + [[package]] name = "chunked_transfer" version = "1.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "fff857943da45f546682664a79488be82e69e43c1a7a2307679ab9afb3a66d2e" +[[package]] +name = "cipher" +version = "0.4.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d1873270f8f7942c191139cb8a40fd228da6c3fd2fc376d7e92d47aa14aeb59e" +dependencies = [ + "crypto-common", + "inout", + "zeroize", +] + [[package]] name = "clang-sys" version = "1.3.3" @@ -367,6 +424,15 @@ dependencies = [ "volatile-register", ] +[[package]] +name = "cpufeatures" +version = "0.2.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dc948ebb96241bb40ab73effeb80d9f93afaad49359d159a5e61be51619fe813" +dependencies = [ + "libc", +] + [[package]] name = "crc32fast" version = "1.3.2" @@ -433,6 +499,16 @@ dependencies = [ "once_cell", ] +[[package]] +name = "crypto-common" +version = "0.1.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1bfb12502f3fc46cca1bb51ac28df9d618d813cdc3d2f25b9fe775a34af26bb3" +dependencies = [ + "generic-array", + "typenum", +] + [[package]] name = "cstr_core" version = "0.2.6" @@ -455,8 +531,18 @@ version = "0.13.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a01d95850c592940db9b8194bc39f4bc0e89dee5c4265e4b1807c34a9aba453c" dependencies = [ - "darling_core", - "darling_macro", + "darling_core 0.13.4", + "darling_macro 0.13.4", +] + +[[package]] +name = "darling" +version = "0.14.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4529658bdda7fd6769b8614be250cdcfc3aeb0ee72fe66f9e41e5e5eb73eac02" +dependencies = [ + "darling_core 0.14.1", + "darling_macro 0.14.1", ] [[package]] @@ -464,6 +550,19 @@ name = "darling_core" version = "0.13.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "859d65a907b6852c9361e3185c862aae7fafd2887876799fa55f5f99dc40d610" +dependencies = [ + "fnv", + "ident_case", + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "darling_core" +version = "0.14.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "649c91bc01e8b1eac09fb91e8dbc7d517684ca6be8ebc75bb9cafc894f9fdb6f" dependencies = [ "fnv", "ident_case", @@ -479,7 +578,18 @@ version = "0.13.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9c972679f83bdf9c42bd905396b6c3588a843a17f0f16dfcfa3e2c5d57441835" dependencies = [ - "darling_core", + "darling_core 0.13.4", + "quote", + "syn", +] + +[[package]] +name = "darling_macro" +version = "0.14.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ddfc69c5bfcbd2fc09a0f38451d2daf0e372e367986a83906d1b0dbc88134fb5" +dependencies = [ + "darling_core 0.14.1", "quote", "syn", ] @@ -512,9 +622,9 @@ checksum = "212d0f5754cb6769937f4501cc0e67f4f4483c8d2c3e1e922ee9edbe4ab4c7c0" [[package]] name = "either" -version = "1.7.0" +version = "1.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3f107b87b6afc2a64fd13cac55fe06d6c8859f12d4b14cbcdd2c67d0976781be" +checksum = "90e5c1c8368803113bf0c9584fc495a58b86dc8a29edbf8fe877d21d9507e797" [[package]] name = "embedded-hal" @@ -585,9 +695,9 @@ dependencies = [ [[package]] name = "embuild" -version = "0.30.2" +version = "0.30.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "75c5cc517bb6e543b6dc30a364d5a20831160fa47b9539c8f0e83abdb32c5fb1" +checksum = "01f030081cf69373a6c4b811934a81c7c9d3a11066ef22b564327a33f9991125" dependencies = [ "anyhow", "bindgen", @@ -626,7 +736,7 @@ version = "0.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ea83a3fbdc1d999ccfbcbee717eab36f8edf2d71693a23ce0d7cca19e085304c" dependencies = [ - "darling", + "darling 0.13.4", "proc-macro2", "quote", "syn", @@ -656,9 +766,9 @@ dependencies = [ [[package]] name = "esp-idf-hal" -version = "0.38.0" +version = "0.38.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cc998eadd4eb0b3da435b72b5f4ac29b16b8937224bc08d49e5701038a1ab2d6" +checksum = "aa416b08c24fc6439b59b7de329738e041af9bbddc733267e47085399f372487" dependencies = [ "anyhow", "embedded-hal 0.2.7", @@ -695,7 +805,7 @@ dependencies = [ "anyhow", "bindgen", "cargo_metadata", - "embuild 0.30.2", + "embuild 0.30.3", "envy", "regex", "serde", @@ -831,10 +941,21 @@ dependencies = [ "slab", ] +[[package]] +name = "generic-array" +version = "0.14.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bff49e947297f3312447abdca79f45f4738097cc82b06e72054d2223f601f1b9" +dependencies = [ + "typenum", + "version_check", +] + [[package]] name = "getrandom" -version = "0.2.3" -source = "git+https://github.com/esp-rs-compat/getrandom.git#b8cb133e304d9ae60742b35d5dc6156360796e2e" +version = "0.2.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4eb1a864a501629691edf6c15a593b7a51eebaa1e8468e9ddc623de7c9b58ec6" dependencies = [ "cfg-if", "libc", @@ -939,12 +1060,6 @@ dependencies = [ "libc", ] -[[package]] -name = "hex" -version = "0.3.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "805026a5d0141ffc30abb3be3173848ad46a1b1664fe632428479619a3644d77" - [[package]] name = "hex" version = "0.4.3" @@ -1002,6 +1117,15 @@ dependencies = [ "hashbrown 0.12.3", ] +[[package]] +name = "inout" +version = "0.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a0c10553d664a4d0bcff9f4215d0aac67a639cc68ef660840afe309b807bc9f5" +dependencies = [ + "generic-array", +] + [[package]] name = "instant" version = "0.1.12" @@ -1049,9 +1173,9 @@ checksum = "830d08ce1d1d941e6b30645f1a0eb5643013d835ce3779a5fc208261dbe10f55" [[package]] name = "libc" -version = "0.2.131" +version = "0.2.132" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "04c3b4822ccebfa39c02fc03d1534441b22ead323fa0f48bb7ddd8e6ba076a40" +checksum = "8371e4e5341c3a96db127eb2465ac681ced4c433e01dd0e938adbef26ba93ba5" [[package]] name = "libloading" @@ -1065,17 +1189,16 @@ dependencies = [ [[package]] name = "lightning" -version = "0.0.108" -source = "git+https://github.com/Evanfeenstra/rust-lightning?branch=v0.0.108-branch#c3aa9558abb5fc3d0390b58bc72331502ed34747" +version = "0.0.110" +source = "git+https://github.com/lightningdevkit/rust-lightning.git?rev=ea5b62fff69847941434fb51562e302eb4e7ff4b#ea5b62fff69847941434fb51562e302eb4e7ff4b" dependencies = [ "bitcoin", ] [[package]] name = "lightning-invoice" -version = "0.16.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "eaafc1cebaf9ea8d2a57e60aae9fe6095554b8305714f8452cd8a20a3aa5b7ba" +version = "0.18.0" +source = "git+https://github.com/lightningdevkit/rust-lightning.git?rev=ea5b62fff69847941434fb51562e302eb4e7ff4b#ea5b62fff69847941434fb51562e302eb4e7ff4b" dependencies = [ "bech32", "bitcoin_hashes", @@ -1087,7 +1210,7 @@ dependencies = [ [[package]] name = "lightning-signer-core" version = "0.1.0-5" -source = "git+https://gitlab.com/Evanfeenstra/validating-lightning-signer?branch=sphinx-key-1.2#676614e29fb87fd33745761fbb6b6327edd8bae0" +source = "git+https://gitlab.com/lightning-signer/validating-lightning-signer.git#86552cd078cc4d423a175e9df5d5abc503096601" dependencies = [ "anyhow", "bitcoin", @@ -1097,27 +1220,22 @@ dependencies = [ "lightning", "lightning-invoice", "log", - "rand", "scopeguard", ] [[package]] name = "lightning-signer-server" version = "0.1.0-5" -source = "git+https://gitlab.com/Evanfeenstra/validating-lightning-signer?branch=sphinx-key-1.2#676614e29fb87fd33745761fbb6b6327edd8bae0" +source = "git+https://gitlab.com/lightning-signer/validating-lightning-signer.git#86552cd078cc4d423a175e9df5d5abc503096601" dependencies = [ "anyhow", "async-trait", - "env_logger", - "hex 0.3.2", + "hex", "lightning-signer-core", "log", - "serde", - "serde_json", - "serde_with", - "test-log", - "time", + "time 0.2.27", "tonic-build", + "vls-persist", ] [[package]] @@ -1215,6 +1333,16 @@ dependencies = [ "minimal-lexical", ] +[[package]] +name = "num-integer" +version = "0.1.45" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "225d3389fb3509a24c93f5c29eb6bde2586b98d9f016636dff58d7c6f7569cd9" +dependencies = [ + "autocfg", + "num-traits", +] + [[package]] name = "num-traits" version = "0.2.15" @@ -1255,6 +1383,15 @@ dependencies = [ "syn", ] +[[package]] +name = "num_threads" +version = "0.1.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2819ce041d2ee131036f4fc9d6ae7ae125a3a40e97ba64d04fe799ad9dabbb44" +dependencies = [ + "libc", +] + [[package]] name = "object" version = "0.29.0" @@ -1266,9 +1403,15 @@ dependencies = [ [[package]] name = "once_cell" -version = "1.13.0" +version = "1.13.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "18a6dbe30758c9f83eb00cbea4ac95966305f5a7772f3f42ebfc7fc7eddbd8e1" +checksum = "074864da206b4973b84eb91683020dbefd6a8c3f0f38e054d93954e891935e4e" + +[[package]] +name = "opaque-debug" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "624a8340c38c1b80fd549087862da4ba43e08858af025b236e509b6649fc13d5" [[package]] name = "os_str_bytes" @@ -1316,6 +1459,17 @@ version = "0.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8b870d8c151b6f2fb93e84a13146138f05d02ed11c7e7c54f8826aaaf7c9f184" +[[package]] +name = "poly1305" +version = "0.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8159bd90725d2df49889a078b54f4f79e87f1f8a8444194cdca81d38f5393abf" +dependencies = [ + "cpufeatures", + "opaque-debug", + "universal-hash", +] + [[package]] name = "ppv-lite86" version = "0.2.16" @@ -1662,9 +1816,11 @@ dependencies = [ [[package]] name = "secp256k1" -version = "0.22.0" -source = "git+https://github.com/Evanfeenstra/rust-secp256k1?branch=v0.22.0-new-rand#f7548146873bb5ec1d8824c1c85eb9fc57b3468d" +version = "0.24.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b7649a0b3ffb32636e60c7ce0d70511eda9c52c658cd0634e194d5a19943aeff" dependencies = [ + "bitcoin_hashes", "rand", "secp256k1-sys", "serde", @@ -1672,8 +1828,9 @@ dependencies = [ [[package]] name = "secp256k1-sys" -version = "0.5.0" -source = "git+https://github.com/Evanfeenstra/rust-secp256k1?branch=v0.22.0-new-rand#f7548146873bb5ec1d8824c1c85eb9fc57b3468d" +version = "0.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7058dc8eaf3f2810d7828680320acda0b25a288f6d288e19278e249bbf74226b" dependencies = [ "cc", ] @@ -1704,9 +1861,9 @@ checksum = "388a1df253eca08550bef6c72392cfe7c30914bf41df5269b68cbd6ff8f570a3" [[package]] name = "serde" -version = "1.0.143" +version = "1.0.144" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "53e8e5d5b70924f74ff5c6d64d9a5acd91422117c60f48c4e07855238a254553" +checksum = "0f747710de3dcd43b88c9168773254e809d8ddbdf9653b84e2554ab219f17860" dependencies = [ "serde_derive", ] @@ -1723,9 +1880,9 @@ dependencies = [ [[package]] name = "serde_derive" -version = "1.0.143" +version = "1.0.144" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d3d8e8de557aee63c26b85b947f5e59b690d0454c753f3adeb5cd7835ab88391" +checksum = "94ed3a816fb1d101812f83e789f888322c34e291f894f19590dc310963e87a00" dependencies = [ "proc-macro2", "quote", @@ -1734,9 +1891,9 @@ dependencies = [ [[package]] name = "serde_json" -version = "1.0.83" +version = "1.0.85" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "38dd04e3c8279e75b31ef29dbdceebfe5ad89f4d0937213c53f7d49d01b3d5a7" +checksum = "e55a28e3aaef9d5ce0506d0a14dbba8054ddc7e499ef522dd8b26859ec9d4a44" dependencies = [ "itoa", "ryu", @@ -1757,22 +1914,26 @@ dependencies = [ [[package]] name = "serde_with" -version = "1.14.0" +version = "2.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "678b5a069e50bf00ecd22d0cd8ddf7c236f68581b03db652061ed5eb13a312ff" +checksum = "89df7a26519371a3cce44fbb914c2819c84d9b897890987fa3ab096491cc0ea8" dependencies = [ - "hex 0.4.3", + "base64", + "chrono", + "hex", "serde", + "serde_json", "serde_with_macros", + "time 0.3.13", ] [[package]] name = "serde_with_macros" -version = "1.5.2" +version = "2.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e182d6ec6f05393cc0e5ed1bf81ad6db3a8feedf8ee515ecdd369809bcce8082" +checksum = "de337f322382fcdfbb21a014f7c224ee041a23785651db67b9827403178f698f" dependencies = [ - "darling", + "darling 0.14.1", "proc-macro2", "quote", "syn", @@ -1808,6 +1969,17 @@ dependencies = [ "autocfg", ] +[[package]] +name = "sphinx-crypter" +version = "0.1.0" +source = "git+https://github.com/stakwork/sphinx-rs.git#40ea52b22cab30eb2cae88a8f2f25b84d656da14" +dependencies = [ + "anyhow", + "chacha20poly1305", + "rand", + "secp256k1", +] + [[package]] name = "sphinx-key" version = "0.1.0" @@ -1820,27 +1992,17 @@ dependencies = [ "esp-idf-hal", "esp-idf-svc", "esp-idf-sys", - "hex 0.4.3", + "hex", "log", "rmp-serde", "serde", "serde_json", "serde_urlencoded", - "sphinx-key-crypter", + "sphinx-crypter", "sphinx-key-signer", "url", ] -[[package]] -name = "sphinx-key-crypter" -version = "0.1.0" -dependencies = [ - "anyhow", - "lightning", - "rand", - "secp256k1", -] - [[package]] name = "sphinx-key-parser" version = "0.1.0" @@ -1855,7 +2017,7 @@ name = "sphinx-key-persister" version = "0.1.0" dependencies = [ "fsdb", - "hex 0.4.3", + "hex", "lightning-signer-server", "log", "serde", @@ -2002,6 +2164,12 @@ dependencies = [ "syn", ] +[[package]] +name = "subtle" +version = "2.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6bdef32e8150c2a081110b42772ffe7d7c9032b606bc226c8260fd97e0976601" + [[package]] name = "syn" version = "1.0.99" @@ -2036,17 +2204,6 @@ dependencies = [ "winapi-util", ] -[[package]] -name = "test-log" -version = "0.2.11" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "38f0c854faeb68a048f0f2dc410c5ddae3bf83854ef0e4977d58306a5edef50e" -dependencies = [ - "proc-macro2", - "quote", - "syn", -] - [[package]] name = "textwrap" version = "0.15.0" @@ -2097,6 +2254,16 @@ dependencies = [ "winapi", ] +[[package]] +name = "time" +version = "0.3.13" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "db76ff9fa4b1458b3c7f077f3ff9887394058460d21e634355b273aaf11eea45" +dependencies = [ + "libc", + "num_threads", +] + [[package]] name = "time-macros" version = "0.1.1" @@ -2156,6 +2323,12 @@ dependencies = [ "syn", ] +[[package]] +name = "typenum" +version = "1.15.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dcf81ac59edc17cc8697ff311e8f5ef2d99fcbd9817b34cec66f90b6c3dfd987" + [[package]] name = "unicode-bidi" version = "0.3.8" @@ -2183,6 +2356,16 @@ version = "1.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7e8820f5d777f6224dc4be3632222971ac30164d4a258d595640799554ebfd99" +[[package]] +name = "universal-hash" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7d3160b73c9a19f7e2939a2fdad446c57c1bbbbf4d919d3213ff1267a580d8b5" +dependencies = [ + "crypto-common", + "subtle", +] + [[package]] name = "untrusted" version = "0.7.1" @@ -2230,10 +2413,22 @@ version = "0.9.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "49874b5167b65d7193b8aba1567f5c7d93d001cafc34600cee003eda787e483f" +[[package]] +name = "vls-persist" +version = "0.1.0" +source = "git+https://gitlab.com/lightning-signer/validating-lightning-signer.git#86552cd078cc4d423a175e9df5d5abc503096601" +dependencies = [ + "hex", + "lightning-signer-core", + "log", + "serde", + "serde_with", +] + [[package]] name = "vls-protocol" version = "0.1.0" -source = "git+https://gitlab.com/Evanfeenstra/validating-lightning-signer?branch=sphinx-key-1.2#676614e29fb87fd33745761fbb6b6327edd8bae0" +source = "git+https://gitlab.com/lightning-signer/validating-lightning-signer.git#86552cd078cc4d423a175e9df5d5abc503096601" dependencies = [ "bolt-derive", "log", @@ -2245,7 +2440,7 @@ dependencies = [ [[package]] name = "vls-protocol-signer" version = "0.1.0" -source = "git+https://gitlab.com/Evanfeenstra/validating-lightning-signer?branch=sphinx-key-1.2#676614e29fb87fd33745761fbb6b6327edd8bae0" +source = "git+https://gitlab.com/lightning-signer/validating-lightning-signer.git#86552cd078cc4d423a175e9df5d5abc503096601" dependencies = [ "bit-vec", "lightning-signer-core", @@ -2282,9 +2477,9 @@ dependencies = [ [[package]] name = "wasi" -version = "0.10.2+wasi-snapshot-preview1" +version = "0.11.0+wasi-snapshot-preview1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fd6fbd9a79829dd1ad0cc20627bf1ed606756a7f77edff7b66b7064f9cb327c6" +checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423" [[package]] name = "wasm-bindgen" @@ -2468,3 +2663,9 @@ name = "zero" version = "0.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5f1bc8a6b2005884962297587045002d8cfb8dcec9db332f4ca216ddc5de82c5" + +[[package]] +name = "zeroize" +version = "1.5.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c394b5bd0c6f669e7275d9c20aa90ae064cb22e75a1cad54e1b34088034b149f" diff --git a/sphinx-key/Cargo.toml b/sphinx-key/Cargo.toml index 15882d6..5679176 100644 --- a/sphinx-key/Cargo.toml +++ b/sphinx-key/Cargo.toml @@ -23,7 +23,7 @@ no_persist = [] bitflags = "1.3.2" esp-idf-sys = { version = "0.31.6", features = ["binstart"] } sphinx-key-signer = { path = "../signer", optional = true } -sphinx-key-crypter = { path = "../crypter" } +sphinx-crypter = { git = "https://github.com/stakwork/sphinx-rs.git" } embedded-svc = "0.22.1" esp-idf-svc = "0.42.1" esp-idf-hal = "0.38.0" @@ -37,12 +37,6 @@ serde_json = { version = "1.0.81", default-features = false } hex = "0.4.3" rmp-serde = "1.1.0" -[patch.crates-io] -# updates the "rand" create to use esp RNG -getrandom = { version = "0.2", git = "https://github.com/esp-rs-compat/getrandom.git" } -secp256k1 = { git = "https://github.com/Evanfeenstra/rust-secp256k1", branch = "v0.22.0-new-rand" } -lightning = { git = "https://github.com/Evanfeenstra/rust-lightning", branch = "v0.0.108-branch" } - [build-dependencies] embuild = "0.29" anyhow = "1" diff --git a/sphinx-key/sdkconfig.defaults b/sphinx-key/sdkconfig.defaults index 6de6b1b..f73fb9e 100644 --- a/sphinx-key/sdkconfig.defaults +++ b/sphinx-key/sdkconfig.defaults @@ -1,5 +1,6 @@ # Rust often needs a bit of an extra main task stack size compared to C (the default is 3K) CONFIG_ESP_MAIN_TASK_STACK_SIZE=64000 +#CONFIG_LOG_DEFAULT_LEVEL_DEBUG=y # Use this to set FreeRTOS kernel tick frequency to 1000 Hz (100 Hz by default). # This allows to use 1 ms granuality for thread sleeps (10 ms by default). diff --git a/sphinx-key/src/conn/mod.rs b/sphinx-key/src/conn/mod.rs index 0ce7cb3..ae2004c 100644 --- a/sphinx-key/src/conn/mod.rs +++ b/sphinx-key/src/conn/mod.rs @@ -1,6 +1,7 @@ pub mod wifi; pub mod http; pub mod mqtt; +pub mod sntp; mod html; diff --git a/sphinx-key/src/conn/sntp.rs b/sphinx-key/src/conn/sntp.rs new file mode 100644 index 0000000..3f79cf1 --- /dev/null +++ b/sphinx-key/src/conn/sntp.rs @@ -0,0 +1,13 @@ +use esp_idf_svc::sntp::EspSntp; +use esp_idf_svc::sntp::SyncStatus::Completed; +use std::time::Duration; +use std::thread; + +pub fn sync_time() { + let sntp = EspSntp::new_default().unwrap(); + println!("SNTP initialized"); + while sntp.get_sync_status() != Completed { + println!("Waiting for sntp sync..."); + thread::sleep(Duration::from_secs(1)); + } +} diff --git a/sphinx-key/src/core/config.rs b/sphinx-key/src/core/config.rs index ee5d715..1fc9f72 100644 --- a/sphinx-key/src/core/config.rs +++ b/sphinx-key/src/core/config.rs @@ -10,10 +10,10 @@ use embedded_svc::wifi::*; use esp_idf_svc::nvs::*; use esp_idf_svc::wifi::*; -use sphinx_key_crypter::chacha::{decrypt, CIPHER_LEN}; -use sphinx_key_crypter::ecdh::{derive_shared_secret_from_slice, PUBLIC_KEY_LEN}; -use sphinx_key_crypter::secp256k1::rand::thread_rng; -use sphinx_key_crypter::secp256k1::{Secp256k1, SecretKey, PublicKey}; +use sphinx_crypter::chacha::{decrypt, PAYLOAD_LEN}; +use sphinx_crypter::ecdh::{derive_shared_secret_from_slice, PUBLIC_KEY_LEN}; +use sphinx_crypter::secp256k1::rand::thread_rng; +use sphinx_crypter::secp256k1::{Secp256k1, SecretKey, PublicKey}; #[derive(Clone, Debug, Deserialize, Serialize)] pub struct Config { @@ -56,7 +56,7 @@ pub fn decrypt_seed(dto: ConfigDTO, sk1: SecretKey) -> Result { derive_shared_secret_from_slice(their_pk_bytes, sk1.secret_bytes())?; // decrypt seed let cipher_seed = hex::decode(dto.seed)?; - let cipher: [u8; CIPHER_LEN] = cipher_seed[..CIPHER_LEN].try_into()?; + let cipher: [u8; PAYLOAD_LEN] = cipher_seed[..PAYLOAD_LEN].try_into()?; let seed = decrypt(cipher, shared_secret)?; Ok(Config { diff --git a/sphinx-key/src/core/events.rs b/sphinx-key/src/core/events.rs index d06ef4c..b2fceb7 100644 --- a/sphinx-key/src/core/events.rs +++ b/sphinx-key/src/core/events.rs @@ -6,6 +6,7 @@ use sphinx_key_signer::lightning_signer::bitcoin::Network; use sphinx_key_signer::vls_protocol::model::PubKey; use sphinx_key_signer::{self, InitResponse}; use std::sync::mpsc; +use std::time::SystemTime; use embedded_svc::httpd::Result; use embedded_svc::mqtt::client::utils::ConnState; @@ -25,6 +26,7 @@ pub enum Event { pub enum Status { Starting, MountingSDCard, + SyncingTime, WifiAccessPoint, Configuring, ConnectingToWifi, @@ -59,6 +61,10 @@ pub fn make_event_loop( Event::Disconnected => { led_tx.send(Status::ConnectingToMqtt).unwrap(); log::info!("GOT an early Event::Disconnected msg!"); + let now = SystemTime::now() + .duration_since(SystemTime::UNIX_EPOCH) + .unwrap(); + log::info!("Tracking the time: {}", now.as_secs()); } } } diff --git a/sphinx-key/src/main.rs b/sphinx-key/src/main.rs index f88b6c6..8d5c8d8 100644 --- a/sphinx-key/src/main.rs +++ b/sphinx-key/src/main.rs @@ -5,6 +5,7 @@ mod periph; use crate::core::{config::*, events::*}; use crate::periph::led::led_control_loop; +#[allow(unused_imports)] use crate::periph::sd::{mount_sd_card, simple_fs_test}; use anyhow::Result; @@ -12,6 +13,7 @@ use esp_idf_sys as _; // If using the `binstart` feature of `esp-idf-sys`, alway use std::sync::{mpsc, Arc}; use std::thread; use std::time::Duration; +use std::time::SystemTime; use embedded_svc::storage::RawStorage; use esp_idf_hal::peripherals::Peripherals; @@ -74,6 +76,16 @@ fn main() -> Result<()> { } }; + led_tx.send(Status::SyncingTime).unwrap(); + conn::sntp::sync_time(); + let now = SystemTime::now() + .duration_since(SystemTime::UNIX_EPOCH) + .unwrap(); + println!( + "Completed the time sync, here is the UNIX time: {}", + now.as_secs(), + ); + led_tx.send(Status::ConnectingToMqtt).unwrap(); // _conn needs to stay in scope or its dropped loop { diff --git a/sphinx-key/src/periph/led.rs b/sphinx-key/src/periph/led.rs index 1d0a2eb..d0fcac1 100644 --- a/sphinx-key/src/periph/led.rs +++ b/sphinx-key/src/periph/led.rs @@ -21,6 +21,7 @@ fn states() -> BTreeMap { let mut s = BTreeMap::new(); s.insert(Status::Starting, (0x000001, 100)); s.insert(Status::MountingSDCard, (0x000102, 100)); + s.insert(Status::SyncingTime, (0x000122, 100)); s.insert(Status::WifiAccessPoint, (0x000100, 100)); s.insert(Status::Configuring, (0x010000, 20)); s.insert(Status::ConnectingToWifi, (0x010100, 350)); diff --git a/sphinx-key/src/periph/sd.rs b/sphinx-key/src/periph/sd.rs index d17ccee..5c5f7bc 100644 --- a/sphinx-key/src/periph/sd.rs +++ b/sphinx-key/src/periph/sd.rs @@ -133,6 +133,7 @@ pub fn mount_sd_card() -> anyhow::Result<()> { Ok(()) } +#[allow(dead_code)] pub fn simple_fs_test() { // Create and write a file, append a file, read a file, delete a file, create a directory, write a file diff --git a/tester/Cargo.toml b/tester/Cargo.toml index 3e6c66c..be125f6 100644 --- a/tester/Cargo.toml +++ b/tester/Cargo.toml @@ -7,7 +7,7 @@ edition = "2018" [dependencies] sphinx-key-signer = { path = "../signer" } sphinx-key-parser = { path = "../parser" } -sphinx-key-crypter = { path = "../crypter" } +sphinx-crypter = { git = "https://github.com/stakwork/sphinx-rs.git" } anyhow = {version = "1", features = ["backtrace"]} log = "0.4" rumqttc = "0.12.0" diff --git a/tester/src/config.rs b/tester/src/config.rs index 48a8ab2..ce02ec1 100644 --- a/tester/src/config.rs +++ b/tester/src/config.rs @@ -1,9 +1,9 @@ use dotenv::dotenv; use rand::{rngs::OsRng, thread_rng, RngCore}; use serde::{Deserialize, Serialize}; -use sphinx_key_crypter::chacha::{encrypt, MSG_LEN, NONCE_END_LEN}; -use sphinx_key_crypter::ecdh::{derive_shared_secret_from_slice, PUBLIC_KEY_LEN}; -use sphinx_key_crypter::secp256k1::Secp256k1; +use sphinx_crypter::chacha::{encrypt, MSG_LEN, NONCE_LEN}; +use sphinx_crypter::ecdh::{derive_shared_secret_from_slice, PUBLIC_KEY_LEN}; +use sphinx_crypter::secp256k1::Secp256k1; use std::convert::TryInto; use std::env; use std::time::Duration; @@ -70,7 +70,7 @@ async fn main() -> anyhow::Result<()> { let their_pk_bytes: [u8; PUBLIC_KEY_LEN] = their_pk[..PUBLIC_KEY_LEN].try_into()?; let shared_secret = derive_shared_secret_from_slice(their_pk_bytes, sk1.secret_bytes())?; - let mut nonce_end = [0; NONCE_END_LEN]; + let mut nonce_end = [0; NONCE_LEN]; OsRng.fill_bytes(&mut nonce_end); let cipher = encrypt(seed, shared_secret, nonce_end)?; diff --git a/tester/src/server.rs b/tester/src/server.rs index f4956fd..bd6dd4a 100644 --- a/tester/src/server.rs +++ b/tester/src/server.rs @@ -5,11 +5,11 @@ use rocket::State; use serde::{Deserialize, Serialize}; use std::convert::TryInto; -use sphinx_key_crypter::chacha::{decrypt, CIPHER_LEN}; -use sphinx_key_crypter::ecdh::{derive_shared_secret_from_slice, PUBLIC_KEY_LEN}; -use sphinx_key_crypter::secp256k1::rand::thread_rng; -use sphinx_key_crypter::secp256k1::Secp256k1; -use sphinx_key_crypter::secp256k1::{PublicKey, SecretKey}; +use sphinx_crypter::chacha::{decrypt, PAYLOAD_LEN}; +use sphinx_crypter::ecdh::{derive_shared_secret_from_slice, PUBLIC_KEY_LEN}; +use sphinx_crypter::secp256k1::rand::thread_rng; +use sphinx_crypter::secp256k1::Secp256k1; +use sphinx_crypter::secp256k1::{PublicKey, SecretKey}; #[derive(Clone, Debug, Serialize, Deserialize)] pub struct ConfigBody { @@ -54,7 +54,7 @@ pub fn decrypt_seed(dto: ConfigBody, sk1: SecretKey) -> anyhow::Result { let shared_secret = derive_shared_secret_from_slice(their_pk_bytes, sk1.secret_bytes())?; // decrypt seed let cipher_seed = hex::decode(dto.seed)?; - let cipher: [u8; CIPHER_LEN] = cipher_seed[..CIPHER_LEN].try_into()?; + let cipher: [u8; PAYLOAD_LEN] = cipher_seed[..PAYLOAD_LEN].try_into()?; let seed = decrypt(cipher, shared_secret)?; Ok(Config {