1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
|
.TH RSA 3
.SH NAME
asn1dump,
asn1toRSApriv,
decodepem,
decodepemchain,
rsadecrypt,
rsaencrypt,
rsafill,,
rsagen,
rsaprivalloc,
rsaprivfree,
rsaprivtopub,
rsapuballoc,
rsapubfree,
X509toRSApub,
X509dump,
X509gen,
X509req,
X509verify \- RSA encryption algorithm
.SH SYNOPSIS
.B #include <u.h>
.br
.B #include <libc.h>
.br
.B #include <mp.h>
.br
.B #include <libsec.h>
.PP
.B
.ta +\w'\fLPEMChain* 'u
RSApriv* rsagen(int nlen, int elen, int nrep)
.PP
.B
RSApriv* rsafill(mpint *n, mpint *ek, mpint *dk, mpint *p, mpint *q)
.PP
.B
mpint* rsaencrypt(RSApub *k, mpint *in, mpint *out)
.PP
.B
mpint* rsadecrypt(RSApriv *k, mpint *in, mpint *out)
.PP
.B
RSApub* rsapuballoc(void)
.PP
.B
void rsapubfree(RSApub*)
.PP
.B
RSApriv* rsaprivalloc(void)
.PP
.B
void rsaprivfree(RSApriv*)
.PP
.B
RSApub* rsaprivtopub(RSApriv*)
.PP
.B
RSApub* X509toRSApub(uchar *cert, int ncert, char *name, int nname)
.PP
.B
RSApriv* asn1toRSApriv(uchar *priv, int npriv)
.PP
.B
void asn1dump(uchar *der, int len)
.PP
.B
uchar* decodepem(char *s, char *type, int *len)
.PP
.B
PEMChain* decodepemchain(char *s, char *type)
.PP
.B
void X509dump(uchar *cert, int ncert)
.PP
.B
uchar* X509gen(RSApriv *priv, char *subj, ulong valid[2], int *certlen);
.PP
.B
uchar* X509req(RSApriv *priv, char *subj, int *certlen);
.PP
.B
char* X509verify(uchar *cert, int ncert, RSApub *pk)
.SH DESCRIPTION
.PP
RSA is a public key encryption algorithm. The owner of a key publishes
the public part of the key:
.EX
struct RSApub
{
mpint *n; // modulus
mpint *ek; // exp (encryption key)
};
.EE
This part can be used for encrypting data (with
.IR rsaencrypt )
to be sent to the owner.
The owner decrypts (with
.IR rsadecrypt )
using his private key:
.EX
struct RSApriv
{
RSApub pub;
mpint *dk; // exp (decryption key)
// precomputed crt values
mpint *p;
mpint *q;
mpint *kp; // k mod p-1
mpint *kq; // k mod q-1
mpint *c2; // for converting residues to number
};
.EE
.PP
Keys are generated using
.IR rsagen .
.I Rsagen
takes both bit length of the modulus, the bit length of the
public key exponent, and the number of repetitions of the Miller-Rabin
primality test to run. If the latter is 0, it does the default number
of rounds.
.I Rsagen
returns a newly allocated structure containing both
public and private keys.
.I Rsaprivtopub
returns a newly allocated copy of the public key
corresponding to the private key.
.PP
.I Rsafill
takes as input the bare minimum pieces of an RSA private key
and computes the rest
.RB ( kp ,
.BR kq ,
and
.BR c2 ).
It returns a new private key.
All the
.BR mpint s
in the key,
even the ones that correspond directly to
.IR rsafill 's
input parameters,
are freshly allocated,
.PP
The routines
.IR rsaalloc ,
.IR rsafree ,
.IR rsapuballoc ,
.IR rsapubfree ,
.IR rsaprivalloc ,
and
.I rsaprivfree
are provided to aid in user provided key I/O.
.PP
Given a binary X.509
.IR cert ,
the routine
.I X509toRSApub
returns the public key and, if
.I name
is not nil, the CN part of the Distinguished Name of the
certificate's Subject.
(This is conventionally a userid or a host DNS name.)
No verification is done of the certificate signature; the
caller should check the fingerprint,
.IR sha1(cert) ,
against a table or check the certificate by other means.
X.509 certificates are often stored in PEM format; use
.I dec64
to convert to binary before computing the fingerprint or calling
.IR X509toRSApub .
For the special case of
certificates signed by a known trusted key
(in a single step, without certificate chains)
.I X509verify
checks the signature on
.IR cert .
It returns nil if successful, else an error string.
.PP
.I X509dump
prints an X.509 certificate to standard ouptut.
.PP
.I X509gen
creates a self-signed X.509 certificate, given an RSA keypair
.IR priv ,
a issuer/subject string
.IR subj ,
and the starting and ending validity dates,
.IR valid .
Length of the allocated binary certificate is stored in
.IR certlen .
The subject line is conventionally of the form
.EX
"C=US ST=NJ L=07922 O=Lucent OU='Bell Labs' CN=Eric"
.EE
using the quoting conventions of
.I tokenize
(see
.IR getfields (3)).
.PP
.I X509req
creates an X.509 certification request.
.PP
.I Asn1toRSApriv
converts an ASN1 formatted RSA private key into the corresponding
.B RSApriv
structure.
.PP
.I Asn1dump
prints an ASN1 object to standard output.
.PP
.I Decodepem
takes a zero terminated string,
.IR s ,
and decodes the PEM (privacy-enhanced mail) formatted section for
.I type
within it.
If successful, it returns the decoded section and sets
.BI * len
to its decoded length.
If not, it returns
.BR nil ,
and
.BI * len
is undefined.
.PP
.I Decodepemchain
is similar but expects a sequence of PEM-formatted sections
and returns a linked list of the decodings:
.IP
.EX
typedef struct PEMChain PEMChain
struct PEMChain
{
PEMChain *next;
uchar *pem;
int pemlen;
};
.EE
.SH SOURCE
.B /usr/local/plan9/src/libsec
.SH SEE ALSO
.IR mp (3),
.IR aes (3),
.IR blowfish (3),
.IR des (3),
.IR dsa (3),
.IR elgamal (3),
.IR rc4 (3),
.IR sechash (3),
.IR prime (3),
.IR rand (3)
.\" .IR pem (8)
|