Generate a key pair
The curve is EC P-256 (prime256v1). Pick one of the paths below. In all of them the private
key never leaves your infrastructure. Do not send it to us or to anyone. No field of our API
accepts a private key, and no one from our support will ever ask for one.
Generate the pair
- OpenSSL
- Node
- Python
- PHP
- Java
- C#
- Go
- Ruby
- Elixir
- Clojure
# privada (guarde em cofre)
openssl ecparam -name prime256v1 -genkey -noout | openssl pkcs8 -topk8 -nocrypt -out privateKey.pem
# pública (é esta que você registra no portal)
openssl ec -in privateKey.pem -pubout -out publicKey.pem
# confira antes de registrar
openssl ec -in privateKey.pem -text -noout | head -3
# Private-Key: (256 bit) ... NIST CURVE: P-256
import { generateKeyPairSync } from 'node:crypto'
import { writeFileSync } from 'node:fs'
const { privateKey, publicKey } = generateKeyPairSync('ec', { namedCurve: 'P-256' })
writeFileSync('privateKey.pem', privateKey.export({ type: 'pkcs8', format: 'pem' }))
writeFileSync('publicKey.pem', publicKey.export({ type: 'spki', format: 'pem' }))
from cryptography.hazmat.primitives import serialization
from cryptography.hazmat.primitives.asymmetric import ec
key = ec.generate_private_key(ec.SECP256R1())
with open("privateKey.pem", "wb") as f:
f.write(key.private_bytes(
serialization.Encoding.PEM,
serialization.PrivateFormat.PKCS8,
serialization.NoEncryption(),
))
with open("publicKey.pem", "wb") as f:
f.write(key.public_key().public_bytes(
serialization.Encoding.PEM,
serialization.PublicFormat.SubjectPublicKeyInfo,
))
<?php
$key = openssl_pkey_new([
'private_key_type' => OPENSSL_KEYTYPE_EC,
'curve_name' => 'prime256v1',
]);
openssl_pkey_export($key, $privatePem);
file_put_contents('privateKey.pem', $privatePem);
// A pública sai da privada — é esta que você registra no portal.
file_put_contents('publicKey.pem', openssl_pkey_get_details($key)['key']);
import java.nio.file.*;
import java.security.*;
import java.security.spec.ECGenParameterSpec;
import java.util.Base64;
public class Gen {
static void pem(String path, String type, byte[] der) throws Exception {
String body = Base64.getMimeEncoder(64, "\n".getBytes()).encodeToString(der);
Files.writeString(Path.of(path),
"-----BEGIN " + type + "-----\n" + body + "\n-----END " + type + "-----\n");
}
public static void main(String[] args) throws Exception {
KeyPairGenerator generator = KeyPairGenerator.getInstance("EC");
generator.initialize(new ECGenParameterSpec("secp256r1"));
KeyPair pair = generator.generateKeyPair();
// getEncoded() já sai nos formatos certos: privada em PKCS#8, pública em SPKI.
pem("privateKey.pem", "PRIVATE KEY", pair.getPrivate().getEncoded());
pem("publicKey.pem", "PUBLIC KEY", pair.getPublic().getEncoded());
}
}
using System.Security.Cryptography;
var ec = ECDsa.Create(ECCurve.NamedCurves.nistP256);
// Os métodos *Pem já exportam nos formatos certos: privada em PKCS#8, pública em SPKI.
File.WriteAllText("privateKey.pem", ec.ExportPkcs8PrivateKeyPem() + "\n");
File.WriteAllText("publicKey.pem", ec.ExportSubjectPublicKeyInfoPem() + "\n");
package main
import (
"crypto/ecdsa"
"crypto/elliptic"
"crypto/rand"
"crypto/x509"
"encoding/pem"
"os"
)
func main() {
key, _ := ecdsa.GenerateKey(elliptic.P256(), rand.Reader)
priv, _ := x509.MarshalPKCS8PrivateKey(key)
pub, _ := x509.MarshalPKIXPublicKey(&key.PublicKey)
os.WriteFile("privateKey.pem",
pem.EncodeToMemory(&pem.Block{Type: "PRIVATE KEY", Bytes: priv}), 0600)
os.WriteFile("publicKey.pem",
pem.EncodeToMemory(&pem.Block{Type: "PUBLIC KEY", Bytes: pub}), 0644)
}
require 'openssl'
key = OpenSSL::PKey::EC.generate('prime256v1')
# private_to_pem exporta em PKCS#8; public_to_pem em SPKI — os formatos que os exemplos leem.
File.write('privateKey.pem', key.private_to_pem)
File.write('publicKey.pem', key.public_to_pem)
key = :public_key.generate_key({:namedCurve, :secp256r1})
# O OTP exporta a privada em SEC1 ("EC PRIVATE KEY"); todo leitor de PEM aceita.
File.write!("privateKey.pem", :public_key.pem_encode([:public_key.pem_entry_encode(:ECPrivateKey, key)]))
{:ECPrivateKey, _v, _priv, {:namedCurve, oid}, point, _} = key
spki = :public_key.pem_entry_encode(:SubjectPublicKeyInfo, {{:ECPoint, point}, {:namedCurve, oid}})
File.write!("publicKey.pem", :public_key.pem_encode([spki]))
(import '[java.security KeyPairGenerator]
'[java.security.spec ECGenParameterSpec]
'[java.util Base64])
(defn pem [path type der]
(spit path (str "-----BEGIN " type "-----\n"
(.encodeToString (Base64/getMimeEncoder 64 (.getBytes "\n")) der)
"\n-----END " type "-----\n")))
(let [pair (.generateKeyPair (doto (KeyPairGenerator/getInstance "EC")
(.initialize (ECGenParameterSpec. "secp256r1"))))]
;; getEncoded ja sai nos formatos certos: privada em PKCS#8, publica em SPKI.
(pem "privateKey.pem" "PRIVATE KEY" (.getEncoded (.getPrivate pair)))
(pem "publicKey.pem" "PUBLIC KEY" (.getEncoded (.getPublic pair))))
If the file you are about to upload contains BEGIN PRIVATE KEY or BEGIN EC PRIVATE KEY, it is
the wrong file. The one you register starts with BEGIN PUBLIC KEY.
Every tab above is executed and checked before it ships: the private key must parse as P-256 and the stored public key must match it byte for byte. Prefer OpenSSL or your language's standard library on a controlled machine: a key that went through a browser went through extensions, cache and download history.
In the browser, on the "New API credential" screen
Click Generate keys. The pair is created in your browser, the private key is downloaded as
privateKey.pem, and the public key is filled into the form for you. The private key never
travels. It never reaches our servers.
It is the fastest way to get started, and fine for sandbox.
Keys in KMS or HSM
Fully supported and encouraged. Create an ECC P-256, sign/verify key, export the public key and
register it. Your Sign calls return DER-encoded signatures. Send them as they are: we accept
both DER and raw R‖S. See signing requests.
What to do with the private key
Keep it in a vault. Never in a repository, never in a log, never in an environment variable shared across teams.
If it leaks, revoke the credential in the portal and create another one. There is no "replace the key" while keeping the credential, and that is deliberate: a credential is a signed binding between one key, one account and one profile. Changing the key means a new binding, that is, a new credential.