2022-01-11 13:46:05 +01:00
// SPDX-FileCopyrightText: 2021 Paul Schaub <vanitasvitae@fsfe.org>
//
// SPDX-License-Identifier: Apache-2.0
package sop.cli.picocli.commands ;
import java.io.File ;
import java.io.FileInputStream ;
import java.io.FileNotFoundException ;
import java.io.IOException ;
import java.util.ArrayList ;
import java.util.List ;
import picocli.CommandLine ;
import sop.Ready ;
2022-02-09 15:12:23 +01:00
import sop.cli.picocli.FileUtil ;
2022-01-11 13:46:05 +01:00
import sop.cli.picocli.SopCLI ;
import sop.enums.EncryptAs ;
import sop.exception.SOPGPException ;
import sop.operation.Encrypt ;
@CommandLine.Command ( name = " encrypt " ,
description = " Encrypt a message from standard input " ,
exitCodeOnInvalidInput = 37 )
2022-05-29 21:17:03 +02:00
public class EncryptCmd extends AbstractSopCmd {
2022-01-11 13:46:05 +01:00
@CommandLine.Option ( names = " --no-armor " ,
description = " ASCII armor the output " ,
negatable = true )
boolean armor = true ;
@CommandLine.Option ( names = { " --as " } ,
description = " Type of the input data. Defaults to 'binary' " ,
2022-05-29 21:17:03 +02:00
paramLabel = " {binary|text} " )
2022-01-11 13:46:05 +01:00
EncryptAs type ;
@CommandLine.Option ( names = " --with-password " ,
2022-02-09 15:12:23 +01:00
description = " Encrypt the message with a password provided by the given password file " ,
2022-01-11 13:46:05 +01:00
paramLabel = " PASSWORD " )
List < String > withPassword = new ArrayList < > ( ) ;
@CommandLine.Option ( names = " --sign-with " ,
description = " Sign the output with a private key " ,
paramLabel = " KEY " )
List < File > signWith = new ArrayList < > ( ) ;
2022-05-29 21:17:03 +02:00
@CommandLine.Option ( names = " --with-key-password " ,
description = " Provide indirect file type pointing at passphrase(s) for secret key(s) " ,
paramLabel = " PASSWORD " )
List < String > withKeyPassword = new ArrayList < > ( ) ;
2022-01-11 13:46:05 +01:00
@CommandLine.Parameters ( description = " Certificates the message gets encrypted to " ,
index = " 0..* " ,
paramLabel = " CERTS " )
List < File > certs = new ArrayList < > ( ) ;
@Override
public void run ( ) {
2022-05-29 21:17:03 +02:00
Encrypt encrypt = throwIfUnsupportedSubcommand (
SopCLI . getSop ( ) . encrypt ( ) , " encrypt " ) ;
2022-01-11 13:46:05 +01:00
if ( type ! = null ) {
try {
encrypt . mode ( type ) ;
} catch ( SOPGPException . UnsupportedOption unsupportedOption ) {
throw new SOPGPException . UnsupportedOption ( " Unsupported option '--as'. " , unsupportedOption ) ;
}
}
if ( withPassword . isEmpty ( ) & & certs . isEmpty ( ) ) {
2022-02-09 15:12:23 +01:00
throw new SOPGPException . MissingArg ( " At least one password file or cert file required for encryption. " ) ;
2022-01-11 13:46:05 +01:00
}
2022-02-09 15:12:23 +01:00
for ( String passwordFileName : withPassword ) {
2022-01-11 13:46:05 +01:00
try {
2022-02-09 15:12:23 +01:00
String password = FileUtil . stringFromInputStream ( FileUtil . getFileInputStream ( passwordFileName ) ) ;
2022-01-11 13:46:05 +01:00
encrypt . withPassword ( password ) ;
} catch ( SOPGPException . UnsupportedOption unsupportedOption ) {
throw new SOPGPException . UnsupportedOption ( " Unsupported option '--with-password'. " , unsupportedOption ) ;
2022-02-09 15:12:23 +01:00
} catch ( IOException e ) {
2022-02-09 23:35:44 +01:00
throw new RuntimeException ( e ) ;
2022-01-11 13:46:05 +01:00
}
}
2022-05-29 21:17:03 +02:00
for ( String passwordFileName : withKeyPassword ) {
try {
String password = FileUtil . stringFromInputStream ( FileUtil . getFileInputStream ( passwordFileName ) ) ;
encrypt . withKeyPassword ( password ) ;
} catch ( SOPGPException . UnsupportedOption unsupportedOption ) {
throw new SOPGPException . UnsupportedOption ( " Unsupported option '--with-key-password'. " , unsupportedOption ) ;
} catch ( IOException e ) {
throw new RuntimeException ( e ) ;
}
}
2022-01-11 13:46:05 +01:00
for ( File keyFile : signWith ) {
try ( FileInputStream keyIn = new FileInputStream ( keyFile ) ) {
encrypt . signWith ( keyIn ) ;
} catch ( FileNotFoundException e ) {
throw new SOPGPException . MissingInput ( " Key file " + keyFile . getAbsolutePath ( ) + " not found. " , e ) ;
} catch ( IOException e ) {
throw new RuntimeException ( e ) ;
} catch ( SOPGPException . KeyIsProtected keyIsProtected ) {
throw new SOPGPException . KeyIsProtected ( " Key from " + keyFile . getAbsolutePath ( ) + " is password protected. " , keyIsProtected ) ;
} catch ( SOPGPException . UnsupportedAsymmetricAlgo unsupportedAsymmetricAlgo ) {
throw new SOPGPException . UnsupportedAsymmetricAlgo ( " Key from " + keyFile . getAbsolutePath ( ) + " has unsupported asymmetric algorithm. " , unsupportedAsymmetricAlgo ) ;
} catch ( SOPGPException . KeyCannotSign keyCannotSign ) {
throw new SOPGPException . KeyCannotSign ( " Key from " + keyFile . getAbsolutePath ( ) + " cannot sign. " , keyCannotSign ) ;
} catch ( SOPGPException . BadData badData ) {
throw new SOPGPException . BadData ( " Key file " + keyFile . getAbsolutePath ( ) + " does not contain a valid OpenPGP private key. " , badData ) ;
}
}
for ( File certFile : certs ) {
try ( FileInputStream certIn = new FileInputStream ( certFile ) ) {
encrypt . withCert ( certIn ) ;
} catch ( FileNotFoundException e ) {
throw new SOPGPException . MissingInput ( " Certificate file " + certFile . getAbsolutePath ( ) + " not found. " , e ) ;
} catch ( IOException e ) {
throw new RuntimeException ( e ) ;
} catch ( SOPGPException . UnsupportedAsymmetricAlgo unsupportedAsymmetricAlgo ) {
throw new SOPGPException . UnsupportedAsymmetricAlgo ( " Certificate from " + certFile . getAbsolutePath ( ) + " has unsupported asymmetric algorithm. " , unsupportedAsymmetricAlgo ) ;
} catch ( SOPGPException . CertCannotEncrypt certCannotEncrypt ) {
throw new SOPGPException . CertCannotEncrypt ( " Certificate from " + certFile . getAbsolutePath ( ) + " is not capable of encryption. " , certCannotEncrypt ) ;
} catch ( SOPGPException . BadData badData ) {
throw new SOPGPException . BadData ( " Certificate file " + certFile . getAbsolutePath ( ) + " does not contain a valid OpenPGP certificate. " , badData ) ;
}
}
if ( ! armor ) {
encrypt . noArmor ( ) ;
}
try {
Ready ready = encrypt . plaintext ( System . in ) ;
ready . writeTo ( System . out ) ;
} catch ( IOException e ) {
throw new RuntimeException ( e ) ;
}
}
}