---
name: "libressl-EC_POINT_point2oct"
section: "3"
platform: "linux"
package: "libressl"
version: "4.4.0-1"
release: "Arch Linux 2026-11-01"
platforms: ["linux"]
url: "https://new.carta.tech/libressl-EC_POINT_point2oct"
---

# libressl-EC\_POINT\_point2oct(3)

encode and decode elliptic curve points

## NAME

**EC\_POINT\_point2oct**, **EC\_POINT\_oct2point**, **EC\_POINT\_point2bn**, **EC\_POINT\_bn2point**, **EC\_POINT\_point2hex**, **EC\_POINT\_hex2point** – encode and decode elliptic curve points

## SYNOPSIS

Crypto Library (libcrypto, -lcrypto)

**#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

The *ctx* argument of all functions in this manual is optional.

An *EC\_POINT* object represents a point on the elliptic curve given by an *EC\_GROUP* object. It is either the point at infinity or it has a representation (x, y) in standard affine coordinates, in which case it satisfies the curve's Weierstrass equation

```
y^2 = x^3 + ax + b
```

in the prime field of size p. Thus, y is a square root of x^3 + ax + b. Since p \> 3 is odd, p - y is another square root with different parity, unless y is zero. Point compression uses that x and the parity of y are enough to compute y using BN\_mod\_sqrt(3).

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. 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 the byte strings:

| | | | |
| --- | --- | --- | --- |
|  | *Compressed* | *Uncompressed* | *Hybrid* |
| Encoding | 2+P \|\| X | 4 \|\| X \|\| Y | 6+P \|\| X \|\| Y |
| Length | 1 + l | 1 + 2l | 1 + 2l |

where the first octet is the point conversion form combined with the parity bit in the compressed and hybrid encodings. The point at infinity is encoded as a single zero byte.

**EC\_POINT\_point2oct**() converts *point* into the octet string encoding of type *form*. It assumes without checking that *point* is a point on the elliptic curve represented by *group* and operates in two modes depending on the *buf* argument. If *buf* is NULL, **EC\_POINT\_point2oct**() returns the length of *point*'s encoding of type *form* and ignores the *len* and *ctx* arguments. If *buf* is not NULL and its length *len* is sufficiently big, **EC\_POINT\_point2oct**() writes the *point*'s encoding of type *form* to *buf* and 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.

**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)](/free/3.md). **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

If *buf* is NULL, **EC\_POINT\_point2oct**() returns the length needed to encode the *point* on *group*, or 0 on error. If *buf* is not NULL, **EC\_POINT\_point2oct**() returns the number of bytes written to *buf* or 0 on error. Error conditions include that *form* is invalid, *len* is too small, and memory allocation failure.

**EC\_POINT\_oct2point**() returns 1 on success and 0 on error. Error conditions include invalid encoding, *buf* does not represent a point on *group*, or memory allocation failure.

**EC\_POINT\_point2bn**() returns a *BIGNUM* containing the encoding of *point* or NULL on error. The returned *BIGNUM* is either *bn* or a newly allocated one which must be freed by the caller. Error conditions include those of **EC\_POINT\_point2oct**(), BN\_bn2bin(3), or memory allocation failure.

**EC\_POINT\_bn2point**() returns an *EC\_POINT* corresponding to the encoding in *bn* or NULL on error. The returned *EC\_POINT* is either *point* or a newly allocated one which must be freed by the caller. Error conditions include those of BN\_bn2bin(3), **EC\_POINT\_oct2point**(), or memory allocation failure.

**EC\_POINT\_point2hex**() returns a newly allocated string or NULL on error. Error conditions include those of **EC\_POINT\_point2bn**() or BN\_bn2hex(3).

**EC\_POINT\_hex2point**() returns an *EC\_POINT* containing the decoded point on *group* or NULL on error. The returned *EC\_POINT* is either *point* or a newly allocated one which must be freed by the caller. Error conditions are those of BN\_hex2bn(3), or **EC\_POINT\_bn2point**().

## SEE ALSO

BN\_mod\_sqrt(3), BN\_new(3), BN\_num\_bits(3), [crypto(3)](/crypto/3.md), 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)

## STANDARDS

*SEC 1: Elliptic Curve Cryptography, Version 2.0*, May 21, 2009, https://www.secg.org/sec1-v2.pdf.

## 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.

## BUGS

The *point\_conversion\_form\_t* is 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.

The poorly chosen signatures of the functions in this manual result in an unergonomic API, particularly so for **EC\_POINT\_point2oct**() and **EC\_POINT\_oct2point**(). Due to fundamental misdesign in the EC library, points are not directly linked to the curve they live on. Adding checks that *point* lives on *group* is too expensive and intrusive, so it is and will continue to be easy to make the EC\_POINT\_point2\* API output nonsense.

**EC\_POINT\_point2bn**() and **EC\_POINT\_bn2point**() make no sense. They abuse *BIGNUM* as a vector type, which is in poor taste.

**EC\_POINT\_point2hex**() and **EC\_POINT\_hex2point**() use a non-standard encoding format.
