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 }