2023-02-02 16:45:59 +00:00
#!/usr/bin/env python3
# MIT License
#
# Copyright (c) 2023 Mark Qvist / unsigned.io
#
# Permission is hereby granted, free of charge, to any person obtaining a copy
# of this software and associated documentation files (the "Software"), to deal
# in the Software without restriction, including without limitation the rights
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
# copies of the Software, and to permit persons to whom the Software is
# furnished to do so, subject to the following conditions:
#
# The above copyright notice and this permission notice shall be included in all
# copies or substantial portions of the Software.
#
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
# SOFTWARE.
import RNS
import argparse
import time
import sys
import os
2023-02-02 18:02:05 +00:00
import base64
2023-02-02 16:45:59 +00:00
from RNS . _version import __version__
APP_NAME = " rnid "
SIG_EXT = " rsg "
ENCRYPT_EXT = " rfe "
CHUNK_SIZE = 16 * 1024 * 1024
def spin ( until = None , msg = None , timeout = None ) :
i = 0
syms = " ⢄⢂⢁⡁⡈⡐⡠ "
if timeout != None :
timeout = time . time ( ) + timeout
2024-10-07 08:44:18 +00:00
print ( f " { msg } " , end = " " )
2023-02-02 16:45:59 +00:00
while ( timeout == None or time . time ( ) < timeout ) and not until ( ) :
time . sleep ( 0.1 )
2024-10-07 08:44:18 +00:00
print ( f ' \x08 \x08 { syms [ i ] } ' , end = " " )
2023-02-02 16:45:59 +00:00
sys . stdout . flush ( )
i = ( i + 1 ) % len ( syms )
2024-10-07 08:44:18 +00:00
print ( f " \r { ' ' * len ( msg ) } \r " , end = " " )
2023-02-02 16:45:59 +00:00
if timeout != None and time . time ( ) > timeout :
return False
else :
return True
def main ( ) :
try :
parser = argparse . ArgumentParser ( description = " Reticulum Identity & Encryption Utility " )
# parser.add_argument("file", nargs="?", default=None, help="input file path", type=str)
parser . add_argument ( " --config " , metavar = " path " , action = " store " , default = None , help = " path to alternative Reticulum config directory " , type = str )
2023-02-02 18:26:27 +00:00
parser . add_argument ( " -i " , " --identity " , metavar = " identity " , action = " store " , default = None , help = " hexadecimal Reticulum Destination hash or path to Identity file " , type = str )
2023-12-02 01:10:22 +00:00
parser . add_argument ( " -g " , " --generate " , metavar = " file " , action = " store " , default = None , help = " generate a new Identity " )
parser . add_argument ( " -m " , " --import " , dest = " import_str " , metavar = " identity_data " , action = " store " , default = None , help = " import Reticulum identity in hex, base32 or base64 format " , type = str )
parser . add_argument ( " -x " , " --export " , action = " store_true " , default = None , help = " export identity to hex, base32 or base64 format " )
2023-02-02 16:45:59 +00:00
parser . add_argument ( " -v " , " --verbose " , action = " count " , default = 0 , help = " increase verbosity " )
parser . add_argument ( " -q " , " --quiet " , action = " count " , default = 0 , help = " decrease verbosity " )
2023-02-03 19:27:39 +00:00
parser . add_argument ( " -a " , " --announce " , metavar = " aspects " , action = " store " , default = None , help = " announce a destination based on this Identity " )
2023-07-09 14:29:40 +00:00
parser . add_argument ( " -H " , " --hash " , metavar = " aspects " , action = " store " , default = None , help = " show destination hashes for other aspects for this Identity " )
2023-12-02 01:10:22 +00:00
parser . add_argument ( " -e " , " --encrypt " , metavar = " file " , action = " store " , default = None , help = " encrypt file " )
parser . add_argument ( " -d " , " --decrypt " , metavar = " file " , action = " store " , default = None , help = " decrypt file " )
2023-02-02 18:02:05 +00:00
parser . add_argument ( " -s " , " --sign " , metavar = " path " , action = " store " , default = None , help = " sign file " )
parser . add_argument ( " -V " , " --validate " , metavar = " path " , action = " store " , default = None , help = " validate signature " )
2023-02-02 16:45:59 +00:00
2023-12-02 01:10:22 +00:00
parser . add_argument ( " -r " , " --read " , metavar = " file " , action = " store " , default = None , help = " input file path " , type = str )
parser . add_argument ( " -w " , " --write " , metavar = " file " , action = " store " , default = None , help = " output file path " , type = str )
2023-02-02 16:45:59 +00:00
parser . add_argument ( " -f " , " --force " , action = " store_true " , default = None , help = " write output even if it overwrites existing files " )
parser . add_argument ( " -I " , " --stdin " , action = " store_true " , default = False , help = argparse . SUPPRESS ) # "read input from STDIN instead of file"
parser . add_argument ( " -O " , " --stdout " , action = " store_true " , default = False , help = argparse . SUPPRESS ) # help="write output to STDOUT instead of file",
parser . add_argument ( " -R " , " --request " , action = " store_true " , default = False , help = " request unknown Identities from the network " )
parser . add_argument ( " -t " , action = " store " , metavar = " seconds " , type = float , help = " identity request timeout before giving up " , default = RNS . Transport . PATH_REQUEST_TIMEOUT )
parser . add_argument ( " -p " , " --print-identity " , action = " store_true " , default = False , help = " print identity info and exit " )
parser . add_argument ( " -P " , " --print-private " , action = " store_true " , default = False , help = " allow displaying private keys " )
2023-12-02 01:10:22 +00:00
parser . add_argument ( " -b " , " --base64 " , action = " store_true " , default = False , help = " Use base64-encoded input and output " )
parser . add_argument ( " -B " , " --base32 " , action = " store_true " , default = False , help = " Use base32-encoded input and output " )
2023-02-02 16:45:59 +00:00
2024-10-07 08:44:18 +00:00
parser . add_argument ( " --version " , action = " version " , version = f " rnid { __version__ } " )
2023-02-02 16:45:59 +00:00
args = parser . parse_args ( )
ops = 0 ;
2023-02-02 18:02:05 +00:00
for t in [ args . encrypt , args . decrypt , args . validate , args . sign ] :
2023-02-02 16:45:59 +00:00
if t :
ops + = 1
if ops > 1 :
RNS . log ( " This utility currently only supports one of the encrypt, decrypt, sign or verify operations per invocation " , RNS . LOG_ERROR )
exit ( 1 )
2023-02-02 18:02:05 +00:00
if not args . read :
if args . encrypt :
args . read = args . encrypt
if args . decrypt :
args . read = args . decrypt
if args . sign :
args . read = args . sign
2023-02-02 18:26:27 +00:00
identity_str = args . identity
2023-12-02 01:10:22 +00:00
if args . import_str :
identity_bytes = None
try :
if args . base64 :
identity_bytes = base64 . urlsafe_b64decode ( args . import_str )
elif args . base32 :
identity_bytes = base64 . b32decode ( args . import_str )
else :
identity_bytes = bytes . fromhex ( args . import_str )
except Exception as e :
2024-10-07 08:44:18 +00:00
print ( f " Invalid identity data specified for import: { e } " )
2023-12-02 01:10:22 +00:00
exit ( 41 )
try :
identity = RNS . Identity . from_bytes ( identity_bytes )
except Exception as e :
2024-10-07 08:44:18 +00:00
print ( f " Could not create Reticulum identity from specified data: { e } " )
2023-12-02 01:10:22 +00:00
exit ( 42 )
RNS . log ( " Identity imported " )
if args . base64 :
2024-10-07 08:44:18 +00:00
RNS . log ( f " Public Key : { base64 . urlsafe_b64encode ( identity . get_public_key ( ) ) . decode ( ' utf-8 ' ) } " )
2023-12-02 01:10:22 +00:00
elif args . base32 :
2024-10-07 08:44:18 +00:00
RNS . log ( f " Public Key : { base64 . b32encode ( identity . get_public_key ( ) ) . decode ( ' utf-8 ' ) } " )
2023-12-02 01:10:22 +00:00
else :
2024-10-07 08:44:18 +00:00
RNS . log ( f " Public Key : { RNS . hexrep ( identity . get_public_key ( ) , delimit = False ) } " )
2023-12-02 01:10:22 +00:00
if identity . prv :
if args . print_private :
if args . base64 :
2024-10-07 08:44:18 +00:00
RNS . log ( f " Private Key : { base64 . urlsafe_b64encode ( identity . get_private_key ( ) ) . decode ( ' utf-8 ' ) } " )
2023-12-02 01:10:22 +00:00
elif args . base32 :
2024-10-07 08:44:18 +00:00
RNS . log ( f " Private Key : { base64 . b32encode ( identity . get_private_key ( ) ) . decode ( ' utf-8 ' ) } " )
2023-12-02 01:10:22 +00:00
else :
2024-10-07 08:44:18 +00:00
RNS . log ( f " Private Key : { RNS . hexrep ( identity . get_private_key ( ) , delimit = False ) } " )
2023-12-02 01:10:22 +00:00
else :
RNS . log ( " Private Key : Hidden " )
if args . write :
try :
wp = os . path . expanduser ( args . write )
if not os . path . isfile ( wp ) or args . force :
identity . to_file ( wp )
2024-10-07 08:44:18 +00:00
RNS . log ( f " Wrote imported identity to { args . write } " )
2023-12-02 01:10:22 +00:00
else :
2024-10-07 08:44:18 +00:00
print ( f " File { wp } already exists, not overwriting " )
2023-12-02 01:10:22 +00:00
exit ( 43 )
except Exception as e :
2024-10-07 08:44:18 +00:00
print ( f " Error while writing imported identity to file: { e } " )
2023-12-02 01:10:22 +00:00
exit ( 44 )
exit ( 0 )
2023-02-02 18:26:27 +00:00
if not args . generate and not identity_str :
2023-02-02 16:45:59 +00:00
print ( " \n No identity provided, cannot continue \n " )
parser . print_help ( )
print ( " " )
2023-02-02 18:26:27 +00:00
exit ( 2 )
2023-02-02 16:45:59 +00:00
else :
targetloglevel = 4
verbosity = args . verbose
quietness = args . quiet
if verbosity != 0 or quietness != 0 :
targetloglevel = targetloglevel + verbosity - quietness
# Start Reticulum
reticulum = RNS . Reticulum ( configdir = args . config , loglevel = targetloglevel )
RNS . compact_log_fmt = True
if args . stdout :
RNS . loglevel = - 1
2023-02-02 18:26:27 +00:00
if args . generate :
identity = RNS . Identity ( )
if not args . force and os . path . isfile ( args . generate ) :
2024-10-07 08:44:18 +00:00
RNS . log ( f " Identity file { args . generate } already exists. Not overwriting. " , RNS . LOG_ERROR )
2023-02-02 18:26:27 +00:00
exit ( 3 )
else :
try :
identity . to_file ( args . generate )
2024-10-07 08:44:18 +00:00
RNS . log ( f " New identity written to { args . generate } " )
2023-02-02 18:26:27 +00:00
exit ( 0 )
except Exception as e :
RNS . log ( " An error ocurred while saving the generated Identity. " , RNS . LOG_ERROR )
2024-10-07 08:44:18 +00:00
RNS . log ( f " The contained exception was: { e } " , RNS . LOG_ERROR )
2023-02-02 18:26:27 +00:00
exit ( 4 )
2023-02-02 16:45:59 +00:00
identity = None
if len ( identity_str ) == RNS . Reticulum . TRUNCATED_HASHLENGTH / / 8 * 2 and not os . path . isfile ( identity_str ) :
# Try recalling Identity from hex-encoded hash
try :
destination_hash = bytes . fromhex ( identity_str )
identity = RNS . Identity . recall ( destination_hash )
if identity == None :
if not args . request :
2024-10-07 08:44:18 +00:00
RNS . log ( f " Could not recall Identity for { RNS . prettyhexrep ( destination_hash ) } . " , RNS . LOG_ERROR )
2023-02-02 16:45:59 +00:00
RNS . log ( " You can query the network for unknown Identities with the -R option. " , RNS . LOG_ERROR )
2023-02-02 18:26:27 +00:00
exit ( 5 )
2023-02-02 16:45:59 +00:00
else :
RNS . Transport . request_path ( destination_hash )
def spincheck ( ) :
return RNS . Identity . recall ( destination_hash ) != None
2024-10-07 08:44:18 +00:00
spin ( spincheck , f " Requesting unknown Identity for { RNS . prettyhexrep ( destination_hash ) } " , args . t )
2023-02-02 16:45:59 +00:00
if not spincheck ( ) :
RNS . log ( " Identity request timed out " , RNS . LOG_ERROR )
2023-02-02 18:26:27 +00:00
exit ( 6 )
2023-02-02 16:45:59 +00:00
else :
identity = RNS . Identity . recall ( destination_hash )
2024-10-07 08:44:18 +00:00
RNS . log ( f " Received Identity { identity } for destination { RNS . prettyhexrep ( destination_hash ) } from the network " )
2023-02-02 16:45:59 +00:00
else :
2024-10-07 08:44:18 +00:00
RNS . log ( f " Recalled Identity { identity } for destination { RNS . prettyhexrep ( destination_hash ) } " )
2023-02-02 16:45:59 +00:00
except Exception as e :
RNS . log ( " Invalid hexadecimal hash provided " , RNS . LOG_ERROR )
2023-02-02 18:26:27 +00:00
exit ( 7 )
2023-02-02 16:45:59 +00:00
else :
# Try loading Identity from file
if not os . path . isfile ( identity_str ) :
RNS . log ( " Specified Identity file not found " )
2023-02-02 18:26:27 +00:00
exit ( 8 )
2023-02-02 16:45:59 +00:00
else :
try :
identity = RNS . Identity . from_file ( identity_str )
2024-10-07 08:44:18 +00:00
RNS . log ( f " Loaded Identity { identity } from { identity_str } " )
2023-02-02 16:45:59 +00:00
except Exception as e :
RNS . log ( " Could not decode Identity from specified file " )
2023-02-02 18:26:27 +00:00
exit ( 9 )
2023-02-02 16:45:59 +00:00
if identity != None :
2023-02-03 19:27:39 +00:00
if args . hash :
try :
aspects = args . hash . split ( " . " )
2023-09-29 10:29:37 +00:00
if not len ( aspects ) > 0 :
2023-02-03 19:27:39 +00:00
RNS . log ( " Invalid destination aspects specified " , RNS . LOG_ERROR )
exit ( 32 )
else :
app_name = aspects [ 0 ]
aspects = aspects [ 1 : ]
if identity . pub != None :
destination = RNS . Destination ( identity , RNS . Destination . OUT , RNS . Destination . SINGLE , app_name , * aspects )
2024-10-07 08:44:18 +00:00
RNS . log ( f " The { args . hash } destination for this Identity is { RNS . prettyhexrep ( destination . hash ) } " )
RNS . log ( f " The full destination specifier is { destination } " )
2023-02-03 19:27:39 +00:00
time . sleep ( 0.25 )
exit ( 0 )
else :
raise KeyError ( " No public key known " )
except Exception as e :
RNS . log ( " An error ocurred while attempting to send the announce. " , RNS . LOG_ERROR )
2024-10-07 08:44:18 +00:00
RNS . log ( f " The contained exception was: { e } " , RNS . LOG_ERROR )
2023-02-03 19:27:39 +00:00
exit ( 0 )
if args . announce :
try :
aspects = args . announce . split ( " . " )
if not len ( aspects ) > 1 :
RNS . log ( " Invalid destination aspects specified " , RNS . LOG_ERROR )
exit ( 32 )
else :
app_name = aspects [ 0 ]
aspects = aspects [ 1 : ]
if identity . prv != None :
destination = RNS . Destination ( identity , RNS . Destination . IN , RNS . Destination . SINGLE , app_name , * aspects )
2024-10-07 08:44:18 +00:00
RNS . log ( f " Created destination { destination } " )
RNS . log ( f " Announcing destination { RNS . prettyhexrep ( destination . hash ) } " )
2023-02-03 19:27:39 +00:00
destination . announce ( )
time . sleep ( 0.25 )
exit ( 0 )
else :
destination = RNS . Destination ( identity , RNS . Destination . OUT , RNS . Destination . SINGLE , app_name , * aspects )
2024-10-07 08:44:18 +00:00
RNS . log ( f " The { args . announce } destination for this Identity is { RNS . prettyhexrep ( destination . hash ) } " )
RNS . log ( f " The full destination specifier is { destination } " )
2023-02-03 19:27:39 +00:00
RNS . log ( " Cannot announce this destination, since the private key is not held " )
time . sleep ( 0.25 )
exit ( 33 )
except Exception as e :
RNS . log ( " An error ocurred while attempting to send the announce. " , RNS . LOG_ERROR )
2024-10-07 08:44:18 +00:00
RNS . log ( f " The contained exception was: { e } " , RNS . LOG_ERROR )
2023-02-03 19:27:39 +00:00
exit ( 0 )
2023-02-02 16:45:59 +00:00
if args . print_identity :
2023-12-02 01:10:22 +00:00
if args . base64 :
2024-10-07 08:44:18 +00:00
RNS . log ( f " Public Key : { base64 . urlsafe_b64encode ( identity . get_public_key ( ) ) . decode ( ' utf-8 ' ) } " )
2023-12-02 01:10:22 +00:00
elif args . base32 :
2024-10-07 08:44:18 +00:00
RNS . log ( f " Public Key : { base64 . b32encode ( identity . get_public_key ( ) ) . decode ( ' utf-8 ' ) } " )
2023-12-02 01:10:22 +00:00
else :
2024-10-07 08:44:18 +00:00
RNS . log ( f " Public Key : { RNS . hexrep ( identity . get_public_key ( ) , delimit = False ) } " )
2023-02-02 16:45:59 +00:00
if identity . prv :
if args . print_private :
2023-12-02 01:10:22 +00:00
if args . base64 :
2024-10-07 08:44:18 +00:00
RNS . log ( f " Private Key : { base64 . urlsafe_b64encode ( identity . get_private_key ( ) ) . decode ( ' utf-8 ' ) } " )
2023-12-02 01:10:22 +00:00
elif args . base32 :
2024-10-07 08:44:18 +00:00
RNS . log ( f " Private Key : { base64 . b32encode ( identity . get_private_key ( ) ) . decode ( ' utf-8 ' ) } " )
2023-12-02 01:10:22 +00:00
else :
2024-10-07 08:44:18 +00:00
RNS . log ( f " Private Key : { RNS . hexrep ( identity . get_private_key ( ) , delimit = False ) } " )
2023-02-02 16:45:59 +00:00
else :
RNS . log ( " Private Key : Hidden " )
exit ( 0 )
2023-12-02 01:10:22 +00:00
if args . export :
if identity . prv :
if args . base64 :
2024-10-07 08:44:18 +00:00
RNS . log ( f " Exported Identity : { base64 . urlsafe_b64encode ( identity . get_private_key ( ) ) . decode ( ' utf-8 ' ) } " )
2023-12-02 01:10:22 +00:00
elif args . base32 :
2024-10-07 08:44:18 +00:00
RNS . log ( f " Exported Identity : { base64 . b32encode ( identity . get_private_key ( ) ) . decode ( ' utf-8 ' ) } " )
2023-12-02 01:10:22 +00:00
else :
2024-10-07 08:44:18 +00:00
RNS . log ( f " Exported Identity : { RNS . hexrep ( identity . get_private_key ( ) , delimit = False ) } " )
2023-12-02 01:10:22 +00:00
else :
RNS . log ( " Identity doesn ' t hold a private key, cannot export " )
exit ( 50 )
exit ( 0 )
2023-02-02 18:02:05 +00:00
if args . validate :
2024-10-07 08:44:18 +00:00
if not args . read and args . validate . lower ( ) . endswith ( f " . { SIG_EXT } " ) :
args . read = str ( args . validate ) . replace ( f " . { SIG_EXT } " , " " )
2023-02-02 18:02:05 +00:00
if not os . path . isfile ( args . validate ) :
2024-10-07 08:44:18 +00:00
RNS . log ( f " Signature file { args . read } not found " , RNS . LOG_ERROR )
2023-02-02 18:26:27 +00:00
exit ( 10 )
2023-02-02 18:02:05 +00:00
if not os . path . isfile ( args . read ) :
2024-10-07 08:44:18 +00:00
RNS . log ( f " Input file { args . read } not found " , RNS . LOG_ERROR )
2023-02-02 18:26:27 +00:00
exit ( 11 )
2023-02-02 18:02:05 +00:00
2023-02-02 16:45:59 +00:00
data_input = None
if args . read :
if not os . path . isfile ( args . read ) :
2024-10-07 08:44:18 +00:00
RNS . log ( f " Input file { args . read } not found " , RNS . LOG_ERROR )
2023-02-02 18:26:27 +00:00
exit ( 12 )
2023-02-02 16:45:59 +00:00
else :
try :
data_input = open ( args . read , " rb " )
except Exception as e :
RNS . log ( " Could not open input file for reading " , RNS . LOG_ERROR )
2024-10-07 08:44:18 +00:00
RNS . log ( f " The contained exception was: { e } " , RNS . LOG_ERROR )
2023-02-02 18:26:27 +00:00
exit ( 13 )
2023-02-02 16:45:59 +00:00
# TODO: Actually expand this to a good solution
# probably need to create a wrapper that takes
# into account not closing stdin when done
# elif args.stdin:
# data_input = sys.stdin
data_output = None
if args . encrypt and not args . write and not args . stdout and args . read :
2024-10-07 08:44:18 +00:00
args . write = f " { args . read } . { ENCRYPT_EXT } "
2023-02-02 16:45:59 +00:00
2024-10-07 08:44:18 +00:00
if args . decrypt and not args . write and not args . stdout and args . read and args . read . lower ( ) . endswith ( f " . { ENCRYPT_EXT } " ) :
args . write = str ( args . read ) . replace ( f " . { ENCRYPT_EXT } " , " " )
2023-02-02 16:45:59 +00:00
2023-02-02 18:02:05 +00:00
if args . sign and identity . prv == None :
RNS . log ( " Specified Identity does not hold a private key. Cannot sign. " , RNS . LOG_ERROR )
2023-02-02 18:26:27 +00:00
exit ( 14 )
2023-02-02 18:02:05 +00:00
if args . sign and not args . write and not args . stdout and args . read :
2024-10-07 08:44:18 +00:00
args . write = f " { args . read } . { SIG_EXT } "
2023-02-02 18:02:05 +00:00
2023-02-02 16:45:59 +00:00
if args . write :
if not args . force and os . path . isfile ( args . write ) :
2024-10-07 08:44:18 +00:00
RNS . log ( f " Output file { args . write } already exists. Not overwriting. " , RNS . LOG_ERROR )
2023-02-02 18:26:27 +00:00
exit ( 15 )
2023-02-02 16:45:59 +00:00
else :
try :
data_output = open ( args . write , " wb " )
except Exception as e :
RNS . log ( " Could not open output file for writing " , RNS . LOG_ERROR )
2024-10-07 08:44:18 +00:00
RNS . log ( f " The contained exception was: { e } " , RNS . LOG_ERROR )
2023-02-02 18:26:27 +00:00
exit ( 15 )
2023-02-02 16:45:59 +00:00
# TODO: Actually expand this to a good solution
# probably need to create a wrapper that takes
# into account not closing stdout when done
# elif args.stdout:
# data_output = sys.stdout
2023-02-02 18:02:05 +00:00
if args . sign :
if identity . prv == None :
RNS . log ( " Specified Identity does not hold a private key. Cannot sign. " , RNS . LOG_ERROR )
2023-02-02 18:26:27 +00:00
exit ( 16 )
2023-02-02 18:02:05 +00:00
if not data_input :
if not args . stdout :
RNS . log ( " Signing requested, but no input data specified " , RNS . LOG_ERROR )
2023-02-02 18:26:27 +00:00
exit ( 17 )
2023-02-02 18:02:05 +00:00
else :
if not data_output :
if not args . stdout :
RNS . log ( " Signing requested, but no output specified " , RNS . LOG_ERROR )
2023-02-02 18:26:27 +00:00
exit ( 18 )
2023-02-02 18:02:05 +00:00
if not args . stdout :
2024-10-07 08:44:18 +00:00
RNS . log ( f " Signing { args . read } " )
2023-02-02 18:02:05 +00:00
try :
data_output . write ( identity . sign ( data_input . read ( ) ) )
data_output . close ( )
data_input . close ( )
if not args . stdout :
if args . read :
2024-10-07 08:44:18 +00:00
RNS . log ( f " File { args . read } signed with { identity } to { args . write } " )
2023-02-02 18:02:05 +00:00
exit ( 0 )
except Exception as e :
if not args . stdout :
RNS . log ( " An error ocurred while encrypting data. " , RNS . LOG_ERROR )
2024-10-07 08:44:18 +00:00
RNS . log ( f " The contained exception was: { e } " , RNS . LOG_ERROR )
2023-02-02 18:02:05 +00:00
try :
data_output . close ( )
except :
pass
try :
data_input . close ( )
except :
pass
2023-02-02 18:26:27 +00:00
exit ( 19 )
2023-02-02 18:02:05 +00:00
if args . validate :
if not data_input :
if not args . stdout :
RNS . log ( " Signature verification requested, but no input data specified " , RNS . LOG_ERROR )
2023-02-02 18:26:27 +00:00
exit ( 20 )
2023-02-02 18:02:05 +00:00
else :
# if not args.stdout:
# RNS.log("Verifying "+str(args.validate)+" for "+str(args.read))
try :
try :
sig_input = open ( args . validate , " rb " )
except Exception as e :
2024-10-07 08:44:18 +00:00
RNS . log ( f " An error ocurred while opening { args . validate } . " , RNS . LOG_ERROR )
RNS . log ( f " The contained exception was: { e } " , RNS . LOG_ERROR )
2023-02-02 18:26:27 +00:00
exit ( 21 )
2023-02-02 18:02:05 +00:00
validated = identity . validate ( sig_input . read ( ) , data_input . read ( ) )
sig_input . close ( )
data_input . close ( )
if not validated :
if not args . stdout :
2024-10-07 08:44:18 +00:00
RNS . log ( f " Signature { args . validate } for file { args . read } is invalid " , RNS . LOG_ERROR )
2023-02-02 18:26:27 +00:00
exit ( 22 )
2023-02-02 18:02:05 +00:00
else :
if not args . stdout :
2024-10-07 08:44:18 +00:00
RNS . log ( f " Signature { args . validate } for file { args . read } made by Identity { identity } is valid " )
2023-02-02 18:02:05 +00:00
exit ( 0 )
except Exception as e :
if not args . stdout :
RNS . log ( " An error ocurred while validating signature. " , RNS . LOG_ERROR )
2024-10-07 08:44:18 +00:00
RNS . log ( f " The contained exception was: { e } " , RNS . LOG_ERROR )
2023-02-02 18:02:05 +00:00
try :
data_output . close ( )
except :
pass
try :
data_input . close ( )
except :
pass
2023-02-02 18:26:27 +00:00
exit ( 23 )
2023-02-02 18:02:05 +00:00
2023-02-02 16:45:59 +00:00
if args . encrypt :
if not data_input :
if not args . stdout :
RNS . log ( " Encryption requested, but no input data specified " , RNS . LOG_ERROR )
2023-02-02 18:26:27 +00:00
exit ( 24 )
2023-02-02 16:45:59 +00:00
else :
if not data_output :
if not args . stdout :
RNS . log ( " Encryption requested, but no output specified " , RNS . LOG_ERROR )
2023-02-02 18:26:27 +00:00
exit ( 25 )
2023-02-02 16:45:59 +00:00
if not args . stdout :
2024-10-07 08:44:18 +00:00
RNS . log ( f " Encrypting { args . read } " )
2023-02-02 16:45:59 +00:00
try :
more_data = True
while more_data :
chunk = data_input . read ( CHUNK_SIZE )
if chunk :
data_output . write ( identity . encrypt ( chunk ) )
else :
more_data = False
data_output . close ( )
data_input . close ( )
if not args . stdout :
if args . read :
2024-10-07 08:44:18 +00:00
RNS . log ( f " File { args . read } encrypted for { identity } to { args . write } " )
2023-02-02 16:45:59 +00:00
exit ( 0 )
except Exception as e :
if not args . stdout :
RNS . log ( " An error ocurred while encrypting data. " , RNS . LOG_ERROR )
2024-10-07 08:44:18 +00:00
RNS . log ( f " The contained exception was: { e } " , RNS . LOG_ERROR )
2023-02-02 16:45:59 +00:00
try :
data_output . close ( )
except :
pass
try :
data_input . close ( )
except :
pass
2023-02-02 18:26:27 +00:00
exit ( 26 )
2023-02-02 16:45:59 +00:00
if args . decrypt :
if identity . prv == None :
RNS . log ( " Specified Identity does not hold a private key. Cannot decrypt. " , RNS . LOG_ERROR )
2023-02-02 18:26:27 +00:00
exit ( 27 )
2023-02-02 16:45:59 +00:00
if not data_input :
if not args . stdout :
RNS . log ( " Decryption requested, but no input data specified " , RNS . LOG_ERROR )
2023-02-02 18:26:27 +00:00
exit ( 28 )
2023-02-02 16:45:59 +00:00
else :
if not data_output :
if not args . stdout :
RNS . log ( " Decryption requested, but no output specified " , RNS . LOG_ERROR )
2023-02-02 18:26:27 +00:00
exit ( 29 )
2023-02-02 16:45:59 +00:00
if not args . stdout :
2024-10-07 08:44:18 +00:00
RNS . log ( f " Decrypting { args . read } ... " )
2023-02-02 16:45:59 +00:00
try :
more_data = True
while more_data :
chunk = data_input . read ( CHUNK_SIZE )
if chunk :
plaintext = identity . decrypt ( chunk )
if plaintext == None :
if not args . stdout :
RNS . log ( " Data could not be decrypted with the specified Identity " )
2023-02-02 18:26:27 +00:00
exit ( 30 )
2023-02-02 16:45:59 +00:00
else :
data_output . write ( plaintext )
else :
more_data = False
data_output . close ( )
data_input . close ( )
if not args . stdout :
if args . read :
2024-10-07 08:44:18 +00:00
RNS . log ( f " File { args . read } decrypted with { identity } to { args . write } " )
2023-02-02 16:45:59 +00:00
exit ( 0 )
except Exception as e :
if not args . stdout :
RNS . log ( " An error ocurred while decrypting data. " , RNS . LOG_ERROR )
2024-10-07 08:44:18 +00:00
RNS . log ( f " The contained exception was: { e } " , RNS . LOG_ERROR )
2023-02-02 16:45:59 +00:00
try :
data_output . close ( )
except :
pass
try :
data_input . close ( )
except :
pass
2023-02-02 18:26:27 +00:00
exit ( 31 )
2023-02-02 16:45:59 +00:00
if True :
pass
elif False :
pass
else :
print ( " " )
parser . print_help ( )
print ( " " )
except KeyboardInterrupt :
print ( " " )
2023-02-02 18:26:27 +00:00
exit ( 255 )
2023-02-02 16:45:59 +00:00
if __name__ == " __main__ " :
main ( )