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.FileOutputStream ;
import java.io.IOException ;
import java.util.ArrayList ;
import java.util.List ;
import picocli.CommandLine ;
import sop.MicAlg ;
import sop.ReadyWithResult ;
import sop.SigningResult ;
2022-05-24 22:09:49 +02:00
import sop.cli.picocli.FileUtil ;
2022-01-11 13:46:05 +01:00
import sop.cli.picocli.Print ;
import sop.cli.picocli.SopCLI ;
import sop.enums.SignAs ;
import sop.exception.SOPGPException ;
import sop.operation.Sign ;
@CommandLine.Command ( name = " sign " ,
description = " Create a detached signature on the data from standard input " ,
exitCodeOnInvalidInput = 37 )
2022-05-29 21:17:03 +02:00
public class SignCmd extends AbstractSopCmd {
2022-05-24 22:09:49 +02:00
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 = " Defaults to 'binary'. If '--as=text' and the input data is not valid UTF-8, sign fails with return code 53. " ,
paramLabel = " {binary|text} " )
SignAs type ;
@CommandLine.Parameters ( description = " Secret keys used for signing " ,
paramLabel = " KEYS " )
List < File > secretKeyFile = new ArrayList < > ( ) ;
2022-05-24 21:55:35 +02:00
@CommandLine.Option ( names = " --with-key-password " , description = " Password(s) to unlock the secret key(s) with " ,
paramLabel = " PASSWORD " )
List < String > withKeyPassword = new ArrayList < > ( ) ;
2022-01-11 13:46:05 +01:00
@CommandLine.Option ( names = " --micalg-out " , description = " Emits the digest algorithm used to the specified file in a way that can be used to populate the micalg parameter for the PGP/MIME Content-Type (RFC3156) " ,
paramLabel = " MICALG " )
File micAlgOut ;
@Override
public void run ( ) {
2022-05-29 21:17:03 +02:00
Sign sign = throwIfUnsupportedSubcommand (
SopCLI . getSop ( ) . sign ( ) , " sign " ) ;
throwIfOutputExists ( micAlgOut , " --micalg-out " ) ;
throwIfEmptyParameters ( secretKeyFile , " KEYS " ) ;
2022-01-11 13:46:05 +01:00
if ( type ! = null ) {
try {
sign . mode ( type ) ;
} catch ( SOPGPException . UnsupportedOption unsupportedOption ) {
Print . errln ( " Unsupported option '--as' " ) ;
Print . trace ( unsupportedOption ) ;
System . exit ( unsupportedOption . getExitCode ( ) ) ;
}
}
2022-05-24 22:09:49 +02:00
for ( String passwordFile : withKeyPassword ) {
try {
String password = FileUtil . stringFromInputStream ( FileUtil . getFileInputStream ( passwordFile ) ) ;
sign . withKeyPassword ( password ) ;
} catch ( SOPGPException . UnsupportedOption unsupportedOption ) {
throw new SOPGPException . UnsupportedOption ( String . format ( ERROR_UNSUPPORTED_OPTION , " --with-key-password " ) , unsupportedOption ) ;
} catch ( IOException e ) {
throw new RuntimeException ( e ) ;
}
2022-05-24 21:55:35 +02:00
}
2022-01-11 13:46:05 +01:00
for ( File keyFile : secretKeyFile ) {
try ( FileInputStream keyIn = new FileInputStream ( keyFile ) ) {
sign . key ( keyIn ) ;
} catch ( FileNotFoundException e ) {
Print . errln ( " File " + keyFile . getAbsolutePath ( ) + " does not exist. " ) ;
Print . trace ( e ) ;
System . exit ( 1 ) ;
} catch ( IOException e ) {
Print . errln ( " Cannot access file " + keyFile . getAbsolutePath ( ) ) ;
Print . trace ( e ) ;
System . exit ( 1 ) ;
} catch ( SOPGPException . KeyIsProtected e ) {
Print . errln ( " Key " + keyFile . getName ( ) + " is password protected. " ) ;
Print . trace ( e ) ;
System . exit ( 1 ) ;
} catch ( SOPGPException . BadData badData ) {
Print . errln ( " Bad data in key file " + keyFile . getAbsolutePath ( ) + " : " ) ;
Print . trace ( badData ) ;
System . exit ( badData . getExitCode ( ) ) ;
}
}
if ( ! armor ) {
sign . noArmor ( ) ;
}
try {
ReadyWithResult < SigningResult > ready = sign . data ( System . in ) ;
SigningResult result = ready . writeTo ( System . out ) ;
MicAlg micAlg = result . getMicAlg ( ) ;
if ( micAlgOut ! = null ) {
// Write micalg out
micAlgOut . createNewFile ( ) ;
FileOutputStream micAlgOutStream = new FileOutputStream ( micAlgOut ) ;
micAlg . writeTo ( micAlgOutStream ) ;
micAlgOutStream . close ( ) ;
}
} catch ( IOException e ) {
Print . errln ( " IO Error. " ) ;
Print . trace ( e ) ;
System . exit ( 1 ) ;
} catch ( SOPGPException . ExpectedText expectedText ) {
Print . errln ( " Expected text input, but got binary data. " ) ;
Print . trace ( expectedText ) ;
System . exit ( expectedText . getExitCode ( ) ) ;
}
}
}