By WitherOrNot
NOTE: PKEY2005 is an area of active research. The documentation contained here is likely to change as more information is discovered.
This writeup assumes that you have already read the patent for this signature scheme. The patent itself assumes decent knowledge of elliptic curve cryptography, group theory, and field theory. If you are looking to implement this system yourself and are unfamiliar with the math, please contact the UMSKT Team, as there will not be sufficient room in this writeup to explain all of the math involved.
The following vocabulary is borrowed from the patent.
-
$M$ , the message, or data, to be validated -
$K$ , a finite field of prime order -
$p$ , the order of$K$ -
$K_3$ , an extension field of$K$ of degree 3 -
$K_6$ , an extension field of$K_3$ of degree 2 -
$E$ , an elliptic curve of the form$y^2 = x^3 + ax + b$ -
$m$ , the order of$E/K$ -
$\vec{\alpha}$ , the private key vector -
$H_1(M)$ , a hash function which outputs a vector of dimension$n$ -
$H_2(M)$ , a hash function which outputs a point in$E/K$ -
$P$ , a generator of the order$m$ torsion subgroup of$E/K_6$ -
$S$ , the signature point in$E/K$ -
$\vec{Q}$ , a collection of$n$ points generated by$P$ -
$e_m(P, Q)$ , a Tate pairing of order$m$ between points$P$ and$Q$
In short, ignoring all of the server-side authentication mechanisms and parameter generation procedures, message validation boils down to the following as per the patent:
- Given a message
$M$ , generate the hash vector$\vec{v} = H_1(M)$ - Generate the hash point
$T = H_2(M)$ - Calculate the point
$Q = \sum v_iQ_i$ - Calculate
$c_1=e_m(Q, T)$ - Compare this value to
$c=e_m(P, S)$ - If
$c = c_1$ , the message is valid, otherwise the message is invalid
Generation of a signature is the reverse of this process:
- Given a message
$M$ , generate the hash vector$\vec{v} = H_1(M)$ - Generate the hash point
$T = H_2(M)$ - Generate
$\vec{Q}$ with$Q_i = \alpha_i P$ - Calculate
$\alpha = \sum v_i \alpha_i \pmod{m}$ - Calculate
$S = \alpha T$ - Return the tuple
$(M, S)$ , and let$\vec{Q}$ be a public parameter
Note that this signature scheme works due to the bilinearity of the pairing function, as
While the patent provides a very comprehensive description of the signature implementation, it fails to completely describe the mechanism used in PKEY2005 specifically. This section is devoted to describing the specifics of PKEY2005's validation mechanism.
The binary serialzed form of a PKEY2005 public key is as follows, given in ImHex Pattern Language.
u8 size_bignum @ 0x15;
// Bignums are stored in little endian order
struct bignum {
u8 data[size_bignum];
};
struct field_data {
u32 magic; // 0x00112233
u16 eq256; // must be 0x0100
padding[2];
u8 must_be_0; // Enables use of unused values, but parser will error if nonzero
u8 size_modulus; // Same as size_bignum
u8 size_order;
u32 ext_deg1; // Degree of first field extension
u32 ext_deg2; // Degree of second field extension
u32 at_0x1f; // unused
u32 at_0x23; // unused
u32 at_0x27; // unused
u32 num_elements; // Number of points Qi and length of H1 vector
u32 at_0x2f; // unused
u32 at_0x33; // unused
u32 at_0x37; // unused
u8 max_quotient; // Can equal floor((24 ^ 25) / p) - 1, unused
u8 h1_coeffs[num_elements]; // H1 radices
bignum modulus; // Prime modulus of base field
u8 order[size_order]; // Order of elliptic curve over base field (also a bignum)
// Polynomials are stored as bytes in order of lowest to highest degree coefficients
u8 ext_split_poly1[ext_deg1 + 1]; // Minimal polynomial of first field extension
u8 ext_split_poly2[ext_deg2 + 1]; // Minimal polynomial of second field extension
// Unused capability: y^2 = x^3 + ec_a_base * x + ec_b_base
// This curve would be over the base field
bignum ec_a_base;
bignum ec_b_base;
// Elliptic curve: y^2 = x^3 + ax + b
bignum ec_a; // a coefficient
bignum ec_b; // b coefficient
};
struct ecpoint_k3 {
bignum x[3];
bignum y[3];
};
struct Pubkey {
u32 magic; // 0x44556677
u16 eq256; // must be 0x0100
padding[2];
u32 field_data_size;
field_data field;
padding[field_data_size + 12 - $];
ecpoint_k3 points[field.num_elements]; // Points Qi over twisted curve
bignum pairing_val[field.ext_deg1 * field.ext_deg2]; // value of Tate pairing between generator P and signature base point S
};
Pubkey pubkey @ 0;
In total, the public key describes the following:
- The parameters of
$E$ :$a$ ,$b$ , and$m$ - The modulus of
$K$ :$p$ -
$F_1$ , the splitting polynomial of$K_3$ over$K$ -
$F_2$ , the splitting polynomial of$K_6$ over$K_3$ -
$\vec{r}$ , a collection of radices used in the implementation of$H_1$ -
$\vec{Q}'$ , a collection of points over$E/K_3$ -
$c$ , the value of$e_m(P, S)$
From this, it can already be seen that the implementation of PKEY2005's signature scheme is different from the patent.
The first major departure from the patent is that BCDFGHJKMPQRTVWXY2346789
.
The value of
Another important note is the binary serialization of elements of extension fields.
Given an extension field
where
The patent also describes that points in
The method to undo this compression is implemented as follows:
- Let
$t$ be the primitive element of the extension from$K_3$ to$K_6$ . - Let
$d = t^2$ - Define
$E' = x^3 + d^2 ax + d^3 b$ - Define the untwist mapping
$\tau : E' \rightarrow E = (x,y) \rightarrow (t^{-2}x, t^{-3}y)$ - Given a point
$R' \in E/K_3$ , recover$R = \tau(R')$
Since the quadratic twist on
Next, the value of
The point
Afterwards, the value of M is recovered through the following algorithm, with
M = 0
# Indexing backwards from n ... 1, ignoring the first element
for i in range(len(r) - 1, 0, -1):
M *= r[i]
M += v[i]
The final value of M can then be interpreted with the following bitfields:
struct DECODED_PKEY {
uint auth : 10; // presumed to be authentication bits
uint pid : 30; // middle 9 digits of Product ID
bool upgrade : 1; // presumed to indicate upgrade keys
}
Finally, the reference pairing value of
Although much of the information involved in generating a signature is not provided in public keys, it turns out that all of the information necessary to generate signatures is theoretically recoverable.
The main property of PKEY2005 public keys that makes key generation theoretically possible is that the pairing value
This allows generation of product keys without needing to know the implementation of
Letting
And now with the value of
And now, the value of
As shown above, the only thing hindering product-key generation is finding the private key vector
- diamondggg, for providing the steps of the algorithm we hadn't reverse-engineered
- CONIGUERO, Neo-Desktop, Endermanch, and TheTank20, for assisting in the reverse-engineering process
- Microsoft, for making cool software worth researching ❤️