android_tools/java_tools/keytool.rs
1use crate::error::*;
2use std::path::{Path, PathBuf};
3use std::process::Command;
4
5/// ## Description
6/// Keytool is a key and certificate management utility. It allows users to
7/// administer their own public/private key pairs and associated certificates
8/// for use in self-authentication (where the user authenticates himself/herself
9/// to other users/services) or data integrity and authentication services,
10/// using digital signatures. It also allows users to cache the public keys
11/// (in the form of certificates) of their communicating peers.
12///
13/// A certificate is a digitally signed statement from one entity (person, company, etc.),
14/// saying that the public key (and some other information) of some other entity has a
15/// particular value. (See Certificates.) When data is digitally signed, the signature
16/// can be verified to check the data integrity and authenticity. Integrity means that
17/// the data has not been modified or tampered with, and authenticity means the data
18/// indeed comes from whoever claims to have created and signed it.
19///
20/// keytool also enables users to administer secret keys used in symmetric
21/// encryption/decryption (e.g. DES).
22///
23/// keytool stores the keys and certificates in a [`keystore`].
24///
25/// Contents options that can help to manage keystore of cryptographic keys
26///
27/// [keystore]::(https://docs.oracle.com/javase/7/docs/technotes/tools/windows/keytool.html#KeyStore)
28#[derive(Clone, Default)]
29pub struct Keytool {
30 v: bool,
31 keystore: Option<PathBuf>,
32 alias: Option<String>,
33 keypass: Option<String>,
34 storepass: Option<String>,
35 dname: Option<Vec<String>>,
36 storetype: Option<StoreType>,
37 providername: Option<String>,
38 providerclass: Option<String>,
39 providerarg: Option<PathBuf>,
40 protected: bool,
41 ext: Option<String>,
42 keysize: Option<u32>,
43 validity: Option<u32>,
44 gencert: bool,
45 genkeypair: bool,
46 genseckey: bool,
47 mportcert: bool,
48 importpass: bool,
49 importkeystore: bool,
50 printcertreq: bool,
51 certreq: bool,
52 exportcert: bool,
53 list: bool,
54 printcert: bool,
55 printcrl: bool,
56 storepasswd: bool,
57 keypasswd: bool,
58 delete: bool,
59 changealias: bool,
60 help: bool,
61 keyalg: Option<KeyAlgorithm>,
62 file: Option<PathBuf>,
63 rfc: bool,
64 jarfile: Option<PathBuf>,
65 new_arg: Option<String>,
66 sslserver: Option<String>,
67 providerpath: Option<Vec<PathBuf>>,
68 destalias: Option<String>,
69}
70
71impl Keytool {
72 pub fn new() -> Self {
73 Self {
74 ..Default::default()
75 }
76 }
77
78 /// The keystore location.
79 ///
80 /// If the JKS [`storetype`] is used and a keystore file does not yet exist, then certain
81 /// keytool commands may result in a new keystore file being created. For example, if
82 /// keytool -genkeypair is invoked and the -keystore option is not specified, the
83 /// default keystore file named .keystore in the user's home directory will be created
84 /// if it does not already exist. Similarly, if the -keystore ks_file option is
85 /// specified but ks_file does not exist, then it will be created.
86 ///
87 /// Note that the input stream from the -keystore option is passed to the `KeyStore.load`
88 /// method. If `NONE` is specified as the URL, then a null stream is passed to the
89 /// `KeyStore.load` method. NONE should be specified if the `KeyStore` is not file-based
90 /// (for example, if it resides on a hardware token device).
91 ///
92 /// [storetype](https://docs.oracle.com/javase/7/docs/technotes/tools/windows/keytool.html#KeyStoreImplementation)
93 pub fn keystore(&mut self, keystore: &Path) -> &mut Self {
94 self.keystore = Some(keystore.to_owned());
95 self
96 }
97
98 /// Alias name of the entry to process
99 pub fn alias(&mut self, alias: &str) -> &mut Self {
100 self.alias = Some(alias.to_string());
101 self
102 }
103
104 /// Key password
105 pub fn keypass(&mut self, keypass: &str) -> &mut Self {
106 self.keypass = Some(keypass.to_string());
107 self
108 }
109
110 /// The password that is used to protect the integrity of the keystore.
111 ///
112 /// If the modifier env or file is not specified, then the password has the value argument,
113 /// which must be at least 6 characters long. Otherwise, the password is retrieved as
114 /// follows:
115 ///
116 /// * `env:` Retrieve the password from the environment variable named argument.
117 /// * `file:` Retrieve the password from the file named argument.
118 ///
119 /// ## Note
120 /// All other options that require passwords, such as -keypass, -srckeypass, -destkeypass,
121 /// -srcstorepass, and -deststorepass, accept the env and file modifiers. Remember to
122 /// separate the password option and the modifier with a colon (:).
123 ///
124 /// The password must be provided to all commands that access the keystore contents. For
125 /// such commands, when the -storepass option is not provided at the command line, the user
126 /// is prompted for it.
127 ///
128 /// When retrieving information from the keystore, the password is optional. If no password
129 /// is specified, then the integrity of the retrieved information cannot be verified and a
130 /// warning is displayed.
131 pub fn storepass(&mut self, storepass: &str) -> &mut Self {
132 self.storepass = Some(storepass.to_string());
133 self
134 }
135
136 /// Key algorithm name
137 pub fn keyalg(&mut self, keyalg: KeyAlgorithm) -> &mut Self {
138 self.keyalg = Some(keyalg);
139 self
140 }
141
142 /// Distinguished name
143 pub fn dname(&mut self, dname: &[String]) -> &mut Self {
144 self.dname = Some(dname.to_vec());
145 self
146 }
147
148 /// This qualifier specifies the type of keystore to be instantiated.
149 pub fn storetype(&mut self, storetype: StoreType) -> &mut Self {
150 self.storetype = Some(storetype);
151 self
152 }
153
154 /// Used to identify a cryptographic service provider's name when listed in the security
155 /// properties file.
156 pub fn providername(&mut self, providername: String) -> &mut Self {
157 self.providername = Some(providername);
158 self
159 }
160
161 /// Used to specify the name of a cryptographic service provider's master class file when
162 /// the service provider is not listed in the security properties file.
163 pub fn providerclass(&mut self, providerclass: String) -> &mut Self {
164 self.providerclass = Some(providerclass);
165 self
166 }
167
168 /// Used with the -providerclass option to represent an optional string input argument
169 /// for the constructor of provider_class_name.
170 pub fn providerarg(&mut self, providerarg: &Path) -> &mut Self {
171 self.providerarg = Some(providerarg.to_owned());
172 self
173 }
174
175 /// Either true or false. This value should be specified as true when a password must be
176 /// specified by way of a protected authentication path such as a dedicated PIN
177 /// reader.Because there are two keystores involved in the -importkeystore command, the
178 /// following two options -srcprotected and -destprotected are provided for the source
179 /// keystore and the destination keystore respectively.
180 pub fn protected(&mut self, protected: bool) -> &mut Self {
181 self.protected = protected;
182 self
183 }
184
185 /// Denotes an X.509 certificate extension. The option can be used in -genkeypair and
186 /// -gencert to embed extensions into the certificate generated, or in -certreq to show
187 /// what extensions are requested in the certificate request. The option can appear
188 /// multiple times. The name argument can be a supported extension name
189 /// (see Named Extensions) or an arbitrary OID number. The value argument, when
190 /// provided, denotes the argument for the extension. When value is omitted, that means
191 /// that the default value of the extension or the extension requires no argument.
192 /// The :critical modifier, when provided, means the extension's isCritical attribute
193 /// is true; otherwise, it is false. You can use :c in place of :critical.
194 pub fn ext(&mut self, ext: String) -> &mut Self {
195 self.ext = Some(ext);
196 self
197 }
198
199 /// Key bit size
200 pub fn keysize(&mut self, keysize: u32) -> &mut Self {
201 self.keysize = Some(keysize);
202 self
203 }
204
205 /// Validity number of days
206 pub fn validity(&mut self, validity: u32) -> &mut Self {
207 self.validity = Some(validity);
208 self
209 }
210
211 /// * {-rfc}: Output in RFC (Request For Comment) style
212 /// * {-infile infile}: Input file name
213 /// * {-outfile outfile}: Output file name
214 /// * {-alias alias}: Alias name of the entry to process
215 /// * {-sigalg sigalg}: Signature algorithm name
216 /// * {-dname dname}: Distinguished name
217 /// * {-startdate startdate}: Certificate validity start date and time
218 /// * {-ext ext}*: X.509 extension
219 /// * {-validity days}: Validity number of days
220 /// * [-keypass arg]: Key password
221 /// * {-keystore keystore}: Keystore name
222 /// * [-storepass arg]: Keystore password
223 /// * {-storetype type}: Keystore type
224 /// * {-providername name}: Provider name
225 /// * {-providerclass class [-providerarg arg]}: Add security provider by fully qualified class
226 /// name with an optional configure argument. For example, if MyProvider is a legacy provider
227 /// loaded via reflection,
228 ///
229 /// ```sh
230 /// keytool -providerclass com.example.MyProvider ...
231 /// ```
232 ///
233 /// * {-providerpath list}: Provider classpath
234 /// * {-v}: Verbose output
235 /// * {-protected}: Password provided through a protected mechanism
236 ///
237 /// Generates a certificate as a response to a certificate request file (which can be created by
238 /// the keytool `-certreq` command). The command reads the request from infile (if omitted, from
239 /// the standard input), signs it using alias's private key, and outputs the X.509 certificate
240 /// into outfile (if omitted, to the standard output). When-rfc is specified, the output format
241 /// is Base64-encoded PEM; otherwise, a binary DER is created.
242 ///
243 /// The sigalg value specifies the algorithm that should be used to sign the certificate. The
244 /// startdate argument is the start time and date that the certificate is valid. The valDays
245 /// argument tells the number of days for which the certificate should be considered valid.
246 ///
247 /// When dname is provided, it is used as the subject of the generated certificate. Otherwise,
248 /// the one from the certificate request is used.
249 ///
250 /// The ext value shows what X.509 extensions will be embedded in the certificate. Read Common
251 /// Options for the grammar of `-ext`.
252 ///
253 /// The `-gencert` option enables you to create certificate chains. The following example creates
254 /// a certificate, e1, that contains three certificates in its certificate chain.
255 pub fn gencert(&mut self, gencert: bool) -> &mut Self {
256 self.gencert = gencert;
257 self
258 }
259
260 /// * {-alias alias}: Alias name of the entry to process
261 /// * {-keyalg alg}: Key algorithm name
262 /// * {-keysize size}: Key bit size
263 /// * {-groupname name}: Group name. For example, an Elliptic Curve name
264 /// * {-sigalg alg}: Signature algorithm name
265 /// * -destalias alias: Destination alias
266 /// * [-dname name]: Distinguished name
267 /// * {-startdate date}: Certificate validity start date and time
268 /// * [-ext value]*: X.509 extension
269 /// * {-validity days}: Validity number of days
270 /// * [-keypass arg]: Key password
271 /// * {-keystore keystore}: Keystore name
272 /// * [-storepass arg]: Keystore password
273 /// * {-storetype type}: Keystore type
274 /// * {-providername name}: Provider name
275 /// * {-providerclass class [-providerarg arg]}: Add security provider by fully
276 /// qualified class name with an optional configure argument.
277 /// * {-providerpath list}: Provider classpath
278 /// * {-v}: Verbose output
279 /// * {-protected}: Password provided through a protected mechanism
280 ///
281 /// Generates a key pair (a public key and associated private key). Wraps the public key
282 /// into an X.509 v3 self-signed certificate, which is stored as a single-element
283 /// certificate chain. This certificate chain and the private key are stored in a new
284 /// keystore entry identified by alias.
285 ///
286 /// The keyalg value specifies the algorithm to be used to generate the key pair, and
287 /// the keysize value specifies the size of each key to be generated. The sigalg value
288 /// specifies the algorithm that should be used to sign the self-signed certificate.
289 /// This algorithm must be compatible with the keyalg value.
290 ///
291 /// The groupname value specifies a named group when generating a key pair. The groupname
292 /// option is preferred over the keysize option because there may be more than one curve
293 /// of the same size. For example:
294 ///
295 /// ```sh
296 /// keytool -genkeypair -keyalg EC -groupname secp384r1
297 /// ```
298 ///
299 /// The dname value specifies the X.500 Distinguished Name to be associated with the value
300 /// of alias, and is used as the issuer and subject fields in the self-signed certificate.
301 /// If no distinguished name is provided at the command line, then the user is prompted
302 /// for one.
303 ///
304 /// The value of keypass is a password used to protect the private key of the generated key
305 /// pair. If no password is provided, then the user is prompted for it. If you press the
306 /// Return key at the prompt, then the key password is set to the same password as the
307 /// keystore password. The keypass value must be at least 6 characters.
308 ///
309 /// The value of startdate specifies the issue time of the certificate, also known as the
310 /// "Not Before" value of the X.509 certificate's Validity field.
311 ///
312 /// The option value can be set in one of these two forms:
313 ///
314 /// ```sh
315 /// ([+-]nnn[ymdHMS])+
316 /// [yyyy/mm/dd] [HH:MM:SS]
317 /// ```
318 ///
319 /// When the option is not provided, the start date is the current time. The option can be
320 /// provided at most once.
321 ///
322 /// The value of valDays specifies the number of days (starting at the date specified by
323 /// `-startdate`, or the current date when `-startdate` is not specified) for which the
324 /// certificate should be considered valid.
325 ///
326 /// This command was named -genkey in earlier releases. The old name is still supported in
327 /// this release. The new name, -genkeypair, is preferred going forward.
328 pub fn genkeypair(&mut self, genkeypair: bool) -> &mut Self {
329 self.genkeypair = genkeypair;
330 self
331 }
332
333 /// * {-alias alias}: Alias name of the entry to process
334 /// * [-keypass arg] : Key password
335 /// * {-keyalg alg}: Key algorithm name
336 /// * {-keysize size}: Key bit size
337 /// * {-keystore keystore}: Keystore name
338 /// * [-storepass arg]: Keystore password
339 /// * {-storetype type}: Keystore type
340 /// * {-providername name}: Provider name
341 /// * {-providerclass class [providerarg arg]}: Add security provider by fully qualified
342 /// class name with an optional configure argument.
343 /// * {-providerpath list}: Provider classpath
344 /// * {-v}: Verbose output
345 /// * {-protected}: Password provided through a protected mechanism
346 ///
347 /// Generates a secret key and stores it in a new KeyStore.SecretKeyEntry identified by
348 /// alias.
349 ///
350 /// The value of keyalg specifies the algorithm to be used to generate the secret key,
351 /// and the value of keysize specifies the size of the key to be generated. The keypass
352 /// value is a password that protects the secret key. If no password is provided, then
353 /// the user is prompted for it. If you press the Return key at the prompt, then the key
354 /// password is set to the same password that is used for the keystore. The keypass value
355 /// must be at least 6 characters.
356 pub fn genseckey(&mut self, genseckey: bool) -> &mut Self {
357 self.genseckey = genseckey;
358 self
359 }
360
361 /// * {-noprompt}: Do not prompt
362 /// * {-trustcacerts}: Trust certificates from cacerts
363 /// * {-protected}: Password is provided through protected mechanism
364 /// * {-alias alias}: Alias name of the entry to process
365 /// * {-file file}: Input file name
366 /// * [-keypass arg]: Key password
367 /// * {-keystore keystore}: Keystore name
368 /// * [-storepass arg]: Keystore password
369 /// * {-storetype type}: Keystore type
370 /// * {-providername name}: Provider name
371 /// * {-providerclass class [-providerarg arg]}: Add security provider by fully qualified
372 /// class name with an optional configure argument.
373 /// * {-providerpath list}: Provider classpath
374 /// * {-v}: Verbose output
375 ///
376 /// Reads the certificate or certificate chain (where the latter is supplied in a PKCS#7
377 /// formatted reply or a sequence of X.509 certificates) from the file cert_file, and
378 /// stores it in the keystore entry identified by alias. If no file is specified, then
379 /// the certificate or certificate chain is read from stdin.
380 ///
381 /// You import a certificate for two reasons: To add it to the list of trusted certificates,
382 /// and to import a certificate reply received from a certificate authority (CA) as the
383 /// result of submitting a Certificate Signing Request to that CA
384 /// (see the -certreq option in Commands).
385 ///
386 /// Which type of import is intended is indicated by the value of the -alias option. If the
387 /// alias does not point to a key entry, then the keytool command assumes you are adding a
388 /// trusted certificate entry. In this case, the alias should not already exist in the
389 /// keystore. If the alias does already exist, then the keytool command outputs an error
390 /// because there is already a trusted certificate for that alias, and does not import the
391 /// certificate. If the alias points to a key entry, then the keytool command assumes you
392 /// are importing a certificate reply.
393 pub fn importcert(&mut self, mportcert: bool) -> &mut Self {
394 self.mportcert = mportcert;
395 self
396 }
397
398 /// * {-alias alias}: Alias name of the entry to process
399 /// * [-keypass arg]: Key password
400 /// * {-keyalg alg}: Key algorithm name
401 /// * {-keysize size}: Key bit size
402 /// * {-keystore keystore}: Keystore name
403 /// * [-storepass arg]: Keystore password
404 /// * {-storetype type}: Keystore type
405 /// * {-providername name}: Provider name
406 /// * {-providerclass class [-providerarg arg]}: Add security provider by fully qualified
407 /// class name with an optional configure argument.
408 /// * {-providerpath list}: Provider classpath
409 /// * {-v}: Verbose output
410 /// * {-protected}: Password provided through a protected mechanism
411 ///
412 /// Imports a passphrase and stores it in a new KeyStore.SecretKeyEntry identified by alias.
413 /// The passphrase may be supplied via the standard input stream; otherwise the user is
414 /// prompted for it. keypass is a password used to protect the imported passphrase. If no
415 /// password is provided, the user is prompted for it. If you press the Return key at the
416 /// prompt, the key password is set to the same password as that used for the keystore.
417 /// keypass must be at least 6 characters long.
418 pub fn importpass(&mut self, importpass: bool) -> &mut Self {
419 self.importpass = importpass;
420 self
421 }
422
423 /// * {-srckeystore keystore}: Source keystore name
424 /// * {-destkeystore keystore}: Destination keystore name
425 /// * {-srcstoretype type}: Source keystore type
426 /// * {-deststoretype type}: Destination keystore type
427 /// * [-srcstorepass arg]: Source keystore password
428 /// * [-deststorepass arg]: Destination keystore password
429 /// * {-srcprotected Source keystore password protected
430 /// * {-srcprovidername name}: Source keystore provider name
431 /// * {-destprotected}: Destination keystore password protected
432 /// * {-destprovidername name}: Destination keystore provider name
433 /// * {-srcalias alias}: Source alias
434 /// * {-destalias alias}: Destination alias
435 /// * [-srckeypass arg]: Source key password
436 /// * [-destkeypass arg]: Destination key password
437 /// * {-noprompt}: Do not prompt
438 /// * {-providerclass class [-providerarg arg]}: Add security provider by fully qualified
439 /// class name with an optional configure argument
440 /// * {-providerpath list}: Provider classpath
441 /// * {-v}: Verbose output
442 ///
443 /// Imports a single entry or all entries from a source keystore to a destination keystore.
444 ///
445 /// When the `-srcalias` option is provided, the command imports the single entry identified
446 /// by the alias to the destination keystore. If a destination alias is not provided with
447 /// destalias, then srcalias is used as the destination alias. If the source entry is
448 /// protected by a password, then srckeypass is used to recover the entry. If srckeypass
449 /// is not provided, then the keytool command attempts to use srcstorepass to recover the
450 /// entry. If srcstorepass is either not provided or is incorrect, then the user is
451 /// prompted for a password. The destination entry is protected with destkeypass. If
452 /// destkeypass is not provided, then the destination entry is protected with the source
453 /// entry password. For example, most third-party tools require storepass and keypass in
454 /// a PKCS #12 keystore to be the same. In order to create a PKCS #12 keystore for these
455 /// tools, always specify a -destkeypass to be the same as -deststorepass.
456 ///
457 /// If the `-srcalias` option is not provided, then all entries in the source keystore are
458 /// imported into the destination keystore. Each destination entry is stored under the
459 /// alias from the source entry. If the source entry is protected by a password, then
460 /// srcstorepass is used to recover the entry. If srcstorepass is either not provided or
461 /// is incorrect, then the user is prompted for a password. If a source keystore entry
462 /// type is not supported in the destination keystore, or if an error occurs while storing
463 /// an entry into the destination keystore, then the user is prompted whether to skip the
464 /// entry and continue or to quit. The destination entry is protected with the source
465 /// entry password.
466 ///
467 /// If the destination alias already exists in the destination keystore, then the user is
468 /// prompted to either overwrite the entry or to create a new entry under a different
469 /// alias name.
470 ///
471 /// If the -noprompt option is provided, then the user is not prompted for a new destination
472 /// alias. Existing entries are overwritten with the destination alias name. Entries that
473 /// cannot be imported are skipped and a warning is displayed.
474 pub fn importkeystore(&mut self, importkeystore: bool) -> &mut Self {
475 self.importkeystore = importkeystore;
476 self
477 }
478
479 /// * {-file file}: Input file name
480 /// * {-v}: Verbose output
481 ///
482 /// Prints the content of a PKCS #10 format certificate request, which can be generated by
483 /// the keytool -certreq command. The command reads the request from file. If there is no
484 /// file, then the request is read from the standard input.Prints the content of a PKCS #10
485 /// format certificate request, which can be generated by the keytool -certreq command. The
486 /// command reads the request from file. If there is no file, then the request is read from
487 /// the standard input.
488 pub fn printcertreq(&mut self, printcertreq: bool) -> &mut Self {
489 self.printcertreq = printcertreq;
490 self
491 }
492
493 /// * {-alias alias}: Alias name of the entry to process
494 /// * {-sigalg alg}: Signature algorithm name
495 /// * {-file file}: Output file name
496 /// * [-keypass arg]: Key password
497 /// * {-keystore keystore}: Keystore name
498 /// * {-dname name}: Distinguished name
499 /// * [-storepass arg]: Keystore password
500 /// * {-storetype type}: Keystore type
501 /// * {-providername name}: Provider name
502 /// * {-providerclass class [-providerarg arg]}: Add security provider by fully qualified
503 /// class name with an optional configure argument.
504 /// * {-providerpath list}: Provider classpath
505 /// * {-v}: Verbose output
506 /// * {-protected }: Password provided through a protected mechanism
507 ///
508 /// Generates a Certificate Signing Request (CSR) using the PKCS #10 format.
509 ///
510 /// A CSR is intended to be sent to a certificate authority (CA). The CA authenticates the
511 /// certificate requestor (usually off-line) and will return a certificate or certificate
512 /// chain, used to replace the existing certificate chain (which initially consists of a
513 /// self-signed certificate) in the keystore.
514 ///
515 /// The private key associated with alias is used to create the PKCS #10 certificate request.
516 /// To access the private key, the correct password must be provided. If keypass is not
517 /// provided at the command line and is different from the password used to protect the
518 /// integrity of the keystore, then the user is prompted for it. If dname is provided, then
519 /// it is used as the subject in the CSR. Otherwise, the X.500 Distinguished Name associated
520 /// with alias is used.
521 ///
522 /// The sigalg value specifies the algorithm that should be used to sign the CSR.
523 ///
524 /// The CSR is stored in the file certreq_file. If no file is specified, then the CSR is
525 /// output to stdout.
526 ///
527 /// Use the importcert command to import the response from the CA.
528 pub fn certreq(&mut self, certreq: bool) -> &mut Self {
529 self.certreq = certreq;
530 self
531 }
532
533 /// * {-rfc}: Output in RFC style
534 /// * {-alias alias}: Alias name of the entry to process
535 /// * {-file file}: Output file name
536 /// * {-keystore keystore}: Keystore name
537 /// * [-storepass arg]: Keystore password
538 /// * {-storetype type}: Keystore type
539 /// * {-providername name}: Provider name
540 /// * {-providerclass class [-providerarg arg]}: Add security provider by fully qualified
541 /// * class name with an optional configure argument.
542 /// * {-providerpath list}: Provider classpath
543 /// * {-v}: Verbose output
544 /// * {-protected}: Password provided through a protected mechanism
545 ///
546 /// Reads from the keystore the certificate associated with alias and stores it in the
547 /// cert_file file. When no file is specified, the certificate is output to stdout.
548 ///
549 /// The certificate is by default output in binary encoding. If the -rfc option is
550 /// specified, then the output in the printable encoding format defined by the [`Internet
551 /// RFC 1421 Certificate Encoding Standard`].
552 ///
553 /// If alias refers to a trusted certificate, then that certificate is output. Otherwise,
554 /// alias refers to a key entry with an associated certificate chain. In that case, the
555 /// first certificate in the chain is returned. This certificate authenticates the public
556 /// key of the entity addressed by alias.
557 ///
558 /// This command was named -export in earlier releases. The old name is still supported
559 /// in this release. The new name, -exportcert, is preferred going forward.
560 ///
561 /// [Internet RFC 1421 Certificate Encoding Standard]::(https://docs.oracle.com/javase/8/docs/technotes/tools/windows/keytool.html#CHDGGFEG)
562 pub fn exportcert(&mut self, exportcert: bool) -> &mut Self {
563 self.exportcert = exportcert;
564 self
565 }
566
567 /// * {-rfc}: Output in RFC style
568 /// * {-alias alias}: Alias name of the entry to process
569 /// * {-keystore keystore}: Keystore name
570 /// * [-storepass arg]: Keystore password
571 /// * {-storetype type}: Keystore type
572 /// * {-providername name}: Provider name
573 /// * {-providerclass class [-providerarg arg] }: Add security provider by fully qualified
574 /// class name with an optional configure argument.
575 /// * {-providerpath list}: Provider classpath
576 /// * {-v}: Verbose output
577 /// * {-protected}: Password provided through a protected mechanism
578 ///
579 /// Prints to stdout the contents of the keystore entry identified by alias. If no alias
580 /// is specified, then the contents of the entire keystore are printed.
581 ///
582 /// This command by default prints the SHA256 fingerprint of a certificate. If the `-v`
583 /// option is specified, then the certificate is printed in human-readable format, with
584 /// additional information such as the owner, issuer, serial number, and any extensions.
585 /// If the -rfc option is specified, then the certificate contents are printed using the
586 /// printable encoding format, as defined by the [`Internet RFC 1421 Certificate Encoding
587 /// Standard`].
588 ///
589 /// You cannot specify both `-v` and `-rfc`.
590 ///
591 /// [Internet RFC 1421 Certificate Encoding Standard]::(https://docs.oracle.com/javase/8/docs/technotes/tools/windows/keytool.html#CHDGGFEG)
592 pub fn list(&mut self, list: bool) -> &mut Self {
593 self.list = list;
594 self
595 }
596
597 /// * {-rfc}: Output in RFC style
598 /// * {-file cert_file}: Input file name
599 /// * {-sslserver server[:port]}: Secure Sockets Layer (SSL) server host and port
600 /// * {-jarfile JAR_file}: Signed .jar file
601 /// * {-v}: Verbose output
602 ///
603 /// Reads the certificate from the file cert_file, the SSL server located at host:port,
604 /// or the signed JAR file JAR_file (with the -jarfile option) and prints its contents
605 /// in a human-readable format. When no port is specified, the standard HTTPS port 443
606 /// is assumed. Note that -sslserver and -file options cannot be provided at the same
607 /// time. Otherwise, an error is reported. If neither option is specified, then the
608 /// certificate is read from stdin.
609 ///
610 /// When -rfc is specified, the keytool command prints the certificate in PEM mode as
611 /// defined by the Internet RFC 1421 Certificate Encoding standard. See [`Internet RFC
612 /// 1421 Certificate Encoding Standard`].
613 ///
614 /// If the certificate is read from a file or stdin, then it might be either binary
615 /// encoded or in printable encoding format, as defined by the RFC 1421 Certificate
616 /// Encoding standard.
617 ///
618 /// If the SSL server is behind a firewall, then the -J-Dhttps.proxyHost=proxyhost and
619 /// -J-Dhttps.proxyPort=proxyport options can be specified on the command line for proxy
620 /// tunneling. See Java Secure Socket Extension (JSSE) Reference Guide at
621 /// http://docs.oracle.com/javase/8/docs/technotes/guides/security/jsse/JSSERefGuide.html
622 ///
623 /// ## Note
624 /// This option can be used independently of a keystore.
625 ///
626 /// [Internet RFC 1421 Certificate Encoding Standard]::(https://docs.oracle.com/javase/8/docs/technotes/tools/windows/keytool.html#CHDGGFEG)
627 pub fn printcert(&mut self, printcert: bool) -> &mut Self {
628 self.printcert = printcert;
629 self
630 }
631
632 /// * -file crl: Input file name
633 /// * {-v}: Verbose output
634 ///
635 /// Reads the Certificate Revocation List (CRL) from the file crl. A CRL is a list of
636 /// digital certificates that were revoked by the CA that issued them. The CA
637 /// generates the crl file.
638 ///
639 /// ## Note
640 /// This option can be used independently of a keystore.
641 pub fn printcrl(&mut self, printcrl: bool) -> &mut Self {
642 self.printcrl = printcrl;
643 self
644 }
645
646 /// * [-new arg]: New password
647 /// * {-keystore keystore}: Keystore name
648 /// * [-storepass arg]: Keystore password
649 /// * {-storetype type}: Keystore type
650 /// * {-providername name}: Provider name
651 /// * {-providerclass class [-providerarg arg]}: Add security provider by fully
652 /// qualified class name with an optional configure argument.
653 /// * {-providerpath list}: Provider classpath
654 /// * {-v}: Verbose output]
655 ///
656 /// Changes the password used to protect the integrity of the keystore contents. The
657 /// new password is new_storepass, which must be at least 6 characters.
658 pub fn storepasswd(&mut self, storepasswd: bool) -> &mut Self {
659 self.storepasswd = storepasswd;
660 self
661 }
662
663 /// * {-alias alias}: Alias name of the entry to process
664 /// * {-keypass old_keypass}: Key password
665 /// * {-new new_keypass}: New password
666 /// * {-keystore keystore}: Keystore name
667 /// * {-storepass arg}: Keystore password
668 /// * {-storetype type}: Keystore type
669 /// * {-providername name}: Provider name
670 /// * {-providerclass class [-providerarg arg]}: Add security provider by fully
671 /// qualified class name with an optional configure argument.
672 /// * {-providerpath list}: Provider classpath
673 /// * {-v}: Verbose output
674 ///
675 /// Changes the password under which the private/secret key identified by alias
676 /// is protected, from old_keypass to new_keypass, which must be at least 6
677 /// characters.
678 ///
679 /// If the `-keypass` option is not provided at the command line, and the key password
680 /// is different from the keystore password, then the user is prompted for it.
681 ///
682 /// If the -new option is not provided at the command line, then the user is prompted
683 /// for it
684 pub fn keypasswd(&mut self, keypasswd: bool) -> &mut Self {
685 self.keypasswd = keypasswd;
686 self
687 }
688
689 /// * [-alias alias]: Alias name of the entry to process
690 /// * {-keystore keystore}: Keystore name
691 /// * [-storepass arg]: Keystore password
692 /// * {-storetype type}: Keystore type
693 /// * {-providername name}: Provider name
694 /// * {-providerclass class [-providerarg arg]}: Add security provider by fully qualified
695 /// class name with an optional configure argument.
696 /// * {-providerpath list}: Provider classpath
697 /// * {-v}: Verbose output
698 /// * {-protected}: Password provided through a protected mechanism
699 ///
700 /// Deletes from the keystore the entry identified by alias. The user is prompted for
701 /// the alias, when no alias is provided at the command line.
702 pub fn delete(&mut self, delete: bool) -> &mut Self {
703 self.delete = delete;
704 self
705 }
706
707 /// * {-alias alias}: Alias name of the entry to process
708 /// * [-destalias alias]: Destination alias
709 /// * [-keypass arg]: Key password
710 /// * {-keystore keystore}: Keystore name
711 /// * [-storepass arg]: Keystore password
712 /// * {-storetype type}: Keystore type
713 /// * {-providername name}: Provider name
714 /// * {-providerclass class [-providerarg arg]}: Add security provider by fully qualifie
715 /// class name with an optional configure argument.
716 /// * {-providerpath list}: Provider classpath
717 /// * {-v}: Verbose output
718 /// * {-protected}: Password provided through a protected mechanism
719 ///
720 /// Move an existing keystore entry from the specified alias to a new alias, destalias.
721 /// If no destination alias is provided, then the command prompts for one. If the original
722 /// entry is protected with an entry password, then the password can be supplied with the
723 /// -keypass option. If no key password is provided, then the storepass (if provided) is
724 /// attempted first. If the attempt fails, then the user is prompted for a password.
725 pub fn changealias(&mut self, changealias: bool) -> &mut Self {
726 self.changealias = changealias;
727 self
728 }
729
730 /// Lists the basic commands and their options.
731 ///
732 /// For more information about a specific command, enter the following, where command_name
733 /// is the name of the command: keytool `-command_name` `-help`.
734 pub fn help(&mut self, help: bool) -> &mut Self {
735 self.help = help;
736 self
737 }
738
739 /// Output file name
740 pub fn file(&mut self, file: &Path) -> &mut Self {
741 self.file = Some(file.to_owned());
742 self
743 }
744
745 /// Signed .jar file
746 pub fn jarfile(&mut self, jarfile: &Path) -> &mut Self {
747 self.jarfile = Some(jarfile.to_owned());
748 self
749 }
750
751 /// New password
752 pub fn new_arg(&mut self, new_arg: String) -> &mut Self {
753 self.new_arg = Some(new_arg);
754 self
755 }
756
757 /// Secure Sockets Layer (SSL) server host and port
758 pub fn sslserver(&mut self, sslserver: String) -> &mut Self {
759 self.sslserver = Some(sslserver);
760 self
761 }
762
763 /// Output in RFC style
764 pub fn rfc(&mut self, rfc: bool) -> &mut Self {
765 self.rfc = rfc;
766 self
767 }
768
769 /// Verbose output
770 pub fn v(&mut self, v: bool) -> &mut Self {
771 self.v = v;
772 self
773 }
774
775 /// Provider classpath
776 pub fn providerpath(&mut self, providerpath: &[PathBuf]) -> &mut Self {
777 self.providerpath = Some(providerpath.to_vec());
778 self
779 }
780
781 /// Destination alias
782 pub fn destalias(&mut self, destalias: String) -> &mut Self {
783 self.destalias = Some(destalias);
784 self
785 }
786
787 /// Runs keytool commands
788 pub fn run(&self) -> Result<Option<Key>> {
789 let mut key = Some(Key::new_default()?);
790 let mut keytool = keytool()?;
791 if self.v {
792 keytool.arg("-v");
793 }
794 if let Some(keystore) = &self.keystore {
795 keytool.arg("-keystore").arg(keystore);
796 if let Some(key) = &mut key {
797 key.key_path = keystore.to_owned();
798 }
799 }
800 if let Some(alias) = &self.alias {
801 keytool.arg("-alias").arg(alias);
802 if let Some(key) = &mut key {
803 key.key_alias = alias.to_owned();
804 }
805 }
806 if let Some(keypass) = &self.keypass {
807 keytool.arg("-keypass").arg(keypass);
808 if let Some(key) = &mut key {
809 key.key_pass = keypass.to_owned();
810 }
811 }
812 if let Some(storepass) = &self.storepass {
813 keytool.arg("-storepass").arg(storepass);
814 }
815 if let Some(dname) = &self.dname {
816 keytool.arg("-dname").arg(
817 dname
818 .iter()
819 .map(|v| v.to_string())
820 .collect::<Vec<String>>()
821 .join(","),
822 );
823 }
824 if let Some(storetype) = &self.storetype {
825 keytool.arg("-storetype").arg(storetype.to_string());
826 }
827 if let Some(keyalg) = &self.keyalg {
828 keytool.arg("-keyalg").arg(keyalg.to_string());
829 }
830 if let Some(providername) = &self.providername {
831 keytool.arg("-providername").arg(providername);
832 }
833 if let Some(providerclass) = &self.providerclass {
834 keytool.arg("-providerclass").arg(providerclass);
835 }
836 if let Some(providerarg) = &self.providerarg {
837 keytool.arg("-providerarg").arg(providerarg);
838 }
839 if self.protected {
840 keytool.arg("-protected");
841 }
842 if let Some(ext) = &self.ext {
843 keytool.arg("-ext").arg(ext);
844 }
845 if let Some(keysize) = &self.keysize {
846 keytool.arg("-keysize").arg(keysize.to_string());
847 }
848 if let Some(validity) = &self.validity {
849 keytool.arg("-validity").arg(validity.to_string());
850 }
851 if self.gencert {
852 keytool.arg("-gencert");
853 }
854 if self.genkeypair {
855 keytool.arg("-genkeypair");
856 }
857 if self.genseckey {
858 keytool.arg("-genseckey");
859 }
860 if self.mportcert {
861 keytool.arg("-mportcert");
862 }
863 if self.importpass {
864 keytool.arg("-importpass");
865 }
866 if self.importkeystore {
867 keytool.arg("-importkeystore");
868 }
869 if self.printcertreq {
870 keytool.arg("-printcertreq");
871 }
872 if self.certreq {
873 keytool.arg("-certreq");
874 }
875 if self.exportcert {
876 keytool.arg("-exportcert");
877 }
878 if self.list {
879 keytool.arg("-list");
880 }
881 if self.printcert {
882 keytool.arg("-printcert");
883 }
884 if self.printcrl {
885 keytool.arg("-printcrl");
886 }
887 if self.storepasswd {
888 keytool.arg("-storepasswd");
889 }
890 if self.keypasswd {
891 keytool.arg("-keypasswd");
892 }
893 if self.delete {
894 keytool.arg("-delete");
895 }
896 if self.changealias {
897 keytool.arg("-changealias");
898 }
899 if self.help {
900 keytool.arg("-help");
901 key = None;
902 }
903 if let Some(file) = &self.file {
904 keytool.arg("-file").arg(file);
905 }
906 if let Some(jarfile) = &self.jarfile {
907 keytool.arg("-jarfile").arg(jarfile);
908 }
909 if let Some(new_arg) = &self.new_arg {
910 keytool.arg("-new").arg(new_arg);
911 }
912 if let Some(sslserver) = &self.sslserver {
913 keytool.arg("-sslserver").arg(sslserver);
914 }
915 if let Some(destalias) = &self.destalias {
916 keytool.arg("-destalias").arg(destalias);
917 }
918 if self.rfc {
919 keytool.arg("-rfc");
920 }
921 if let Some(providerpath) = &self.providerpath {
922 keytool.arg("-providerpath").arg(
923 providerpath
924 .iter()
925 .map(|v| v.to_string_lossy().to_string())
926 .collect::<Vec<String>>()
927 .join(","),
928 );
929 }
930 keytool.output_err(true)?;
931 Ok(key)
932 }
933}
934
935/// The `keytool` command is a key and certificate management utility. It enables users to
936/// administer their own public/private key pairs and associated certificates for use in
937/// self-authentication (where the user authenticates himself or herself to other users
938/// and services) or data integrity and authentication services, using digital signatures.
939/// The `keytool` command also enables users to cache the public keys (in the form of
940/// certificates) of their communicating peers
941pub fn keytool() -> Result<Command> {
942 if let Ok(keytool) = which::which(bin!("keytool")) {
943 return Ok(Command::new(keytool));
944 }
945 if let Ok(java) = std::env::var("JAVA_HOME") {
946 let keytool = PathBuf::from(java).join("bin").join(bin!("keytool"));
947 if keytool.exists() {
948 return Ok(Command::new(keytool));
949 }
950 }
951 Err(Error::CmdNotFound("keytool".to_string()))
952}
953
954#[derive(Clone)]
955pub enum StoreType {
956 JKS,
957 /// This keystore implementation employs a much stronger protection of private
958 /// keys (using password-based encryption with Triple DES) than JKS. You can
959 /// upgrade your keystore of type "JKS" to type "JCEKS" by changing the password
960 /// of a private-key entry in your keystore.
961 JCEKS,
962 /// There is a difference between PKCS12 type keystore created on the keytool
963 /// provided in the IBM JVM and the keytool provided in an Oracle JVM. The keytool
964 /// in an IBM JVM uses a PKCS12 keystore to store both key entries and certificate
965 /// entries.The keytool in an Oracle JVM uses a PKCS12 keystore to store key entries.
966 /// The keytool program in IBM's JVM can read the keystore created by the keytool
967 /// program provided by an Oracle JVM, but not the other way around.
968 PKCS12,
969 /// This is a second version of `PKCS12` type `keystore`. It can be read by the keytool
970 /// program in an `Oracle JVM`.
971 PKCS12S2,
972 /// This is a RACF® keyring keystore. This type is available only on z/OS® systems
973 /// with RACF installed. When using JCERACFKS keystore, you must always specify the
974 /// `-keystore` option. This is no default value.
975 JCERACFKS,
976}
977
978#[derive(Clone)]
979pub enum KeyAlgorithm {
980 RSA,
981 /// This keystore implementation employs a much stronger protection of private
982 /// keys (using password-based encryption with Triple DES) than JKS. You can
983 /// upgrade your keystore of type "JKS" to type "JCEKS" by changing the password
984 /// of a private-key entry in your keystore.
985 DSA,
986 /// There is a difference between PKCS12 type keystore created on the keytool
987 /// provided in the IBM JVM and the keytool provided in an Oracle JVM. The keytool
988 /// in an IBM JVM uses a PKCS12 keystore to store both key entries and certificate
989 /// entries.The keytool in an Oracle JVM uses a PKCS12 keystore to store key entries.
990 /// The keytool program in IBM's JVM can read the keystore created by the keytool
991 /// program provided by an Oracle JVM, but not the other way around.
992 EC,
993 /// This is a second version of `PKCS12` type `keystore`. It can be read by the keytool
994 /// program in an `Oracle JVM`.
995 DES,
996 /// This is a RACF® keyring keystore. This type is available only on z/OS® systems
997 /// with RACF installed. When using JCERACFKS keystore, you must always specify the
998 /// `-keystore` option. This is no default value.
999 DESede,
1000}
1001
1002impl std::fmt::Display for StoreType {
1003 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
1004 match *self {
1005 Self::JKS => write!(f, "JKS"),
1006 Self::JCEKS => write!(f, "JCEKS"),
1007 Self::PKCS12 => write!(f, "PKCS12"),
1008 Self::PKCS12S2 => write!(f, "PKCS12S2"),
1009 Self::JCERACFKS => write!(f, "JCERACFKS"),
1010 }
1011 }
1012}
1013
1014impl std::fmt::Display for KeyAlgorithm {
1015 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
1016 match *self {
1017 Self::RSA => write!(f, "RSA"),
1018 Self::DSA => write!(f, "DSA"),
1019 Self::EC => write!(f, "EC"),
1020 Self::DES => write!(f, "DES"),
1021 Self::DESede => write!(f, "DESede"),
1022 }
1023 }
1024}
1025
1026#[derive(Debug, Clone)]
1027pub struct Key {
1028 pub key_path: PathBuf,
1029 pub key_pass: String,
1030 pub key_alias: String,
1031}
1032
1033impl Key {
1034 pub fn new_default() -> Result<Self> {
1035 let key_path = android_dir()?.join("aab.keystore");
1036 let key_pass = "android".to_string();
1037 let key_alias = "androidaabkey".to_string();
1038 Ok(Self {
1039 key_path,
1040 key_pass,
1041 key_alias,
1042 })
1043 }
1044}
1045
1046/// Returns or crates it if needed the path to `.android` in the user's home directory.
1047pub fn android_dir() -> Result<PathBuf> {
1048 let android_dir = dirs::home_dir()
1049 .ok_or(Error::UnableToAccessHomeDirectory)?
1050 .join(".android");
1051 std::fs::create_dir_all(&android_dir)?;
1052 Ok(android_dir)
1053}