import com.xenomachina.argparser.ArgParser import com.xenomachina.argparser.default import com.xenomachina.argparser.mainBody import org.fusesource.jansi.internal.CLibrary.STDIN_FILENO import org.fusesource.jansi.internal.CLibrary.isatty import java.nio.charset.Charset import java.security.MessageDigest import kotlin.system.exitProcess class Args(parser: ArgParser) { val encrypt by parser.flagging("-e", "--encrypt", help = "Encrypt stdin instead of decrypting") val keyExchange by parser .storing("-k", "--key-exchange", help = "Key-Exchange header value, required if nonce is not provided") .default(null) val cloudPassword by parser .storing("-p", "--password", help = "Cloud password, if camera has been provisioned") .default(null) val username by parser .storing("-u", "--username", help = "User name, either admin or none. Default admin") .default("admin") val nonce by parser .storing("-n", "--nonce", help = "Nonce, required if key-exchange is not provided") .default(null) } fun main(args: Array) = mainBody { ArgParser(args).parseInto(::Args).run { if (keyExchange == null && nonce == null) { System.err.println("Either the Key-Exchange or the nonce must be provided!") exitProcess(1) } if (cloudPassword == null) { System.err.println("Cloud password not provided, using the default one for unprovisioned cameras") } if (isatty(STDIN_FILENO) == 1) { System.err.println("Data to ${if (encrypt) "encrypt" else "decrypt"} must be sent to standard input!") exitProcess(1) } val toProcess = System.`in`.readAllBytesCompat() if (toProcess == null) { System.err.println("Unable to read data from stdin!") exitProcess(1) } val hashedPassword: String? = cloudPassword?.let { MessageDigest .getInstance("MD5") .apply { update(it.toByteArray(Charset.forName("UTF-8"))) } .digest() .toHexString() } val aes = if (keyExchange != null) { StreamAesUtils.generateFromExchangeKeyAndSuperSecretKey(keyExchange, hashedPassword) } else { StreamAesUtils.fromUserNonceSuperSecretKey(username, nonce, hashedPassword) } val output = if (encrypt) { aes.encrypt(toProcess) } else { aes.decrypt(toProcess) } System.out.write(output) } }