| Crates.io | origin-sdk |
| lib.rs | origin-sdk |
| version | 0.1.1 |
| created_at | 2025-09-03 14:14:34.290815+00 |
| updated_at | 2025-09-03 22:11:12.075848+00 |
| description | A Rust implementation of the Origin SDK, which is used in games to communicate with the EA Desktop client. |
| homepage | |
| repository | https://github.com/ploxxxy/origin-sdk |
| max_upload_size | |
| id | 1822590 |
| size | 107,402 |
This crate handles the low-level networking, cryptography, and request/response mapping of the LSX protocol, providing an asynchronous API for connecting, authenticating, and interacting with the Origin (EA Desktop) backend.
use origin_sdk::{protocol::game::GetAllGameInfo, sdk::OriginSdk};
#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
// Connect to the Origin SDK server
let (client, _) = OriginSdk::connect("127.0.0.1:3216").await.unwrap();
let game_info = client.send_request(GetAllGameInfo {}).await.unwrap();
println!("{:#?}", game_info);
// GetAllGameInfoResponse {
// up_to_date: true,
// languages: "de_DE,en_US,es_ES,es_MX,fr_FR,it_IT,ja_JP,ko_KR,pl_PL,pt_BR,ru_RU,zh_CN,zh_TW",
// free_trial: false,
// full_game_purchased: true,
// full_game_released: true,
// full_game_release_date: "0000-00-00T00:00:48",
// expiration: "0000-00-00T00:00:08",
// system_time: "2025-09-03T12:15:54",
// has_expiration: false,
// installed_version: "",
// installed_language: "en_US",
// available_version: "0.0.0.0",
// display_name: "Knockout City™",
// max_group_size: 16,
// entitlement_source: "EPIC",
// }
Ok(())
}
All request types are defined in src/protocol and are organized by domain:
achievements.rsauth.rsbroadcast.rschat.rsEach request implements the RequestResponse trait, which is generated by the request_response! macro.
This ensures requests are automatically mapped to their corresponding ResponseBody variant:
pub enum RequestBody {
// ...
GetProfile(GetProfile)
// ...
}
pub enum ResponseBody {
// ...
GetProfileResponse(GetProfileResponse),
// ...
}
request_response! {
// ...
GetProfile => GetProfileResponse,
// ...
}
// This call will be automatically deserialized into a `GetProfileResponse`
let profile = client.send_request(GetProfile { /* ... */ }).await?;
The LSX protocol uses a custom AES-128-ECB scheme with deterministic key derivation. The session key is derived through a challenge handshake with the server.
Challenge event with a random hex string keyseed = (byte[0] << 8) | byte[1]
ChallengeResponse request back to the server, which includes:
ChallengeAccepted response, both sides now share the same AES keyWarranty Voider for releasing LSX-Dumper and publishing information about the protocol on various forumsBergmann89 for releasing xsd-parser, which helped with LSX model generationThis project is a third-party reimplementation of the Origin SDK, based on reverse-engineering and observations of Origin SDK versions 9.12.1.7 and 10.6.1.8, intended for educational and research purposes only.
It is not affiliated with, endorsed by, or supported by Electronic Arts.