EC_POINT_POINT2OCT(3)
π
EC_POINT_POINT2OCT(3) β the libcrypto manual, bestie edition
okay so this is a page from the Library Functions Manual and it's all about elliptic curve points β encoding them, decoding them, the whole glow-up. Six functions, one very specific vibe. Let's get into it π
β¨ NAME β¨
EC_POINT_point2oct, EC_POINT_oct2point, EC_POINT_point2bn, EC_POINT_bn2point, EC_POINT_point2hex, EC_POINT_hex2point β they encode and decode elliptic curve points. That's it, that's the whole job π
πΈ SYNOPSIS πΈ
library βlibcryptoβ #include <openssl/bn.h>
#include <openssl/ec.h>
typedef enum {
POINT_CONVERSION_COMPRESSED = 2,
POINT_CONVERSION_UNCOMPRESSED = 4,
POINT_CONVERSION_HYBRID = 6
} point_conversion_form_t;
size_t
EC_POINT_point2oct(const EC_GROUP *group, const EC_POINT *point,
point_conversion_form_t form, unsigned char *buf, size_t len,
BN_CTX *ctx);
int
EC_POINT_oct2point(const EC_GROUP *group, EC_POINT *point,
const unsigned char *buf, size_t len, BN_CTX *ctx);
BIGNUM *
EC_POINT_point2bn(const EC_GROUP *group, const EC_POINT *point,
point_conversion_form_t form, BIGNUM *bn, BN_CTX *ctx);
EC_POINT *
EC_POINT_bn2point(const EC_GROUP *group, const BIGNUM *bn,
EC_POINT *point, BN_CTX *ctx);
char *
EC_POINT_point2hex(const EC_GROUP *group, const EC_POINT *point,
point_conversion_form_t form, BN_CTX *ctx);
EC_POINT *
EC_POINT_hex2point(const EC_GROUP *group, const char *hex,
EC_POINT *point, BN_CTX *ctx);
π¦ DESCRIPTION π¦
First things first, bestie: the ctx argument of all functions in this manual is optional. Optional! She doesn't have to be there if she doesn't wanna be π«Ά
π the whole point (pun intended)
An EC_POINT object represents a point on the elliptic curve given by an EC_GROUP object. It's one of two things: either it's the point at infinity, or it has a representation (x, y) in standard affine coordinates β and in that case it satisfies the curve's Weierstrass equation:
y^2 = x^3 + ax + b
...in the prime field of size p. So like, y is a square root of x^3 + ax + b. And since p > 3 is odd, p - y is another square root with different parity, unless y is zero. (Not me doing algebra at 2am π)
Point compression literally just uses that: x plus the parity of y is enough to compute y using BN_mod_sqrt(3). Iconic shortcut behaviour β¨
π how field elements get represented
Field elements are represented as non-negative integers < p in big-endian 2-complement form, zero-padded on the left to the byte length l of p.
So if X and Y are the representations of x and y respectively, and P is the parity bit of y, the three encodings of the point (x, y) are these byte strings:
Compressed Uncompressed Hybrid
Encoding 2+P || X 4 || X || Y 6+P || X || Y
Length 1 + l 1 + 2l 1 + 2l
the first octet is the point conversion form combined with the parity bit in the compressed and hybrid encodings. And the point at infinity? Encoded as a single zero byte. tiny. humble. iconic π
π EC_POINT_point2oct()
Converts point into the octet string encoding of type form.
β οΈ Heads up: it assumes without checking thatpointis a point on the elliptic curve represented bygroup. no vibe check, no validation, just trust π
It operates in two modes depending on the buf argument:
- If
bufisNULLβ it returns the length ofpoint's encoding of typeformand ignores thelenandctxarguments. - If
bufis notNULLand its lengthlenis sufficiently big β it writes the point's encoding of typeformtobufand returns the number of bytes written.
Unless point is the point at infinity, the coordinates to be encoded are calculated using EC_POINT_get_affine_coordinates(3).
π EC_POINT_oct2point()
Decodes the octet string representation of a point on group in buf of size len and β if it represents a point on group β sets it on the caller-provided point using EC_POINT_set_to_infinity(3), EC_POINT_set_compressed_coordinates(3), or EC_POINT_set_affine_coordinates(3).
For hybrid encoding, the consistency of the parity bit in the leading octet is verified. yes ma'am, we're checking π₯
π§ EC_POINT_point2bn()
Returns a BIGNUM containing the encoding of type form of the point on group. If bn is NULL, this BIGNUM is newly allocated; otherwise the result is copied into bn and returned.
EC_POINT_point2bn() is equivalent to EC_POINT_point2oct() followed by BN_bin2bn(3).
π EC_POINT_bn2point()
Assumes that bn contains the encoding of a point on group. If point is NULL, the result is placed in a newly allocated EC_POINT; otherwise the result is placed in point, which is then returned.
EC_POINT_bn2point() is equivalent to BN_bn2bin(3) followed by EC_POINT_oct2point().
β EC_POINT_point2hex()
Returns a printable string containing the hexadecimal encoding of the point encoding of type form of the point on group. The string must be freed by the caller using free(3). freeing your own strings, we love responsibility π«Ά
EC_POINT_point2hex() is equivalent to EC_POINT_point2bn() followed by BN_bn2hex(3).
π EC_POINT_hex2point()
Interprets hex as a hexadecimal encoding of the point encoding of a point on group. If point is NULL, the result is returned in a newly allocated EC_POINT; otherwise the result is copied into point, which is then returned.
EC_POINT_hex2point() is equivalent to BN_hex2bn(3) followed by EC_POINT_bn2point().
π RETURN VALUES π
okay pay attention, this is the part where people get got:
- If
bufisNULL,EC_POINT_point2oct()returns the length needed to encode the point ongroup, or0on error. Ifbufis notNULL,EC_POINT_point2oct()returns the number of bytes written tobufor0on error. Error conditions include thatformis invalid,lenis too small, and memory allocation failure. EC_POINT_oct2point()returns1on success and0on error. Error conditions include invalid encoding,bufdoes not represent a point ongroup, or memory allocation failure.EC_POINT_point2bn()returns aBIGNUMcontaining the encoding ofpointorNULLon error. The returnedBIGNUMis eitherbnor a newly allocated one which must be freed by the caller. Error conditions include those ofEC_POINT_point2oct(),BN_bn2bin(3), or memory allocation failure.EC_POINT_bn2point()returns anEC_POINTcorresponding to the encoding inbnorNULLon error. The returnedEC_POINTis eitherpointor a newly allocated one which must be freed by the caller. Error conditions include those ofBN_bn2bin(3),EC_POINT_oct2point(), or memory allocation failure.EC_POINT_point2hex()returns a newly allocated string orNULLon error. Error conditions include those ofEC_POINT_point2bn()orBN_bn2hex(3).EC_POINT_hex2point()returns anEC_POINTcontaining the decoded point ongrouporNULLon error. The returnedEC_POINTis eitherpointor a newly allocated one which must be freed by the caller. Error conditions are those ofBN_hex2bn(3), orEC_POINT_bn2point().
π«Ά reminder bestie: "newly allocated" means you free it. Every. Single. Time. No leaks on my watch.
π SEE ALSO π
BN_mod_sqrt(3), BN_new(3), BN_num_bits(3), crypto(3), d2i_ECPKParameters(3), EC_GROUP_check(3), EC_GROUP_get_curve_name(3), EC_GROUP_new_by_curve_name(3), EC_GROUP_new_curve_GFp(3), EC_KEY_METHOD_new(3), EC_KEY_new(3), EC_POINT_add(3), EC_POINT_get_affine_coordinates(3), EC_POINT_new(3), ECDH_compute_key(3), ECDSA_SIG_new(3)
like, the whole friend group π«
π STANDARDS π
SEC 1: Elliptic Curve Cryptography, Version 2.0, https://www.secg.org/sec1-v2.pdf, May 21, 2009.
π°οΈ HISTORY π°οΈ
EC_POINT_point2oct() and EC_POINT_oct2point() first appeared in OpenSSL 0.9.7 and have been available since OpenBSD 3.2.
EC_POINT_point2bn(), EC_POINT_bn2point(), EC_POINT_point2hex(), and EC_POINT_hex2point() first appeared in OpenSSL 0.9.8 and have been available since OpenBSD 4.5.
they've been around. elders. respect them π
π BUGS π
okay this is the venting section and honestly? valid.
- The
point_conversion_form_tis not properly exposed in the API. There is no representation for the point at infinity, nor is there an API interface for the parity bit β forcing applications to invent their own and do bit twiddling in buffers. bit twiddling!! in buffers!! in this economy!! π - The poorly chosen signatures of the functions in this manual result in an unergonomic API, particularly so for
EC_POINT_point2oct()andEC_POINT_oct2point(). Due to fundamental misdesign in the EC library, points are not directly linked to the curve they live on. Adding checks thatpointlives ongroupis too expensive and intrusive, so it is and will continue to be easy to make theEC_POINT_point2*API output nonsense. no cap, that's the situation π EC_POINT_point2bn()andEC_POINT_bn2point()make no sense. They abuseBIGNUMas a vector type, which is in poor taste. read that again. in poor taste π΅EC_POINT_point2hex()andEC_POINT_hex2point()use a non-standard encoding format. not standard. we said what we said.
and that's the page!! this was EC_POINT_POINT2OCT(3) from the Debian build, dated June 13, 2025 β go encode a point, free your memory, and hydrate πβ¨π
π¦ where this page comes from
- alpine 3.24: libressl-doc 4.3.1-r0 Β· custom
- arch rolling: libressl 4.4.0-1 Β· ISC AND custom:OpenSSL
- Copyright (c) 2025 Theo Buehler <tb@openbsd.org>
- π girlified by deepseek-ai/DeepSeek-V4.1-Flash-1017 on : a language model's rewrite of the original, under its terms