1OpenSSL extension for PHP
2
3$Id$
4
5The functions implemented so far make it possible to seal and open data, and
6also create and verify signatures.
7
8NEW: support for S/MIME encrypt/decrypt/sign/verify, as well as more
9flexibility for specifying certificates/keys.
10
11To enable the extension, configure PHP with --with-openssl.
12
13Specifying keys/certificates
14----------------------------
15
16Most of the functions require a key or a certificate as a parameter; to make
17things easy for you to use openssl, this extension allows you
18to specify certificates in the following way:
19
201. As an X.509 resource returned from openssl_x509_read
212. As a string in the format file://filename, where filename is the path to the
22 certificate file (it will be opened and read automatically)
233. As a string containing the data from the certificate file
24
25Similarly, you can use the following methods of specifying a public key:
26
271. As a key resource returned from openssl_get_publickey
282. An X509 resource - public key only
293. As a string in the format file://filename
304. As a string containing the data from the key file
31
32Additionally, for a private key, when the openssl extension function does not
33allow you to enter the passphrase as a parameter you may use the syntax
34array($key, "passphrase") where $key can be a key specified using one of the
35methods listed above.
36
37Certificate Verification
38------------------------
39When calling a function that will verify a signature/certificate, the cainfo
40parameter is an array containing file and directory names that specifiy the
41locations of trusted CA files. If a directory is specified, then it must be a
42correctly hashed directory.
43
44Misc:
45-----
46
47mixed openssl_error_string()
48
49returns the message from the last error that the OpenSSL library encountered
50and moves it's internal error pointer to the next message. If there are no
51more error messages, returns false.
52
53General Key/Cert Functions:
54---------------------------
55
56resource openssl_get_privatekey(mixed key [, string passphrase])
57
58Parses the key data and returns a key resource identifier. If the key is
59encrypted a passphrase is needed. This can be supplied as second argument.
60
61
62resource openssl_get_publickey(mixed cert)
63
64Extracts the public key from the given certificate or public key and returns
65a key resource identifier.
66
67
68void openssl_free_key(resource key)
69
70Frees the resource given by the key resource identifier.
71Note that this function does not accept the extended key specification
72syntax mentioned above, as it doesn't make sense in this case!
73
74array openssl_x509_parse(mixed x509[, bool shortnames=true])
75
76Parses the certificate data and returns an array containing information
77about the certificate, it's intended purposes, subject, issuer, validity
78etc. etc. If shortnames is true (the default) then the fields will be
79keyed by the shortname forms eg: CN as opposed to commonName (shortnames
80= false).
81
82
83bool openssl_x509_checkpurpose(mixed x509cert, int purpose,
84 array cainfo[, string untrustedfile])
85
86Verifies if the certificate can be used for a specific purpose.
87Purpose can be one of the following values:
88 X509_PURPOSE_SSL_CLIENT
89 X509_PURPOSE_SSL_SERVER
90 X509_PURPOSE_NS_SSL_SERVER
91 X509_PURPOSE_SMIME_SIGN
92 X509_PURPOSE_SMIME_ENCRYPT
93 X509_PURPOSE_CRL_SIGN
94 X509_PURPOSE_ANY
95
96cainfo is an array of CA information (as mentioned above).
97untrusted file specifies a file containing a bunch of certs that
98are not trusted but may be useful in validating the certificate.
99
100
101resource openssl_read_x509(mixed cert)
102
103Parses the cert and returns a resource that can be used with the
104other openssl functions
105
106
107void openssl_free_x509(resource x509)
108
109Frees the resource given by the x509 resource identifier.
110Note that this function does not accept the extended cert specification
111syntax mentioned above, as it doesn't make sense in this case!
112
113
114PKCS7 (S/MIME) Sign/Verify/Encrypt/Decrypt Functions:
115-----------------------------------------------------
116
117These functions allow you to manipulate S/MIME messages!
118
119They are based on apps/smime.c from the openssl dist, so for information,
120see the documentation for openssl.
121
122You may pass in some flags that affect how these functions work using
123and array containing the following values:
124"detached", "nodetached", "text", "nointern", "noverify", "nochain",
125"nocerts", "noattr", "binary", "nosigs".
126The options correspond to the options of the same name for the
127"openssl smime" command (smime(1)).
128
129
130bool openssl_pkcs7_verify(string filename, array flags[, string signerscerts][,
131 array cainfo])
132
133Verifies that the signature on the MIME message contained in the file
134named by filename is valid. If signerscerts is passed in, it holds the
135name of a file into which the certificates of those that signed the
136message will be stored.
137cainfo and flags are CA information and flag information as described
138above.
139
140
141bool openssl_pkcs7_encrypt(string infile, string outfile, array recipcerts,
142 array headers[, array flags])
143
144Encrypts the MIME message contained in the file named by infile using
145the certificates held in recipcerts. The result is place in the file
146named outfile.
147recipcerts is an array of certificate identifiers representing the certs
148of the intended recipients of the message.
149headers is an array of headers to prepend to the message: they will
150not be included in the encoded section.
151flags is flag information as described above.
152Hint: you will want to put "To", "From", and "Subject" headers in headers.
153Headers can be either an assoc array keyed by header named, or can be
154and indexed array containing a single header line per value.
155The message will be encoded using a RC2-40 bit cipher.
156TODO: allow user to specify cipher.
157
158bool openssl_pkcs7_sign(string infile, string outfile, mixed signcert, mixed
159 signkey, array headers[, array flags][, string extracertsfilename])
160
161Signs the MIME message contained in the file named by infile using the
162certificate and key pair identified by signcert/signkey.
163Signkey must be the private key corresponding to signcert.
164The result is placed in the file named by outfile.
165Headers and flags have the same effects as mentioned above.
166extracertsfilename names a file containing a bunch of additional certificates
167to include in the signature, in order to aid the recipient in verifying the
168message.
169
170
171bool openssl_pkcs7_decrypt(string infilename, string outfilename, mixed
172 recipcert, mixed recipkey)
173
174Decrypts the MIME message contained in the file named by infilename
175using the certificate and private key pair recipcert/recipkey.
176The descrypted result is placed in outfilename.
177TODO: add flags parameter, if needed?
178
179
180EVP Sign/Verify/Encrypt/Decrypt Functions:
181------------------------------------------
182
183bool openssl_sign(string data, &string signature, mixed key)
184
185Uses key to create signature for data, returns true on success and false
186on failure. signature is passed by reference and contains the newly created
187signature on success.
188
189
190int openssl_verify(string data, string signature, mixed key)
191
192Uses key to verify that the signature is correct for the given data.
193Returns 1 if correct, 0 if incorrect, and -1 on error.
194
195
196int openssl_seal(string data, &string sealdata, &array ekeys, array pubkeys)
197
198Encrypts data using pubkeys, so that only owners of the respective private
199keys and ekeys can decrypt and read the data. Returns the length of the
200sealed data on success, else false. On success, sealdata and ekeys hold
201the sealed data and envelope keys.
202
203
204bool openssl_open(string data, &string opendata, string ekey, int privkey)
205
206Opens (decrypts) sealed data using a private key and the corresponding
207envelope key. Returns true on success and false on failure. On success,
208opendata will hold the descypted data.
209
210
211See below for more details on usage. Also feel free to mail me at
212venaas@php.net if you have questions. The OpenSSL documentation,
213especially the EVP documentation at
214http://www.openssl.org/docs/crypto/evp.html, might also be of help.
215
216
217HOWTO:
218
219To do anything you need a private key and a certificate containing the
220corresponding public key. This is similar to what you have using say an
221Apache webserver with OpenSSL. For testing you could try keys that come
222with OpenSSL, that's what the sample scripts below do. You can also get
223keys from some CA, or you can create them yourself.
224
225
226Creating private key
227
228To generate an unprotected 1024 bit RSA private key you can do
229
230 openssl genrsa -out /tmp/test.key 1024
231
232Private keys should be protected by a passphrase though.
233
234
235Creating a self signed certificate
236
237To generate a self signed certificate from the key that is valid for
238365 days, do
239
240 openssl req -new -key /tmp/test.key -out /tmp/test.crt -days 365 -x509
241
242
243Example usage
244
245These examples use keys that come with OpenSSL, you should perhaps test with
246those first.
247
248
249Seal and open
250
251 <?php
252 $data = "Follow the white rabbit";
253
254 // Get certificate into a string
255 // this file comes with OpenSSL 0.9.6
256 $fp = fopen("/src/openssl-0.9.6/demos/maurice/cert.pem", "r");
257 $cert = fread($fp, 8192);
258 fclose($fp);
259 // get public key from certificate
260 $pk1 = openssl_get_publickey($cert);
261 // $pk1 is an encryption key resource id if success, else false
262 // Repeat if want public keys for multiple parties
263
264 $fp = fopen("/src/openssl-0.9.6/demos/sign/cert.pem", "r");
265 $cert = fread($fp, 8192);
266 fclose($fp);
267 $pk2 = openssl_get_publickey($cert);
268
269 // seal data, only owners of $pk1 and $pk2 can decrypt $sealed with keys
270 // $ekeys[0] and $ekeys[1] respectively.
271 openssl_seal($data, $sealed, $ekeys, array($pk1,$pk2));
272 openssl_free_key($pk1);
273 openssl_free_key($pk2);
274
275 // now we try to decrypt data for one of the recipients
276 $fp = fopen("/src/openssl-0.9.6/demos/sign/key.pem", "r");
277 // Get PEM coded key into $pkey
278 $pkey = fread($fp, 8192);
279 fclose($fp);
280 // $key will be resource id for unpacked $pkey
281 $key = openssl_get_privatekey($pkey);
282
283 openssl_open($sealed, $open, $ekeys[1], $key);
284 openssl_free_key($key);
285 echo "$open\n";
286 ?>
287
288
289Sign and verify
290
291 <?php
292 $data = "Follow the white rabbit";
293
294 // First we need to have a string containing the private key in PEM format
295 // this file comes with OpenSSL 0.9.6
296 $fp = fopen("/src/openssl-0.9.6/demos/sign/key.pem", "r");
297 $pkey = fread($fp, 8192);
298 fclose($fp);
299
300 // get private key from the PEM format
301 // $key is an encr key resource id if success, else false
302 $key = openssl_get_privatekey($pkey);
303
304 // calculate signature
305 openssl_sign($data, $signature, $key);
306 openssl_free_key($key);
307
308 // recipient verifies signature
309 // read certificate
310 $fp = fopen("/src/openssl-0.9.6/demos/sign/cert.pem", "r");
311 $cert = fread($fp, 8192);
312 fclose($fp);
313
314 // Get public key from the certificate
315 $pubkey = openssl_get_publickey($cert);
316
317 // state whether signature is okay or not
318 echo openssl_verify($data, $signature, $pubkey) == 1 ? "ok\n" : "bad\n";
319
320 // free key
321 openssl_free_key($pubkey);
322 ?>
323