Quantcast
Channel: VBForums - CodeBank - Visual Basic 6 and earlier
Viewing all articles
Browse latest Browse all 1448

Certificate Verify

$
0
0
My knowledge of ECDSA Certificate handling was minimal, but in order to produce a TLS 1.3 web server, RFC 8446 requires support for digitial signatures. So after a laborious learning experience, I decided to post what I learned.

The private key is recovered from the "privkey.pem" Base64 encoded file, decoded to ASN.1 format, and finally to a Private EC Key.
Code:

Base64 Encoded File:
-----BEGIN EC PRIVATE KEY-----
MHcCAQEEIMrOBboK+r8CzXUj6EJG67fUX9UGz2K+sMFsGiOlZQProAoGCCqGSM49
AwEHoUQDQgAEU0GMUttccTAXPsGYQyrF0gZt0KuRWpmnq8Zt0IvG6ZwrMoPg9slF
sXYQOQ8hOKkQwLYzKbQgifvKw6aB/xnLtQ==
-----END EC PRIVATE KEY-----

ASN.1 Private Key:
30 77 02 01 01 04 20 CA CE 05 BA 0A FA BF 02 CD
75 23 E8 42 46 EB B7 D4 5F D5 06 CF 62 BE B0 C1
6C 1A 23 A5 65 03 EB A0 0A 06 08 2A 86 48 CE 3D
03 01 07 A1 44 03 42 00 04 53 41 8C 52 DB 5C 71
30 17 3E C1 98 43 2A C5 D2 06 6D D0 AB 91 5A 99
A7 AB C6 6D D0 8B C6 E9 9C 2B 32 83 E0 F6 C9 45
B1 76 10 39 0F 21 38 A9 10 C0 B6 33 29 B4 20 89
FB CA C3 A6 81 FF 19 CB B5

Private Key:
04 53 41 8C 52 DB 5C 71 30 17 3E C1 98 43 2A C5
D2 06 6D D0 AB 91 5A 99 A7 AB C6 6D D0 8B C6 E9
9C 2B 32 83 E0 F6 C9 45 B1 76 10 39 0F 21 38 A9
10 C0 B6 33 29 B4 20 89 FB CA C3 A6 81 FF 19 CB
B5 CA CE 05 BA 0A FA BF 02 CD 75 23 E8 42 46 EB
B7 D4 5F D5 06 CF 62 BE B0 C1 6C 1A 23 A5 65 03
EB

Then the Magic string is added to form the Blob, which is used to sign the extended Session Hash, which is then ASN.1 encoded to form the Certificate Verify record. Note that the Compression byte (&H04) is overwritten and not required.
Code:

Private Key Blob:
45 43 53 32 20 00 00 00 53 41 8C 52 DB 5C 71 30
17 3E C1 98 43 2A C5 D2 06 6D D0 AB 91 5A 99 A7
AB C6 6D D0 8B C6 E9 9C 2B 32 83 E0 F6 C9 45 B1
76 10 39 0F 21 38 A9 10 C0 B6 33 29 B4 20 89 FB
CA C3 A6 81 FF 19 CB B5 CA CE 05 BA 0A FA BF 02
CD 75 23 E8 42 46 EB B7 D4 5F D5 06 CF 62 BE B0
C1 6C 1A 23 A5 65 03 EB                       

Hash:
20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20
20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20
20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20
20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20
54 4C 53 20 31 2E 33 2C 20 73 65 72 76 65 72 20
43 65 72 74 69 66 69 63 61 74 65 56 65 72 69 66
79 00 C8 A1 31 6D 80 8B BE C9 60 3B 1B CF 57 2B
99 02 8C B0 0A 64 7A BE C5 93 AA 88 6C C8 60 70
78 54                                         

Signed Hash:
99 B5 49 9B D1 4D 82 52 19 CA E5 EC E8 A2 49 81
59 57 21 19 4B 67 8B 2A 62 19 71 21 E6 94 19 5E
99 A4 E7 12 CA 7A 0E 8D BE D2 F3 E0 C8 7C EE EC
B9 52 D9 F8 F4 07 25 2C 61 BF 77 64 C5 75 32 88

Cert Verify:
0F 00 00 4B 04 03 00 47 30 45 02 20 5E 19 94 E6
21 71 19 62 2A 8B 67 4B 19 21 57 59 81 49 A2 E8
EC E5 CA 19 52 82 4D D1 9B 49 B5 99 02 21 00 88
32 75 C5 64 77 BF 61 2C 25 07 F4 F8 D9 52 B9 EC
EE 7C C8 E0 F3 D2 BE 8D 0E 7A CA 12 E7 A4 99

That record is then encrypted and sent to the client directly after the Certificate itself. At the client end, the Cert Verify is decrypted, then ASN.1 decoded to get the signed hash. The Public Key is normally extracted from the Certificate, but in this case I extracted it from the Private Key. If anyone knows of an efficient way to extract the key from the Certificate, I would be very interested. Anyway, the Public Key Blob and the Signature are fed into the BCryptVerifySignature function and verified. That routine supposedly wants the original Hash itself, but I discovered that it only needs a 32 byte string (no explanation offered).
Code:

Public Key Blob:
45 43 53 31 20 00 00 00 53 41 8C 52 DB 5C 71 30
17 3E C1 98 43 2A C5 D2 06 6D D0 AB 91 5A 99 A7
AB C6 6D D0 8B C6 E9 9C 2B 32 83 E0 F6 C9 45 B1
76 10 39 0F 21 38 A9 10 C0 B6 33 29 B4 20 89 FB
CA C3 A6 81 FF 19 CB B5                       

Certificate Hash:
20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20
20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20

Hash Signature:
0C 06 0A AA 8F 7A 44 20 C7 DD FE A6 CF 2D 63 31
02 A1 29 B3 27 8E 36 72 77 04 B3 C8 90 A4 CF 61
9E 90 AC CC DC 6E F5 46 5B 9E C7 EF 1B 2C DE 5E
0A 7E B9 0B 00 55 D6 C2 06 F3 CE 7D F4 3D F0 BD

Certificate Verified!

There are a few extra buttons that directly demonstrate some functions.
1. Verify Test - This routine demonstrates what happens when a Private key does not match the Public key.
2. Convert String - This was added because I used a different method to convert a Unicode ASCII string to a byte string and back again. I am hoping that this new routine handles ASCII values greater than &H7F, and is more efficient than my old routine.
3. Cert Verify - This routine demonstrates the conversion of an ASN.1 encoded key to a Base64 encoded file format.

J.A. Coutts
Attached Files

Viewing all articles
Browse latest Browse all 1448

Trending Articles



<script src="https://jsc.adskeeper.com/r/s/rssing.com.1596347.js" async> </script>