mirror of
https://github.com/stakwork/sphinx-key.git
synced 2026-01-31 21:34:19 +01:00
Merge pull request #56 from stakwork/velocity-control
Implement initial velocity control, drop our vls fork in favor of root vls repo
This commit is contained in:
@@ -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" }
|
||||
|
||||
@@ -1,18 +0,0 @@
|
||||
[package]
|
||||
name = "sphinx-key-auther"
|
||||
version = "0.1.0"
|
||||
authors = ["Evan Feenstra <evanfeenstra@gmail.com>"]
|
||||
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"]
|
||||
@@ -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<u8>) -> String {
|
||||
encode_config(input, URL_SAFE)
|
||||
}
|
||||
pub fn base64_decode(input: &str) -> Result<Vec<u8>> {
|
||||
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<Self> {
|
||||
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<Vec<u8>> {
|
||||
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<u8>, 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<u8>, secret_key: &SecretKey) -> Result<Vec<u8>> {
|
||||
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<u8>,
|
||||
sig: &Vec<u8>,
|
||||
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<u8>) -> Result<Message> {
|
||||
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<T: secp256k1::Signing>(
|
||||
secp: &Secp256k1<T>,
|
||||
input: Vec<u8>,
|
||||
secret_key: &SecretKey,
|
||||
) -> Signature {
|
||||
let message = hash_message(input);
|
||||
secp.sign_ecdsa(&message, &secret_key)
|
||||
}
|
||||
|
||||
pub fn hash_message(input: Vec<u8>) -> 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!");
|
||||
}
|
||||
}
|
||||
@@ -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" }
|
||||
|
||||
|
||||
2
crypter-ffi/.gitignore
vendored
2
crypter-ffi/.gitignore
vendored
@@ -1,2 +0,0 @@
|
||||
notes.md
|
||||
src/crypter.uniffi.rs
|
||||
@@ -1,31 +0,0 @@
|
||||
[package]
|
||||
name = "crypter-ffi"
|
||||
version = "0.1.0"
|
||||
authors = ["Evan Feenstra <evanfeenstra@gmail.com>"]
|
||||
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" }
|
||||
|
||||
@@ -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!"
|
||||
@@ -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!"
|
||||
@@ -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
|
||||
@@ -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<UInt8>) -> 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<UInt8>) {
|
||||
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<T: FixedWidthInteger>() throws -> T {
|
||||
let range = offset..<offset + MemoryLayout<T>.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<UInt8> {
|
||||
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<UInt8>.Index
|
||||
|
||||
init() {
|
||||
self.bytes = []
|
||||
self.offset = 0
|
||||
}
|
||||
|
||||
func writeBytes<S>(_ 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<T: FixedWidthInteger>(_ 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<T>(_ callback: (UnsafeMutablePointer<RustCallStatus>) -> T) throws -> T {
|
||||
try makeRustCall(callback, errorHandler: {
|
||||
$0.deallocate()
|
||||
return UniffiInternalError.unexpectedRustCallError
|
||||
})
|
||||
}
|
||||
|
||||
private func rustCallWithError<T, F: FfiConverter>
|
||||
(_ errorFfiConverter: F.Type, _ callback: (UnsafeMutablePointer<RustCallStatus>) -> T) throws -> T
|
||||
where F.SwiftType: Error, F.FfiType == RustBuffer
|
||||
{
|
||||
try makeRustCall(callback, errorHandler: { return try errorFfiConverter.lift($0) })
|
||||
}
|
||||
|
||||
private func makeRustCall<T>(_ callback: (UnsafeMutablePointer<RustCallStatus>) -> 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<UInt8>(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() {
|
||||
}
|
||||
}
|
||||
@@ -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);
|
||||
};
|
||||
@@ -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 <stdbool.h>
|
||||
#include <stdint.h>
|
||||
|
||||
// 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
|
||||
);
|
||||
@@ -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 *
|
||||
}
|
||||
@@ -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<T> = std::result::Result<T, CrypterError>;
|
||||
|
||||
#[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<String> {
|
||||
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<String> {
|
||||
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<String> {
|
||||
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<String> {
|
||||
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(())
|
||||
}
|
||||
}
|
||||
@@ -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<u8> = 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<u8> = 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<u8> = 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<u8> = 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)
|
||||
}
|
||||
@@ -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<KotlinType, FfiType> {
|
||||
// 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<KotlinType>: FfiConverter<KotlinType, RustBuffer.ByValue> {
|
||||
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<E> {
|
||||
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 <U, E: Exception> rustCallWithError(errorHandler: CallStatusErrorHandler<E>, 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<InternalException> {
|
||||
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 <U> 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 <reified Lib : Library> loadIndirect(
|
||||
componentName: String
|
||||
): Lib {
|
||||
return Native.load<Lib>(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<String, RustBuffer.ByValue> {
|
||||
// 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<CrypterException> {
|
||||
override fun lift(error_buf: RustBuffer.ByValue): CrypterException = FfiConverterTypeCrypterError.lift(error_buf)
|
||||
}
|
||||
}
|
||||
|
||||
public object FfiConverterTypeCrypterError : FfiConverterRustBuffer<CrypterException> {
|
||||
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)
|
||||
})
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -1,23 +0,0 @@
|
||||
[package]
|
||||
name = "sphinx-key-crypter"
|
||||
version = "0.1.0"
|
||||
authors = ["Evan Feenstra <evanfeenstra@gmail.com>"]
|
||||
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" }
|
||||
|
||||
@@ -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(())
|
||||
}
|
||||
}
|
||||
@@ -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(())
|
||||
}
|
||||
|
||||
}
|
||||
@@ -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(())
|
||||
}
|
||||
}
|
||||
@@ -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 }
|
||||
|
||||
|
||||
@@ -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"
|
||||
|
||||
@@ -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<NodeEntry>,
|
||||
states: Bucket<NodeStateEntry>,
|
||||
channels: DoubleBucket<ChannelEntry>,
|
||||
allowlist: Bucket<AllowlistItemEntry>,
|
||||
chaintracker: Bucket<ChainTrackerEntry>,
|
||||
@@ -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));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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" }
|
||||
|
||||
@@ -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<u8>, network: Network) -> anyhow::Result<InitResponse> {
|
||||
// let persister: Arc<dyn Persist> = Arc::new(DummyPersister);
|
||||
let persister: Arc<dyn Persist> = 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::<Vec<_>>();
|
||||
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<dyn Persist> = 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
|
||||
|
||||
@@ -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<dyn StartingTimeFactory> {
|
||||
Box::new(RandomStartingTimeFactory {})
|
||||
pub(crate) fn new() -> Arc<dyn StartingTimeFactory> {
|
||||
Arc::new(RandomStartingTimeFactory {})
|
||||
}
|
||||
}
|
||||
|
||||
387
sphinx-key/Cargo.lock
generated
387
sphinx-key/Cargo.lock
generated
@@ -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"
|
||||
|
||||
@@ -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"
|
||||
|
||||
@@ -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).
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
pub mod wifi;
|
||||
pub mod http;
|
||||
pub mod mqtt;
|
||||
pub mod sntp;
|
||||
mod html;
|
||||
|
||||
|
||||
|
||||
13
sphinx-key/src/conn/sntp.rs
Normal file
13
sphinx-key/src/conn/sntp.rs
Normal file
@@ -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));
|
||||
}
|
||||
}
|
||||
@@ -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<Config> {
|
||||
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 {
|
||||
|
||||
@@ -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());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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 {
|
||||
|
||||
@@ -21,6 +21,7 @@ fn states() -> BTreeMap<Status, (Color, Time)> {
|
||||
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));
|
||||
|
||||
@@ -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
|
||||
|
||||
|
||||
@@ -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"
|
||||
|
||||
@@ -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)?;
|
||||
|
||||
|
||||
@@ -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<Config> {
|
||||
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 {
|
||||
|
||||
Reference in New Issue
Block a user