github.com/muhammedhassanm/blockchain@v0.0.0-20200120143007-697261defd4d/sawtooth-core-master/adm/src/commands/keygen.rs (about)

     1  /*
     2   * Copyright 2018 Intel Corporation
     3   *
     4   * Licensed under the Apache License, Version 2.0 (the "License");
     5   * you may not use this file except in compliance with the License.
     6   * You may obtain a copy of the License at
     7   *
     8   *     http://www.apache.org/licenses/LICENSE-2.0
     9   *
    10   * Unless required by applicable law or agreed to in writing, software
    11   * distributed under the License is distributed on an "AS IS" BASIS,
    12   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    13   * See the License for the specific language governing permissions and
    14   * limitations under the License.
    15   * ------------------------------------------------------------------------------
    16   */
    17  
    18  use std::ffi::CString;
    19  use std::fs::{metadata, OpenOptions};
    20  use std::io::prelude::*;
    21  #[cfg(target_os = "linux")]
    22  use std::os::linux::fs::MetadataExt;
    23  #[cfg(not(target_os = "linux"))]
    24  use std::os::unix::fs::MetadataExt;
    25  use std::os::unix::fs::OpenOptionsExt;
    26  use std::path::Path;
    27  
    28  use clap::ArgMatches;
    29  use libc;
    30  
    31  use sawtooth_sdk::signing;
    32  
    33  use config;
    34  use err::CliError;
    35  
    36  pub fn run<'a>(args: &ArgMatches<'a>) -> Result<(), CliError> {
    37      let path_config = config::get_path_config();
    38      let key_dir = &path_config.key_dir;
    39      if !key_dir.exists() {
    40          return Err(CliError::EnvironmentError(format!(
    41              "Key directory does not exist: {:?}",
    42              key_dir
    43          )));
    44      }
    45  
    46      let key_name = args.value_of("key_name").unwrap_or("validator");
    47      let private_key_path = key_dir.join(key_name).with_extension("priv");
    48      let public_key_path = key_dir.join(key_name).with_extension("pub");
    49  
    50      if !args.is_present("force") {
    51          if private_key_path.exists() {
    52              return Err(CliError::EnvironmentError(format!(
    53                  "file exists: {:?}",
    54                  private_key_path
    55              )));
    56          }
    57          if public_key_path.exists() {
    58              return Err(CliError::EnvironmentError(format!(
    59                  "file exists: {:?}",
    60                  public_key_path
    61              )));
    62          }
    63      }
    64  
    65      let context = signing::create_context("secp256k1")
    66          .map_err(|err| CliError::EnvironmentError(format!("{}", err)))?;
    67  
    68      let private_key = context
    69          .new_random_private_key()
    70          .map_err(|err| CliError::EnvironmentError(format!("{}", err)))?;
    71      let public_key = context
    72          .get_public_key(&*private_key)
    73          .map_err(|err| CliError::EnvironmentError(format!("{}", err)))?;
    74  
    75      let key_dir_info =
    76          metadata(key_dir).map_err(|err| CliError::EnvironmentError(format!("{}", err)))?;
    77  
    78      #[cfg(not(target_os = "linux"))]
    79      let (key_dir_uid, key_dir_gid) = (key_dir_info.uid(), key_dir_info.gid());
    80      #[cfg(target_os = "linux")]
    81      let (key_dir_uid, key_dir_gid) = (key_dir_info.st_uid(), key_dir_info.st_gid());
    82  
    83      {
    84          if private_key_path.exists() {
    85              println!("overwriting file: {:?}", private_key_path);
    86          } else {
    87              println!("writing file: {:?}", private_key_path);
    88          }
    89          let mut private_key_file = OpenOptions::new()
    90              .write(true)
    91              .create(true)
    92              .mode(0o640)
    93              .open(private_key_path.as_path())
    94              .map_err(|err| CliError::EnvironmentError(format!("{}", err)))?;
    95  
    96          private_key_file
    97              .write(private_key.as_hex().as_bytes())
    98              .map_err(|err| CliError::EnvironmentError(format!("{}", err)))?;
    99      }
   100  
   101      {
   102          if public_key_path.exists() {
   103              println!("overwriting file: {:?}", public_key_path);
   104          } else {
   105              println!("writing file: {:?}", public_key_path);
   106          }
   107          let mut public_key_file = OpenOptions::new()
   108              .write(true)
   109              .create(true)
   110              .mode(0o644)
   111              .open(public_key_path.as_path())
   112              .map_err(|err| CliError::EnvironmentError(format!("{}", err)))?;
   113  
   114          public_key_file
   115              .write(public_key.as_hex().as_bytes())
   116              .map_err(|err| CliError::EnvironmentError(format!("{}", err)))?;
   117      }
   118  
   119      chown(private_key_path.as_path(), key_dir_uid, key_dir_gid)?;
   120      chown(public_key_path.as_path(), key_dir_uid, key_dir_gid)?;
   121      Ok(())
   122  }
   123  
   124  fn chown(path: &Path, uid: u32, gid: u32) -> Result<(), CliError> {
   125      let pathstr = path.to_str()
   126          .ok_or_else(|| CliError::EnvironmentError(format!("Invalid path: {:?}", path)))?;
   127      let cpath =
   128          CString::new(pathstr).map_err(|err| CliError::EnvironmentError(format!("{}", err)))?;
   129      let result = unsafe { libc::chown(cpath.as_ptr(), uid, gid) };
   130      match result {
   131          0 => Ok(()),
   132          code => Err(CliError::EnvironmentError(format!(
   133              "Error chowning file {}: {}",
   134              pathstr, code
   135          ))),
   136      }
   137  }