X-Ray Eyes in Cybersecurity

As a child, didn’t you want X-ray glasses? Just imagine being able to see though walls. Well, in cybersecurity, sometimes you need X-ray…

X-Ray Eyes in Cybersecurity

As a child, didn’t you want X-ray glasses? Just imagine being able to see though walls. Well, in cybersecurity, sometimes you need X-ray eyes, especially when looking at the details of our digital artefacts. So, let’s do a bit of delving into the formation of public key pairs and digital certificates. And, for me, cybersecurity is most interesting when we get down to the bits and bytes, and try to understand how all the elements fit together, and in how they are created.

Note, in this article, I will use the wonderful xxd program, and where “xxd -plain” converts from byte values into a hex string. We normally use hex strings to be able to view and edit binary values.

PEM and DER

One of the great things about cryptography is the way we have managed to migrate our methods. This migration is often required when we introduce new methods (such as with ECC) or where methods are deprecated (such as for DES). We thus have ways to define new methods and which can be easily interpreted by applications. At the core of this is the DER format for defining our cryptography.

We need ways to distribute our public keys, private keys and digital certificates in a portable format. One of the most common forms is Distinguished Encoding Rules (DER) encoding of ASN.1 (Abstract Syntax Notation One). Overall it is a truly binary representation of the encoded data.

The other common format is PEM, which converts the binary encoding into a text-readable format. With PEM we can encode cryptographic information in a Base64 ASCII format and with plain-text headers and footers of “ — — -BEGIN RSA PRIVATE KEY — — -” and “ — — -END RSA PRIVATE KEY — — -”, whereas with DER, we have binary format.

An example private key is [here]:

-----BEGIN PRIVATE KEY-----
MIGHAgEAMBMGByqGSM49AgEGCCqGSM49AwEHBG0wawIBAQQgbWQGAmoVJCTfv6dE
N/55Al6OHA3DQ7GHesXij/WPQ0ShRANCAARidNTJiKD+rwqAITZNihCI6rWucirb
XMr2lKGvXPHgeK9uBp5UQ14kW7SrMSh3hthlSOJuuSENzK9K0OmVm07K
-----END PRIVATE KEY-----

A public key [here]:

-----BEGIN PUBLIC KEY-----
MFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEYnTUyYig/q8KgCE2TYoQiOq1rnIq
21zK9pShr1zx4HivbgaeVENeJFu0qzEod4bYZUjibrkhDcyvStDplZtOyg==
-----END PUBLIC KEY-----

A certificate [here]:

-----BEGIN CERTIFICATE-----
MIIBaTCCAQ+gAwIBAgIBBDAKBggqhkjOPQQDAjAYMRYwFAYDVQQDDA1BU2VjdXJp
dHlzaXRlMB4XDTE1MTIzMTIzNTk1OVoXDTI1MTIzMTIzNTk1OVowFTETMBEGA1UE
AwwKV2ViIHNlcnZlcjBZMBMGByqGSM49AgEGCCqGSM49AwEHA0IABGJ01MmIoP6v
CoAhNk2KEIjqta5yKttcyvaUoa9c8eB4r24GnlRDXiRbtKsxKHeG2GVI4m65IQ3M
r0rQ6ZWbTsqjTTBLMAkGA1UdEwQCMAAwDgYDVR0PAQH/BAQDAgeAMC4GA1UdHwQn
MCUwI6AhoB+GHWh0dHA6Ly9ib2IuYXNlY3VyaXR5c2l0ZS5jb20vMAoGCCqGSM49
BAMCA0gAMEUCIQDJykBnped+C6r7SbhYFDMemMoUZ/6JaVmhGdOEnr8XxQIgVbhD
xb8HiBvve7BxHnyHv7DREt7nE8fI3Y4IPu80ADw=
-----END CERTIFICATE-----

DER format

This article will look at the DER format and use OpenSSL to decode a hex string and its contents. Overall ASN.1 is used to define abstract types and values. One of the most basic types is SEQUENCE and is an ordered collection of one or more types. In DER, SEQUENCE is identified with a tag of “30”, and followed by a byte value for the length of the object defined. The other common types are OBJECT IDENTIFIER (and which has a tag of “06”) and BIT STRING (and which has a tag of “03”).

The object identifier tag is used to define the cryptography methods used. An example identifier for ECC encryption is “1.2.840.10045.2.1”, and where 1 is OSI, 2 is member body, 840 is US (ANSI), and 10045 is “ansi-X9–62”, and “2” is key type [1]. Other common algorithms are: “1.2.840.113549.1.1.1” (X509 RSA), “1.2.840.10040.4.1” (X509 Digital Signature Standard -DSS), and “1.2.840.10046.2.1” (Diffie-Hellman — DH). The following is an example of the hex sequence for an object ID, and where we have the “06” tag, followed by an identifier for seven bytes (“07”), and then the Object ID of seven bytes (“2a8648ce3d0201”):

06 07 2a8648ce3d0201  # Object ID -  7 bytes long: 1.2.840.10045.2.1 (ECC)

We can also define the curve type in the object identifier, and where we have the form of iso(1), member-body(2), us(840), ansi-X9–62(10045), curves(3), prime(1). For example, 1.2.840.10045.3.1.7 defines ECDSA P-256. Other examples are SECP192R1 (“1.2.840.10045.3.1.1”), SECP224R1 (“1.3.132.0.33”), SECP256K1 (“1.3.132.0.10”), SECP256R1 (“1.2.840.10045.3.1.7”), SECP384R1 (“1.3.132.0.34”), SECP521R1 (“1.3.132.0.35”), and BRAINPOOLP256R1 (“1.3.36.3.3.2.8.1.1.7”). An example where we have an identifier (“06”), followed by the number of bytes identifier (“08”) and Object ID of eight bytes (“2a8648ce3d030107”):

06 08 2a8648ce3d030107  # Object ID -  8 bytes long: 1.2.840.10045.3.1.7 (ECDSA P256)

For the “03” tag, we define a bitstream for keys. In the following, we have “03”, followed by the number of bytes (66 bytes) for the keys, and then the keys are defined after this (64 bytes):

03 42 # Bit stream - 0x42 (66 bytes long)
0004 # Identifies public key
2927b10512bae3eddcfe467828128bad2903269919f7086069c8c4df6c732838 # Identifies public key x co-ordinate
c7787964eaac00e5921fb1498a60f4606766b3d9685001558d1a974e7341513e # Identifies public key y co-ordinate

An example hex string for a DER format for ECC public keys is:

3059301306072a8648ce3d020106082a8648ce3d030107034200042927b10512bae3eddcfe467828128bad2903269919f7086069c8c4df6c732838c7787964eaac00e5921fb1498a60f4606766b3d9685001558d1a974e7341513

We can then break down with:

30 59 # Sequence length 0x59 -  91 bytes long
30 13 # Sequence length 0x13 - 21 bytes long
06 07 2a8648ce3d0201 # Object ID - 7 bytes long - 1.2.840.10045.2.1 (ECC)
06 08 2a8648ce3d030107 # Object ID - 8 bytes long - 1.2.840.10045.3.1.7 (ECDSA P256)
03 42 # Bit stream - 0x42 (66 bytes long)
0004 # Identifies public key
2927b10512bae3eddcfe467828128bad2903269919f7086069c8c4df6c732838 # Identifies public key x co-ordinate
c7787964eaac00e5921fb1498a60f4606766b3d9685001558d1a974e7341513e # Identifies public key y co-ordinate

If we OpenSSL, we can use xdd to convert the hex string into a byte array, and then parse for ASN1.

echo 3059301306072a8648ce3d020106082a8648ce3d030107034200042927b10512bae3eddcfe467828128bad2903269919f7086069c8c4df6c732838c7787964eaac00e5921fb1498a60f4606766b3d9685001558d1a974e7341513e 
| xxd -r -p | openssl asn1parse -inform der

0:d=0 hl=2 l= 89 cons: SEQUENCE
2:d=1 hl=2 l= 19 cons: SEQUENCE
4:d=2 hl=2 l= 7 prim: OBJECT :id-ecPublicKey
13:d=2 hl=2 l= 8 prim: OBJECT :prime256v1
23:d=1 hl=2 l= 66 prim: BIT STRING
0000 - 00 04 29 27 b1 05 12 ba-e3 ed dc fe 46 78 28 12 ..)'........Fx(.
0010 - 8b ad 29 03 26 99 19 f7-08 60 69 c8 c4 df 6c 73 ..)......`i...ls
0020 - 28 38 c7 78 79 64 ea ac-00 e5 92 1f b1 49 8a 60 (8.xyd.......I.`
0030 - f4 60 67 66 b3 d9 68 50-01 55 8d 1a 97 4e 73 41 .`gf..hP.U...NsA
0040 - 51 3e Q.

We can see that the bit string has a “00 04” are the start, and followed by the x-ordinate (0x2917 …) and (y-coordinate (0xc778…) of the public key.

ASN1 parsing for RSA keys

For RSA keys, we can generate a 512-bit key pair, and then convert to a hex DER string with:

(base) billbuchanan@ASecuritySite openssl % openssl genrsa 512 
| openssl rsa -outform der | xxd -plain
writing RSA key
30820154020100300d06092a864886f70d01010105000482013e3082013a
020100024100beeaa2dd3aa43a38904f57707465532c31ffe5904e2335d5
4a26b7ba046846a165cd72090e0b109cae3fc5e95e0c89d7531ffeaad319
3b0e9dae357481fac16102030100010240632216fb64edcdc57d39959fb0
f0c42558b9158cbee60d97f8eeedcbcb6a11f1e99d45890de936eb167c53
f45876d2fed8f31a889ab6029cc04b6d09e2657681022100f6cb29b3286f
46e3f025d9e71afb84aeb1e19fe874378d490e73ef2a3fab8ae9022100c6
09db5bb1906090e80d79d69109ec37359bafc06b9ed9fff97a5bcb9c1f07
b902201fdf7d333635a8e22751bc22acc96f0960cfd2e7229b4a13f559e3
b9811f96810221008e92de17df77ffed9302d0aa86f4cbd8db81604079ba
7d5be9f20b5044ef9a1102203092b0733f508f646ec80520db410860ebe7
d4bb15db8ad3703666b57b41fe75

For a 1,024-bit modulus, we generate a key pair with:

3082013a020100024100a53c172810b45f94cb1edbd6a7eeffd5fa94b4c692d00bec0760bc53dff8b3034ed82f92debb553ae6fc0663ab90247e71af25a7643ad055cec78345b92c36c7020301000102403de24885efe3ae1c8b0a6ea97151d8ad6a610167919aabac6582fc65a96f7a937b40f06c5594f0fe1a74b957e731a021f9b214bfcb7fecfee328a9b041eb8d41022100da6a12118066136f8b1478dd78625bb80ed2ffa6b525a0cbc89058a37040faa7022100c1ab44c7fd1fcc554f4143072361f0bf064619b25fcc54064def8692da5006e102203bf114585d46a65adc6e97e5201ece512b30591d2565d845551bd857b27d02cd02201acc03dc581dca3c1397481af8be587d55f4e521553804784ad8559a84328681022100bd24bc374ab656a11b2d531ac4eaebb5dd013848c654268d453942a39248bc32

If we parse we get [here]:

echo 3082013a020100024100a53c172810b45f94cb1edbd6a7eeffd5fa94b4c692d00bec0760bc53dff8b3034ed82f92debb553ae6fc0663ab90247e71af25a7643ad055cec78345b92c36c7020301000102403de24885efe3ae1c8b0a6ea97151d8ad6a610167919aabac6582fc65a96f7a937b40f06c5594f0fe1a74b957e731a021f9b214bfcb7fecfee328a9b041eb8d41022100da6a12118066136f8b1478dd78625bb80ed2ffa6b525a0cbc89058a37040faa7022100c1ab44c7fd1fcc554f4143072361f0bf064619b25fcc54064def8692da5006e102203bf114585d46a65adc6e97e5201ece512b30591d2565d845551bd857b27d02cd02201acc03dc581dca3c1397481af8be587d55f4e521553804784ad8559a84328681022100bd24bc374ab656a11b2d531ac4eaebb5dd013848c654268d453942a39248bc32 | xxd -r -p | openssl asn1parse -inform der

0:d=0 hl=4 l= 314 cons: SEQUENCE
4:d=1 hl=2 l= 1 prim: INTEGER :00
7:d=1 hl=2 l= 65 prim: INTEGER :A53C172810B45F94CB1EDBD6A7EEFFD5FA94B4C692D00BEC0760BC53DFF8B3034ED82F92DEBB553AE6FC0663AB90247E71AF25A7643AD055CEC78345B92C36C7
74:d=1 hl=2 l= 3 prim: INTEGER :010001
79:d=1 hl=2 l= 64 prim: INTEGER :3DE24885EFE3AE1C8B0A6EA97151D8AD6A610167919AABAC6582FC65A96F7A937B40F06C5594F0FE1A74B957E731A021F9B214BFCB7FECFEE328A9B041EB8D41
145:d=1 hl=2 l= 33 prim: INTEGER :DA6A12118066136F8B1478DD78625BB80ED2FFA6B525A0CBC89058A37040FAA7
180:d=1 hl=2 l= 33 prim: INTEGER :C1AB44C7FD1FCC554F4143072361F0BF064619B25FCC54064DEF8692DA5006E1
215:d=1 hl=2 l= 32 prim: INTEGER :3BF114585D46A65ADC6E97E5201ECE512B30591D2565D845551BD857B27D02CD
249:d=1 hl=2 l= 32 prim: INTEGER :1ACC03DC581DCA3C1397481AF8BE587D55F4E521553804784AD8559A84328681
283:d=1 hl=2 l= 33 prim: INTEGER :BD24BC374AB656A11B2D531AC4EAEBB5DD013848C654268D453942A39248BC32

The values in sequence are N, e, d, p, q, and where:

N=A53C172810B45F94CB1EDBD6A7EEFFD5FA94B4C692D00BEC0760BC53DFF8B3034ED82F92DEBB553AE6FC0663AB90247E71AF25A7643AD055CEC78345B92C36C7

e=010001

d=3DE24885EFE3AE1C8B0A6EA97151D8AD6A610167919AABAC6582FC65A96F7A937B40F06C5594F0FE1A74B957E731A021F9B214BFCB7FECFEE328A9B041EB8D41

p=DA6A12118066136F8B1478DD78625BB80ED2FFA6B525A0CBC89058A37040FAA7

q=C1AB44C7FD1FCC554F4143072361F0BF064619B25FCC54064DEF8692DA5006E1

We see that N has 128 bytes, and so is 1,024 bits long, and that p and q are 512 bit long. If we multiply p times q we get the modulus value:

>>> p=int("DA6A12118066136F8B1478DD78625BB80ED2FFA6B525A0CBC89058A37040FAA7",16)
>>> q=int("C1AB44C7FD1FCC554F4143072361F0BF064619B25FCC54064DEF8692DA5006E1",16)
>>> hex(p*q)
'0xa53c172810b45f94cb1edbd6a7eeffd5fa94b4c692d00bec0760bc53dff8b3034ed82f92debb553ae6fc0663ab90247e71af25a7643ad055cec78345b92c36c7'

and which is equal to the modulus (N).

ASN.1 parsing for ECC keys

We can generate a secp256k1 private key with (the -noout option does not generate the ECC parameters)

% openssl ecparam -genkey -name secp256r1 -outform der -noout | xxd -plain
using curve name prime256v1 instead of secp256r1
3077020101042037c67057c9350ce42d9aa365aa874c2f62db43bf309667
a25e5cae0a958c1065a00a06082a8648ce3d030107a144034200048bd1ff
01a5fe5cda52970c65d0cf41265391b4520d7709832a71f1af4796b8234f
212b7d8840ae45ee1f98c8b65e2d84fe64c6e5d709a206a1388f66eff58b
51

If we parse we get [here]:


DER string: 3077020101042037c67057c9350ce42d9aa365aa874c2f62db43bf309667a25e5cae0a958c1065a00a06082a8648ce3d030107a144034200048bd1ff01a5fe5cda52970c65d0cf41265391b4520d7709832a71f1af4796b8234f212b7d8840ae45ee1f98c8b65e2d84fe64c6e5d709a206a1388f66eff58b51


==Sequence==
Integer (02): 0x1
--->Sequence (A0)
--->Obj ID tag (06 - Object ID)
ID algorithm: 1.2.840.10045.3.1.7 secp256r1
--->Sequence (A1)
Bit value: b'048bd1ff01a5fe5cda52970c65d0cf41265391b4520d7709832a71f1af4796b8234f212b7d8840ae45ee1f98c8b65e2d84fe64c6e5d709a206a1388f66eff58b51'

If we use OpenSSL to parse we get [here]:

echo 3077020101042037c67057c9350ce42d9aa365aa874c2f62db43bf309667a25e5cae0a958c1065a00a06082a8648ce3d030107a144034200048bd1ff01a5fe5cda52970c65d0cf41265391b4520d7709832a71f1af4796b8234f212b7d8840ae45ee1f98c8b65e2d84fe64c6e5d709a206a1388f66eff58b51 | xxd -r -p | openssl asn1parse -inform der

0:d=0 hl=2 l= 119 cons: SEQUENCE
2:d=1 hl=2 l= 1 prim: INTEGER :01
5:d=1 hl=2 l= 32 prim: OCTET STRING
0000 - 37 c6 70 57 c9 35 0c e4-2d 9a a3 65 aa 87 4c 2f 7.pW.5..-..e..L/
0010 - 62 db 43 bf 30 96 67 a2-5e 5c ae 0a 95 8c 10 65 b.C.0.g.^\.....e
39:d=1 hl=2 l= 10 cons: cont [ 0 ]
41:d=2 hl=2 l= 8 prim: OBJECT :prime256v1
51:d=1 hl=2 l= 68 cons: cont [ 1 ]
53:d=2 hl=2 l= 66 prim: BIT STRING
0000 - 00 04 8b d1 ff 01 a5 fe-5c da 52 97 0c 65 d0 cf ........\.R..e..
0010 - 41 26 53 91 b4 52 0d 77-09 83 2a 71 f1 af 47 96 A.S..R.w..*q..G.
0020 - b8 23 4f 21 2b 7d 88 40-ae 45 ee 1f 98 c8 b6 5e .#O!+}...E.....^
0030 - 2d 84 fe 64 c6 e5 d7 09-a2 06 a1 38 8f 66 ef f5 -..d.......8.f..
0040 - 8b 51

The 00 04 part of the key identifies that it is an uncompressed point, and thus has an (x,y) value. Thus we have 64 bytes for the key, of which 32 bytes (256 bits) for an x coordinate value, and 32 byte for a y coordinate value.

References

[1] RFC 3279, Algorithms and Identifiers for the Internet X.509 Public Key Infrastructure Certificate and Certificate Revocation List (CRL) Profile [here]

A list of object IDs:

Hashing:
MD2 1.2.840.113549.2.2
MD5 1.2.840.113549.2.5
SHA-1 1.3.14.3.2.26
SHA-224 2.16.840.1.101.3.4.2.4
SHA-256 2.16.840.1.101.3.4.2.1
SHA-394 2.16.840.1.101.3.4.2.2
SHA-512 2.16.840.1.101.3.4.2.3Public key:RSA Encryption 1.2.840.113549.1.1.1
DSA 1.2.840.10040.4.1
Diffie-Hellman (dhPublicNumber) 1.2.840.10046.2.1
ECC (ecPublicKey) 1.2.840.10045.2.1
md2WithRsaEncryption 1.2.840.113549.1.1.2Signatures:
md5WithRsaEncryption 1.2.840.113549.1.1.4
sha1WithRsaEncryption 1.2.840.113549.1.1.5
sha224WithRsaEncryption 1.2.840.113549.1.1.14
sha256WithRsaEncryption 1.2.840.113549.1.1.11
sha384WithRsaEncryption 1.2.840.113549.1.1.12
sha512WithRsaEncryption 1.2.840.113549.1.1.13
dsaWithSha1 1.2.840.10040.4.3
dsaWithSha224 2.16.840.1.101.3.4.3.1
dsaWithSha256 2.16.840.1.101.3.4.3.2
ecdsaWithSha1 1.2.840.10045.4.1
ecdsaWithSha224 1.2.840.10045.4.3.1
ecdsaWithSha256 1.2.840.10045.4.3.2
ecdsaWithSha384 1.2.840.10045.4.3.3
ecdsaWithSha512 1.2.840.10045.4.3.4Password Base Encryption Algorithms:
pbeWithMd2AndDesCbc 1.2.840.113549.1.5.1
pbeWithMd5AndDesCbc 1.2.840.113549.1.5.3
pbeWithSha1AndDesCbc 1.2.840.113549.1.5.10
pbeWithMd2AndRc2Cbc 1.2.840.113549.1.5.4
pbeWithMd5AndRc2Cbc 1.2.840.113549.1.5.6
pbeWithSha1AndRc2Cbc 1.2.840.113549.1.5.11
pbeWithSha1And40BitRc2Cbc 1.2.840.113549.1.12.1.6
pbeWithSha1And128BitRc2Cbc 1.2.840.113549.1.12.1.5
pbeWithSha1And40BitRc4 1.2.840.113549.1.12.1.2
pbeWithSha1And128BitRc4 1.2.840.113549.1.12.1.1
pbeWithSha1And3DesCbc 1.2.840.113549.1.12.1.3Symmetric Encryption Algorithms:
DES CBC 1.3.14.3.2.7
3DES CBC 1.2.840.113549.3.7
RC2 1.2.840.113549.3.2
ArcFour 1.2.840.113549.3.4
AES CBC 128 2.16.840.1.101.3.4.1.2
AES CBC 256 2.16.840.1.101.3.4.1.42x.500 Distinguished Name Attributes:
name 2.5.4.41
surname 2.5.4.4
given name 2.5.4.42
initials 2.5.4.43
generation qualifier 2.5.4.44
common name 2.5.4.3
locality name 2.5.4.7
state or province name 2.5.4.8
organization name 2.5.4.10
organizational unit name 2.5.4.11
title 2.5.4.12
dnQualifier 2.5.4.46
country name 2.5.4.6
email address 1.2.840.113549.1.9.1
domain component 0.9.2342.19200300.100.1.25
street address 2.5.4.9
postal code 2.5.4.17
mail 0.9.2342.19200300.100.1.3
serial number 2.5.4.5ECC names:
secp192r1 1.2.840.10045.3.1.1
secp224r1 1.3.132.0.33
secp256r1 1.2.840.10045.3.1.7
secp384r1 1.3.132.0.34
secp521r1 1.3.132.0.35
brainpoolP160r1 1.3.36.3.3.2.8.1.1.1
brainpoolP192r1 1.3.36.3.3.2.8.1.1.3
brainpoolP224r1 1.3.36.3.3.2.8.1.1.5
brainpoolP256r1 1.3.36.3.3.2.8.1.1.7
brainpoolP320r1 1.3.36.3.3.2.8.1.1.9
brainpoolP384r1 1.3.36.3.3.2.8.1.1.11
brainpoolP512r1 1.3.36.3.3.2.8.1.1.13