|
| 1 | +========== |
| 2 | +ECC basics |
| 3 | +========== |
| 4 | + |
| 5 | +The :term:`ECC`, as any asymmetric cryptography system, deals with private |
| 6 | +keys and public keys. Private keys are generally used to create signatures, |
| 7 | +and are kept, as the name suggest, private. That's because possession of a |
| 8 | +private key allows creating a signature that can be verified with a public key. |
| 9 | +If the public key is associated with an identity (like a person or an |
| 10 | +institution), possession of the private key will allow to impersonate |
| 11 | +that identity. |
| 12 | + |
| 13 | +The public keys on the other hand are widely distributed, and they don't |
| 14 | +have to be kept private. The primary purpose of them, is to allow |
| 15 | +checking if a given signature was made with the associated private key. |
| 16 | + |
| 17 | +On a more low level, the private key is a single number, usually the |
| 18 | +size of the curve size: a NIST P-256 private key will have a size of 256 bits, |
| 19 | +though as it needs to be selected randomly, it may be a slightly smaller |
| 20 | +number (255-bit, 248-bit, etc.). |
| 21 | +Public points are a pair of numbers. That pair specifies a point on an |
| 22 | +elliptic curve (a pair of points that satisfy the curve equation). |
| 23 | +Those two numbers are similarly close in size to the curve size, so both the |
| 24 | +``x`` and ``y`` coordinate of a NIST P-256 curve will also be around 256 bit in |
| 25 | +size. |
| 26 | + |
| 27 | +.. note:: |
| 28 | + To be more precise, the size of the private key is related to the |
| 29 | + curve *order*, i.e. the number of points on a curve. The coordinates |
| 30 | + of the curve depend on the *field* of the curve, which usually means the |
| 31 | + size of the *prime* used for operations on points. While the *order* and |
| 32 | + the *prime* size are related and fairly close in size, it's possible |
| 33 | + to have a curve where either of them is larger by a bit (i.e. |
| 34 | + it's possible to have a curve that uses a 256 bit prime that has a 257 bit |
| 35 | + order). |
| 36 | + |
| 37 | +Since normally computers work with much smaller numbers, like 32 bit or 64 bit, |
| 38 | +we need to use special approaches to represent numbers that are hundreds of |
| 39 | +bits large. |
| 40 | + |
| 41 | +First is to decide if the numbers should be stored in a big |
| 42 | +endian format, or in little endian format. In big endian, the most |
| 43 | +significant bits are stored first, so a number like :math:`2^{16}` is saved |
| 44 | +as a three of byes: byte with value 1 and two bytes with value 0. |
| 45 | +In little endian format the least significant bits are stored first, so |
| 46 | +the number like :math:`2^{16}` would be stored as three bytes: |
| 47 | +first two bytes with value 0, than a byte with value 1. |
| 48 | + |
| 49 | +For :term:`ECDSA` big endian encoding is usually used, for :term:`EdDSA` |
| 50 | +little endian encoding is usually used. |
| 51 | + |
| 52 | +Secondly, we need to decide if the numbers need to be stored as fixed length |
| 53 | +strings (zero padded if necessary), or if they should be stored with |
| 54 | +minimal number of bytes necessary. |
| 55 | +That depends on the format and place it's used, some require strict |
| 56 | +sizes (so even if the number encoded is 1, but the curve used is 128 bit large, |
| 57 | +that number 1 still needs to be encoded with 16 bytes, with fifteen most |
| 58 | +significant bytes equal zero). |
| 59 | + |
| 60 | +Generally, public keys (i.e. points) are expressed as fixed size byte strings. |
| 61 | + |
| 62 | +While public keys can be saved as two integers, one to represent the |
| 63 | +``x`` coordinate and one to represent ``y`` coordinate, that actually |
| 64 | +provides a lot of redundancy. Because of the specifics of elliptic curves, |
| 65 | +for every valid ``x`` value there are only two valid ``y`` values. |
| 66 | +Moreover, if you have an ``x`` values, you can compute those two possible |
| 67 | +``y`` values (if they exist). |
| 68 | +As such, it's possible to save just the ``x`` coordinate and the sign |
| 69 | +of the ``y`` coordinate (as the two possible values are negatives of |
| 70 | +each-other: :math:`y_1 == -y_2`). |
| 71 | + |
| 72 | +That gives us few options to represent the public point, the most common are: |
| 73 | + |
| 74 | +1. As a concatenation of two fixed-length big-endian integers, so called |
| 75 | + :term:`raw encoding`. |
| 76 | +2. As a concatenation of two fixed-length big-endian integers prefixed with |
| 77 | + the type of the encoding, so called :term:`uncompressed` point |
| 78 | + representation (the type is represented by a 0x04 byte). |
| 79 | +3. As a fixed-length big-endian integer representing the ``x`` coordinate |
| 80 | + prefixed with the byte representing the combined type of the encoding |
| 81 | + and the sign of the ``y`` coordinate, so called :term:`compressed` |
| 82 | + point representation. |
| 83 | + |
| 84 | +Now, while we can save the byte strings as-is and "remember" which curve |
| 85 | +was used to generate those private and public keys, interoperability usually |
| 86 | +requires us to also save information about the curve together with the |
| 87 | +corresponding key. Here too there are many ways to do it: |
| 88 | +save the parameters of the used curve explicitly, use the name of the |
| 89 | +well-known curve as a string, use a numerical identifier of the well-known |
| 90 | +curve, etc. |
| 91 | + |
| 92 | +For public keys the most interoperable format is the one described |
| 93 | +in RFC5912 (look for SubjectPublicKeyInfo structure). |
| 94 | +For private keys, the RFC5915 format (also known as the ssleay format) |
| 95 | +and the PKCS#8 format (described in RFC5958) are the most popular. |
| 96 | +All of those specify a binary encoding, called DER, which can use |
| 97 | +bytes with any values. For some uses it's useful to limit byte use |
| 98 | +to printable characters, then the PEM formatting of the DER-encoded data |
| 99 | +can be used. |
0 commit comments