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}