Announcing oci-req-signer-c: A lightweight C library for Oracle Cloud request signing
At Riptides, we’ve been building a solution that securely federates workloads with Oracle Cloud Infrastructure (OCI) — as well as with AWS, GCP, and Azure. During this process, we faced a technical challenge that led us to create — and now open source — oci-req-signer-c, a minimal C implementation of the OCI request signing algorithm. This is part of our broader effort to enable deep, kernel-level identity federation across all major cloud providers, a topic we explored in detail in our post, Why Cloud-Native Federation Isn’t Enough for Non-Human Identities in AWS, GCP, and Azure.
The context
In our architecture, workloads obtain temporary OCI credentials (User Principal Session Tokens) by exchanging ID tokens issued by the Riptides Control Plane. These credentials are then injected into OCI API requests on the fly entirely transparently to the workloads themselves.
Here’s the key technical detail:
Each OCI API request must include a valid Authorization header signed with the RSA private key associated with the temporary credential.
In our system:
- An RSA keypair is generated dynamically for each session.
- The public key is sent to OCI along with the ID token to request a temporary credential.
- The private key stays in our control and is used to sign outgoing OCI API requests.
All of this happens in kernel space, inside a Linux kernel module responsible for intercepting and modifying outgoing HTTP(S) traffic.
You can also read more about our kernel-based architecture and how we integrate SPIFFE and kTLS in Seamless Kernel-Based Non-Human Identity with kTLS and SPIFFE
The Problem
While OCI provides official SDKs for Python, Java, Go, and others, none of them include a C implementation of the signing algorithm. Moreover we couldn't find one which is suitable for use in kernel modules or other low-level environments.
We needed a pure C implementation, with no dynamic allocations and no dependency on libc features unavailable in the kernel. When we couldn’t find one, we decided to build it.
We encountered similar challenges with AWS request signing, which led us to develop and open source libsigv4 — a portable C library implementing AWS SigV4 with kernel compatibility.
Our solution — oci-req-signer-c
oci-req-signer-c is a lightweight, dependency-minimal C library for computing OCI-style HTTP request signatures.
It’s designed to work both in user space and kernel space, or anywhere a small, efficient, and auditable signer is required.
Features
- Self-contained — minimal dependencies, builds as
.aor.so - No dynamic memory allocation — kernel and embedded safe
- RSA private key (DER format) support
- Simple API for signing any HTTP request
- Customizable system header handling (
OCI_SYSTEM_HEADER) - Produces the HTTP Authorization header (key and value) for OCI requests, including the computed signature and all required metadata
Example Usage
#include "oci_signer.h"
// Example-specific buffer size constants
#define EXAMPLE_AUTH_HEADER_MAX_LEN 4096
int main()
{
// Sample request parameters
const char *method = "GET";
const char *uri = "/20160918/instances";
const char *host = "iaas.us-phoenix-1.oraclecloud.com";
const char *date = "Thu, 05 Jan 2014 21:31:40 GMT";
const char *payload = "";
// Example key_id in format: tenancy/user/fingerprint
const char *key_id =
"ocid1.tenancy.oc1..aaaaaaaaba3pv6wkcr4jqae5f15p2b2m2yt2j6rx32uzr4h25vqstifsfdsq/"
"ocid1.user.oc1..aaaaaaaat5nvwcna5j6aqzjcaty5eqbb6qt2jvpkanghtgdaqedqw3rynjq/"
"20:3b:97:13:55:1c:5b:0d:d3:37:d8:50:4e:c5:3a:34";
// Alternative: Example key_id using session token format
// const char *key_id = "ST$aaaaaaaa7tz3aaaaaaaaaymq2maaaaaaabfwiljtdnfgqaaaa";
// Initialize OCI signer parameters
oci_signer_params_t signer_params = {0}; // Zero-initialize the structure
// Set the private key in DER format using the binary type
signer_params.private_key.data = ...;
signer_params.private_key.len = ...;
signer_params.key_id = oci_signer_string((unsigned char *)key_id);
signer_params.method = oci_signer_string((unsigned char *)method);
signer_params.uri = oci_signer_string((unsigned char *)uri);
signer_params.payload = oci_signer_string((unsigned char *)payload);
signer_params.headers[0].key = oci_signer_string((unsigned char *)"host");
signer_params.headers[0].value = oci_signer_string((unsigned char *)host);
signer_params.headers[1].key = oci_signer_string((unsigned char *)"date");
signer_params.headers[1].value = oci_signer_string((unsigned char *)date);
signer_params.num_headers = 2;
// Set the required crypto functions
signer_params.sha256 = ...;
signer_params.rsa_sign_sha256 = ...;
signer_params.base64_encode = ...;
// Buffer for the Authorization header
unsigned char *auth_header_buf = malloc(EXAMPLE_AUTH_HEADER_MAX_LEN);
memset(auth_header_buf, 0, EXAMPLE_AUTH_HEADER_MAX_LEN);
oci_signer_header_t auth_header =
{
.value = {.data = auth_header_buf}
};
int status = oci_signer_sign(&signer_params, &auth_header, EXAMPLE_AUTH_HEADER_MAX_LEN);
if (status == OCI_SIGNER_OK)
{
printf("Authorization header value: %.*s\n", auth_header.value.len, auth_header.value.data);
}
else
{
fprintf(stderr, "Failed to sign the request\n");
}
free(auth_header_buf);
free(key_data);
}How we use it at Riptides
This library powers our kernel-space credential injection system, enabling OCI authentication without any user-space process or SDK.
Our kernel module:
- Obtains a User Principal Session Token (temporary credential) from OCI using an ID token and a ephemeral RSA public key.
- Intercepts outgoing OCI API requests.
- Injects the temporary credential and recomputes the Authorization signature with
oci-req-signer-cusing the matching private key.
This enables transparent, secure, and short-lived identity federation for workloads accessing OCI resources.
Why we open sourced it
We realized this signing challenge isn’t unique to us.
Anyone building low-level OCI integrations, embedded systems, or custom networking stacks might need a C implementation of OCI’s signing logic.
By open sourcing oci-req-signer-c, we aim to:
- Help developers implement secure OCI integrations in constrained environments
- Enable experimentation in edge and kernel space contexts
- Encourage community collaboration and extensions
Get started
You can check out the source here: 👉 https://github.com/riptideslabs/oci-req-signer-c
We’d love feedback, especially from embedded developers running into the same challenges.
Closing thoughts
What started as an internal engineering need to make OCI request signing possible inside a Linux kernel module has evolved into a reusable, open-source library for the broader community.
We’re excited to share oci-req-signer-c and look forward to seeing how others use it in their projects.
If you enjoyed this post, follow us on LinkedIn and X for more updates. If you’d like to see Riptides in action, get in touch with us for a demo.
Ready to replace secrets
with trusted identities?
Build with trust at the core.
