Skip to content

Commit 8c051b1

Browse files
committed
FEAT: added support to load X.509 encoded private RSA keys
1 parent 3cdba9b commit 8c051b1

File tree

4 files changed

+163
-72
lines changed

4 files changed

+163
-72
lines changed

src/mezz/codec-ssh-key.reb

+55-51
Original file line numberDiff line numberDiff line change
@@ -23,9 +23,37 @@ wrap [
2323
return rsa-init n e
2424
]
2525
]
26-
print ["Not RSA key! (" v ")"]
26+
sys/log/error 'REBOL ["Not RSA key! (" v ")"]
2727
none
2828
]
29+
init-rsa-public-key: function [data [block!]][
30+
parse data [
31+
'SEQUENCE into [
32+
'INTEGER set n: binary! ;modulus
33+
'INTEGER set e: binary! ;publicExponent
34+
]
35+
]
36+
rsa-init n e
37+
]
38+
init-rsa-private-key: function [data [block!]][
39+
parse data [
40+
'SEQUENCE into [
41+
'INTEGER set v: binary! ;version
42+
'INTEGER set n: binary! ;modulus
43+
'INTEGER set e: binary! ;publicExponent
44+
'INTEGER set d: binary! ;privateExponent
45+
'INTEGER set p: binary! ;prime1
46+
'INTEGER set q: binary! ;prime2
47+
;- dp, dq and qp are computed when initialized, so not used here
48+
;'INTEGER set dp: binary! ;exponent1 d mod (p-1)
49+
;'INTEGER set dq: binary! ;exponent2 d mod (q-1)
50+
;'INTEGER set qp: binary! ;coefficient (inverse of q) mod p
51+
to end
52+
]
53+
to end
54+
]
55+
rsa-init/private n e d p q
56+
]
2957

3058
register-codec [
3159
name: 'ssh-key
@@ -52,22 +80,21 @@ wrap [
5280
][ init-from-ssh2-key key ]
5381
]
5482
if "4,ENCRYPTED" = select pkix/header "Proc-Type" [
55-
print "ENCRYPTED key!"
83+
sysl/log/info 'REBOL "ENCRYPTED key!"
5684
try/except [
5785
dek-info: select pkix/header "DEK-Info"
58-
;probe dek-info
86+
sysl/log/info 'REBOL ["Using:" dek-info]
5987
parse dek-info [
6088
"AES-128-CBC" #"," copy iv to end
6189
]
6290
iv: debase iv 16
6391
unless p [p: ask/hide "Pasword: "]
64-
p: checksum
65-
join to binary! p copy/part iv 8
66-
'md5
92+
p: checksum (join to binary! p copy/part iv 8) 'md5
6793
d: aes/key/decrypt p iv
6894
pkix/binary: aes/stream d pkix/binary
6995
][ return none ]
7096
]
97+
sys/log/info 'REBOL ["Trying to resolve:" pkix/label]
7198

7299
switch pkix/label [
73100
"SSH2 PUBLIC KEY" [
@@ -78,66 +105,43 @@ wrap [
78105
try/except [
79106
data: codecs/der/decode pkix/binary
80107
][
81-
print "Failed to decode DER day for RSA key!"
82-
probe system/state/last-error
108+
sys/log/error 'REBOL "Failed to decode DER day for RSA key!"
109+
sys/log/error 'REBOL system/state/last-error
83110
return none
84111
]
85112

86113
switch pkix/label [
87-
"PUBLIC KEY" [
88-
; resolve RSA public data from the DER structure (PKCS#1)
89-
all [
114+
"PUBLIC KEY"
115+
"PRIVATE KEY" [
116+
; resolve key data from the DER structure (PKCS#1)
117+
return attempt [
90118
parse data [
91119
'SEQUENCE into [
92-
'SEQUENCE set v: block! ; AlgorithmIdentifier
93-
'BIT_STRING set data: binary! ; PublicKey
120+
opt ['INTEGER binary!]
121+
'SEQUENCE into [
122+
'OBJECT_IDENTIFIER set oid: binary! ; AlgorithmIdentifier
123+
to end ;'NULL binary!
124+
]
125+
['BIT_STRING | 'OCTET_STRING] set data: binary! ; PublicKey
94126
(
95127
data: codecs/der/decode data
96128
)
97129
]
98130
]
99-
v/OBJECT_IDENTIFIER = #{2A864886F70D010101} ;= rsaEncryption
100-
parse data [
101-
'SEQUENCE into [
102-
'INTEGER set n: binary! ;modulus
103-
'INTEGER set e: binary! ;publicExponent
131+
switch/default oid [
132+
#{2A864886F70D010101} [ ;= rsaEncryption
133+
return either pkix/label = "PUBLIC KEY" [
134+
init-rsa-public-key data
135+
][ init-rsa-private-key data ]
104136
]
137+
][
138+
sys/log/error 'REBOL ["Unknown key type:" codecs/der/decode-OID oid]
139+
none
105140
]
106141
]
107-
; resolve RSA handle from parsed data
108-
return rsa-init n e
109-
]
110-
"RSA PUBLIC KEY" [
111-
; resolve RSA public data from the DER structure (PKCS#1)
112-
parse data [
113-
'SEQUENCE into [
114-
'INTEGER set n: binary! ;modulus
115-
'INTEGER set e: binary! ;publicExponent
116-
]
117-
]
118-
; resolve RSA handle from parsed data
119-
return rsa-init n e
120-
]
121-
"RSA PRIVATE KEY" [
122-
; resolve RSA private data from the DER structure (PKCS#1)
123-
parse data [
124-
'SEQUENCE into [
125-
'INTEGER set v: binary! ;version
126-
'INTEGER set n: binary! ;modulus
127-
'INTEGER set e: binary! ;publicExponent
128-
'INTEGER set d: binary! ;privateExponent
129-
'INTEGER set p: binary! ;prime1
130-
'INTEGER set q: binary! ;prime2
131-
'INTEGER set dp: binary! ;exponent1 d mod (p-1)
132-
'INTEGER set dq: binary! ;exponent2 d mod (q-1)
133-
'INTEGER set inv: binary! ;coefficient (inverse of q) mod p
134-
to end
135-
]
136-
to end
137-
]
138-
; resolve RSA handle from parsed data
139-
return rsa-init/private n e d p q dp dq inv
140142
]
143+
"RSA PUBLIC KEY" [ return init-rsa-public-key data ]
144+
"RSA PRIVATE KEY" [ return init-rsa-private-key data ]
141145
]
142146
none ; no success!
143147
]
+31
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
-----BEGIN CERTIFICATE-----
2+
MIIFQzCCAyugAwIBAgIJAMs479eTDagfMA0GCSqGSIb3DQEBCwUAMDgxDzANBgNV
3+
BAoMBlJlYm9sMzERMA8GA1UECwwIVGVzdENlcnQxEjAQBgNVBAMMCWxvY2FsaG9z
4+
dDAeFw0yMjAyMTQwOTQ2MzVaFw0yMzAyMTQwOTQ2MzVaMDgxDzANBgNVBAoMBlJl
5+
Ym9sMzERMA8GA1UECwwIVGVzdENlcnQxEjAQBgNVBAMMCWxvY2FsaG9zdDCCAiIw
6+
DQYJKoZIhvcNAQEBBQADggIPADCCAgoCggIBAKZNLMJO1Tb8xXNktj32QU+WH3Cn
7+
iaJQ7kER3Ez61uEAApD5ufU3eE2CYg27ul7aXocA9bFrl8M3IBSvCI58fnIiaz73
8+
1erQQRHirWjvK4GFwiE1Jj6pUxON49ghbq+UMvLQ1IMDqsGjKjw9KL+u4615EEAd
9+
eIigrNPVKLevo6tXdkdAAJ+nSKz8uNwHgW2iazNoh9C5T2cEdZ7e4Q4BsX7oMcZR
10+
Xb8MZQvFmYQgtL/AHg9SuuJagTIkZ9To5XOMROjSbRCyQnd55X6ckW3hrROotEf1
11+
vp69ik1vlBsNVibttk+6dOHl9IZd18D++qrKUYxRKZUr3/xmn8oavvYcWX+Sohgc
12+
djIkT5pASWzteVg6AcFyEbDhj08cef4QyLyBueG0ucY6eTTliknbjKssPpX6I9S4
13+
G+YQwds1fdOWYiCuXvsBqMakMagyoua+3OZRwnZYEljS4TomdlHYi+XeM7rckIxk
14+
m+IWz4sHX/APmh3mXq5EBXzhyJKC0qNTY8++TKax+QiD1q9IeNp1WxpiAlTT7aDz
15+
Pt3//GtHQ/BghVPFHHRGumI+I/D3jQt5M6lp6VpJYz39evcUgP8VAsrUzD8gTiTb
16+
+5Bu2DvZyOAdhGhI4p89DXwXkTtK7Na1N2/FN1zEGOEMd+xgeVc3aqQmx8JCGq69
17+
QTWvn3MY2IVDPAChAgMBAAGjUDBOMB0GA1UdDgQWBBQlFfh6orfcbhSfclJCrfhk
18+
bLxuZjAfBgNVHSMEGDAWgBQlFfh6orfcbhSfclJCrfhkbLxuZjAMBgNVHRMEBTAD
19+
AQH/MA0GCSqGSIb3DQEBCwUAA4ICAQAyEZbultlpt7o9HuMe/iL9xfZr2c3Pizbc
20+
iHuUAB6NZFAsW680uNXIU7V6i7roPPynPE5Wi1nx3Jlzlw7a/ee+8lBLrLEXWJDV
21+
2VjLbfZvstKtsvp2BPibvak2PXjT8EGr9HhtTurzKTZW4ULjvaf6UzgBTIdJrDsR
22+
e0zKDS3z3AB2hLUq3yV0I6XZK/I8nVFWXJhXgI3OFeTyOWDDsd4Odfbc9ISXtZeU
23+
RHOpcTkQ65FUuAkvBZKtlPSLgQR1qwEDspGm6YpPzUFdKdNIRh8svv5ny6FxfLwF
24+
82ib9L13YWB1gHpvxjrHR3ydcS/7LZQPcDdWlpbIzS4NBsqa1EgxMvsOzbuEDMXS
25+
IFBT+JY6NzASs9YK9lsx9T05oSl/yvF19OF7gMsEdct/zxits9arC0m3+zvykM8k
26+
RoxRE4asFIaUVE+y54N9hZqNrU43g2++Ln9/L27fL20XeBqDMJ5DKmVoVZr6ALTn
27+
EhH6AbQoQSJc3upwSv2N6tDfRsC/bqv3cuH3Z/LuuePW3eRiYpBIugrCGyYbR8Ip
28+
7gb4xCA1wll13LfMWVBJ01dtkABrEFye2/1iPt4UUQJ8VAJ329l0obLbTdVRDXYa
29+
Q1aOe2F1jlqGPbhu1it27ep1rsZzQC0ZUZr4jkSr0aRVbSJAOStnTOlOhloiCnGj
30+
rvs7V8Ow9Q==
31+
-----END CERTIFICATE-----

src/tests/units/files/MyKey.key

+52
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,52 @@
1+
-----BEGIN PRIVATE KEY-----
2+
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
51+
16AeXFDJSx8U70+5T6rF9x2ZL1DYXwQd
52+
-----END PRIVATE KEY-----

src/tests/units/rsa-test.r3

+25-21
Original file line numberDiff line numberDiff line change
@@ -44,28 +44,29 @@ Rebol [
4444
55E38967EDFCD1848A8BE89E2CE12A9A3D5554BBF13CC583190876B79C45ECEC
4545
67ED6461DFECD6A0DBC6D9031207C0213006F4B527003BA7E2F21C6FAC9E9719
4646
}
47-
dp: #{
48-
1B8B0F5E473A61AF72F28256F7F20B8F8C6EA69BB49738BF1FB553912F318F94
49-
9D5F7728134A22998C31222D9E99302E7B450E6B97698051B2049E1CF2D43654
50-
5E34D9746E80A0D33FC6A4621168E6D000EFB41EFCD9ADB9865CDC2DE6DC8DB8
51-
1B61AF479B120F153200DDB3ABC2DF9FD1149ACEAB63739BF187A22A44E2063D
52-
}
53-
dq: #{
54-
B3D9401FD7E0801B28151F0E69CD91FC4DA0C36F36AD3DA418E021BC89651131
55-
3579FAC0EA1B9452F31F05C3299FC96A796EAFCF39D8639492405EE931D0BF6A
56-
02379C6F086E9D4151BD09522ADA44DA947CB85C41BFDDF461780E1EDEEF859B
57-
46CA1B4689EE8D360DD7109A3FA4CEEB58EF5AB5FE2F5F2DC57C38F7843F7209
58-
}
59-
qi: #{
60-
1B233FA7A26B5F24A2CF5B6816029B595F89748DE3438CA9BBDADB316C77AD02
61-
417E6B7416863381421911514470EAB07A644DF35CE80C069AF819342963460E
62-
3247643743985856DC037B948FA9BB193F987646275D6BC7247C3B9E572D27B7
63-
48F9917CAC1923AC94DB8671BD0285608B5D95D50A1B33BA21AEB34CA8405515
64-
}
47+
;- dp, dq and qp are computed when initialized, so not used here
48+
;dp: #{
49+
;1B8B0F5E473A61AF72F28256F7F20B8F8C6EA69BB49738BF1FB553912F318F94
50+
;9D5F7728134A22998C31222D9E99302E7B450E6B97698051B2049E1CF2D43654
51+
;5E34D9746E80A0D33FC6A4621168E6D000EFB41EFCD9ADB9865CDC2DE6DC8DB8
52+
;1B61AF479B120F153200DDB3ABC2DF9FD1149ACEAB63739BF187A22A44E2063D
53+
;}
54+
;dq: #{
55+
;B3D9401FD7E0801B28151F0E69CD91FC4DA0C36F36AD3DA418E021BC89651131
56+
;3579FAC0EA1B9452F31F05C3299FC96A796EAFCF39D8639492405EE931D0BF6A
57+
;02379C6F086E9D4151BD09522ADA44DA947CB85C41BFDDF461780E1EDEEF859B
58+
;46CA1B4689EE8D360DD7109A3FA4CEEB58EF5AB5FE2F5F2DC57C38F7843F7209
59+
;}
60+
;qp: #{
61+
;1B233FA7A26B5F24A2CF5B6816029B595F89748DE3438CA9BBDADB316C77AD02
62+
;417E6B7416863381421911514470EAB07A644DF35CE80C069AF819342963460E
63+
;3247643743985856DC037B948FA9BB193F987646275D6BC7247C3B9E572D27B7
64+
;48F9917CAC1923AC94DB8671BD0285608B5D95D50A1B33BA21AEB34CA8405515
65+
;}
6566
]
6667
--test-- "Init RSA keys"
6768
--assert handle? key-pub: rsa-init ko/n ko/e ;<-- this key has only public properties
68-
--assert handle? key-pri: rsa-init/private ko/n ko/e ko/d ko/p ko/q ko/dp ko/dq ko/qi
69+
--assert handle? key-pri: rsa-init/private ko/n ko/e ko/d ko/p ko/q ;ko/dp ko/dq ko/qp
6970
--assert "#[handle! rsa]" = mold key-pub
7071
--assert "#[handle! rsa]" = mold key-pri
7172
;@@ https://github.com/Oldes/Rebol-issues/issues/906
@@ -126,9 +127,12 @@ Rebol [
126127
===end-group===
127128

128129
===start-group=== "RSA initialization from file"
129-
--test-- "RSA private key from OpenSSL format"
130+
--test-- "RSA private key from OpenSSL format (RSA PRIVATE KEY)"
130131
--assert handle? try [private-key: load %units/files/rebol-private-no-pass.key]
131-
; cleanup:
132+
rsa private-key none
133+
--test-- "RSA private key from OpenSSL x509 format (PRIVATE KEY)"
134+
; openssl req -new -newkey rsa:4096 -x509 -sha256 -days 365 -nodes -out MyCertificate.crt -keyout MyKey.key
135+
--assert handle? try [private-key: load %units/files/MyKey.key]
132136
rsa private-key none
133137
===end-group===
134138

0 commit comments

Comments
 (0)