Encrypt contents of stdin and write to stdout
| 714 | |
| 715 | // Encrypt contents of stdin and write to stdout |
| 716 | int clean (int argc, const char** argv) |
| 717 | { |
| 718 | const char* key_name = 0; |
| 719 | const char* key_path = 0; |
| 720 | const char* legacy_key_path = 0; |
| 721 | |
| 722 | int argi = parse_plumbing_options(&key_name, &key_path, argc, argv); |
| 723 | if (argc - argi == 0) { |
| 724 | } else if (!key_name && !key_path && argc - argi == 1) { // Deprecated - for compatibility with pre-0.4 |
| 725 | legacy_key_path = argv[argi]; |
| 726 | } else { |
| 727 | std::clog << "Usage: git-crypt clean [--key-name=NAME] [--key-file=PATH]" << std::endl; |
| 728 | return 2; |
| 729 | } |
| 730 | Key_file key_file; |
| 731 | load_key(key_file, key_name, key_path, legacy_key_path); |
| 732 | |
| 733 | const Key_file::Entry* key = key_file.get_latest(); |
| 734 | if (!key) { |
| 735 | std::clog << "git-crypt: error: key file is empty" << std::endl; |
| 736 | return 1; |
| 737 | } |
| 738 | |
| 739 | // Read the entire file |
| 740 | |
| 741 | Hmac_sha1_state hmac(key->hmac_key, HMAC_KEY_LEN); // Calculate the file's SHA1 HMAC as we go |
| 742 | uint64_t file_size = 0; // Keep track of the length, make sure it doesn't get too big |
| 743 | std::string file_contents; // First 8MB or so of the file go here |
| 744 | temp_fstream temp_file; // The rest of the file spills into a temporary file on disk |
| 745 | temp_file.exceptions(std::fstream::badbit); |
| 746 | |
| 747 | char buffer[1024]; |
| 748 | |
| 749 | while (std::cin && file_size < Aes_ctr_encryptor::MAX_CRYPT_BYTES) { |
| 750 | std::cin.read(buffer, sizeof(buffer)); |
| 751 | |
| 752 | const size_t bytes_read = std::cin.gcount(); |
| 753 | |
| 754 | hmac.add(reinterpret_cast<unsigned char*>(buffer), bytes_read); |
| 755 | file_size += bytes_read; |
| 756 | |
| 757 | if (file_size <= 8388608) { |
| 758 | file_contents.append(buffer, bytes_read); |
| 759 | } else { |
| 760 | if (!temp_file.is_open()) { |
| 761 | temp_file.open(std::fstream::in | std::fstream::out | std::fstream::binary | std::fstream::app); |
| 762 | } |
| 763 | temp_file.write(buffer, bytes_read); |
| 764 | } |
| 765 | } |
| 766 | |
| 767 | // Make sure the file isn't so large we'll overflow the counter value (which would doom security) |
| 768 | if (file_size >= Aes_ctr_encryptor::MAX_CRYPT_BYTES) { |
| 769 | std::clog << "git-crypt: error: file too long to encrypt securely" << std::endl; |
| 770 | return 1; |
| 771 | } |
| 772 | |
| 773 | // We use an HMAC of the file as the encryption nonce (IV) for CTR mode. |
no test coverage detected