Getting started
The quickest useful integration is: import an account identity once, clear the caller-owned secret buffer, validate a peer key, encrypt, persist or transmit the immutable result, then decrypt on the receiving identity.
The coordinates below are canonical, but public registry publication is not a completed release gate. Today, build and test the matching artifact from this repository before adding it to an application.
Add the package
- Rust
- Kotlin
- Android
- Swift
- TypeScript
[dependencies]
softchat = { path = "../softchat-sdk/crates/softchat" }
The crate currently depends on reviewed, unpublished Softrelay Git revisions,
so cargo package is intentionally not presented as a crates.io install.
dependencies {
implementation("com.softcose:softchat:0.1.0")
}
Generate the repository-local Maven layout with
bash scripts/test-kotlin-package.sh. The JVM package needs its matching
native libsoftchat on the library path.
dependencies {
implementation("com.softcose:softchat-android:0.1.0")
}
Build the AAR with bash scripts/build-android-package.sh. It contains
arm64-v8a and x86_64 native libraries and consumer R8 rules.
dependencies: [
.package(path: "../softchat-package")
]
Build the staged XCFramework/SwiftPM distribution on macOS with
bash scripts/build-swift-package.sh; import only SoftchatKit.
bash scripts/test-javascript-package.sh
npm install ./target/packages/javascript/softcose-softchat-0.1.0.tgz
Node supports CommonJS and ESM. Browser and Worker consumers use the explicit browser initializer described below.
Complete one encrypted round trip
The sample secret is deliberately omitted. Load 32 secret bytes from your platform authority, never from source code.
- Rust
- Kotlin
- Android
- Swift
- TypeScript
use softchat::LocalIdentity;
let alice = LocalIdentity::from_secret_bytes(&alice_secret)?;
alice_secret.fill(0);
let bob = LocalIdentity::from_secret_bytes(&bob_secret)?;
bob_secret.fill(0);
let bob_public = bob.public_key();
let encrypted = alice.encrypt_utf8(&bob_public, "hello")?;
let plaintext = bob.decrypt_utf8(&encrypted)?;
assert_eq!(plaintext, "hello");
# Ok::<(), softchat::SoftchatError>(())
val alice = SoftchatIdentity.import(aliceSecret)
aliceSecret.fill(0)
val bob = SoftchatIdentity.import(bobSecret)
bobSecret.fill(0)
val encrypted = alice.encrypt(bob.publicKey, "hello")
check(bob.decrypt(encrypted) == "hello")
val alice = SoftchatIdentity.import(accountSecret)
accountSecret.fill(0)
val encrypted = withContext(Dispatchers.Default) {
alice.encrypt(recipientPublicKey, "hello")
}
messageDao.insert(encrypted.toPersistedRecord())
Keep cryptography off the main thread. The result is a language-owned value; map it into the application’s Room schema rather than persisting a generated binding object.
let alice = try SoftchatIdentity(secretKey: aliceSecret)
aliceSecret.resetBytes(in: aliceSecret.indices)
let bob = try SoftchatIdentity(secretKey: bobSecret)
bobSecret.resetBytes(in: bobSecret.indices)
let encrypted = try alice.encrypt("hello", for: bob.publicKey)
let plaintext = try bob.decrypt(encrypted)
precondition(plaintext == "hello")
import { SoftchatIdentity } from "@softcose/softchat";
const alice = SoftchatIdentity.import(aliceSecret);
aliceSecret.fill(0);
const bob = SoftchatIdentity.import(bobSecret);
bobSecret.fill(0);
const encrypted = alice.encrypt(bob.publicKey, "hello");
console.assert(bob.decrypt(encrypted) === "hello");
For a browser or Worker:
import { initializeSoftchat } from "@softcose/softchat/browser";
const { SoftchatIdentity } = await initializeSoftchat();
- Rust
- Kotlin
- Android
- Swift
- TypeScript
Next
Learn the identity lifecycle, then choose the family you need: Nostr and cryptography, private messaging, chat and account events, relay and persistence, Noise and synchronization, or media and HTTP plans.