2020-12-16 20:09:01 +01:00
/ *
* Copyright 2020 Paul Schaub .
*
* Licensed under the Apache License , Version 2 . 0 ( the " License " ) ;
* you may not use this file except in compliance with the License .
* You may obtain a copy of the License at
*
* http : //www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing , software
* distributed under the License is distributed on an " AS IS " BASIS ,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND , either express or implied .
* See the License for the specific language governing permissions and
* limitations under the License .
* /
2020-11-26 11:00:48 +01:00
package org.pgpainless.sop.commands ;
import org.bouncycastle.openpgp.PGPException ;
import org.bouncycastle.openpgp.PGPSecretKeyRing ;
import org.bouncycastle.openpgp.PGPSignature ;
import org.bouncycastle.util.io.Streams ;
import org.pgpainless.PGPainless ;
2020-12-16 16:43:58 +01:00
import org.pgpainless.encryption_signing.EncryptionBuilderInterface ;
2020-11-26 11:00:48 +01:00
import org.pgpainless.encryption_signing.EncryptionStream ;
import org.pgpainless.key.protection.UnprotectedKeysProtector ;
import org.pgpainless.sop.Print ;
import picocli.CommandLine ;
2020-12-22 22:08:38 +01:00
import java.io.ByteArrayOutputStream ;
import java.io.File ;
import java.io.FileInputStream ;
import java.io.IOException ;
2020-12-16 20:09:01 +01:00
import static org.pgpainless.sop.Print.err_ln ;
import static org.pgpainless.sop.Print.print_ln ;
2020-12-22 22:07:13 +01:00
@CommandLine.Command ( name = " sign " , description = " Create a detached signature " )
2020-11-26 11:00:48 +01:00
public class Sign implements Runnable {
public enum Type {
binary ,
text
}
2020-12-22 22:05:47 +01:00
@CommandLine.Option ( names = " --no-armor " ,
description = " ASCII armor the output " ,
negatable = true )
boolean armor = true ;
2020-11-26 11:00:48 +01:00
2020-12-16 20:09:01 +01:00
@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. " ,
2020-12-22 22:08:38 +01:00
paramLabel = " {binary|text} " )
2020-11-26 11:00:48 +01:00
Type type ;
2020-12-22 22:08:38 +01:00
@CommandLine.Parameters ( description = " Secret keys used for signing " ,
paramLabel = " KEY " ,
arity = " 1..* " )
File [ ] secretKeyFile ;
2020-11-26 11:00:48 +01:00
@Override
public void run ( ) {
2020-12-22 22:08:38 +01:00
PGPSecretKeyRing [ ] secretKeys = new PGPSecretKeyRing [ secretKeyFile . length ] ;
for ( int i = 0 , secretKeyFileLength = secretKeyFile . length ; i < secretKeyFileLength ; i + + ) {
File file = secretKeyFile [ i ] ;
try {
PGPSecretKeyRing secretKey = PGPainless . readKeyRing ( ) . secretKeyRing ( new FileInputStream ( file ) ) ;
secretKeys [ i ] = secretKey ;
} catch ( IOException | PGPException e ) {
err_ln ( " Error reading secret key ring " + file . getName ( ) ) ;
err_ln ( e . getMessage ( ) ) ;
System . exit ( 1 ) ;
return ;
}
2020-11-26 11:00:48 +01:00
}
try {
2020-12-16 16:43:58 +01:00
ByteArrayOutputStream out = new ByteArrayOutputStream ( ) ;
EncryptionBuilderInterface . DocumentType documentType = PGPainless . encryptAndOrSign ( )
. onOutputStream ( out )
. doNotEncrypt ( )
. createDetachedSignature ( )
. signWith ( new UnprotectedKeysProtector ( ) , secretKeys ) ;
2020-12-22 22:05:47 +01:00
EncryptionBuilderInterface . Armor builder = type = = Type . text ? documentType . signCanonicalText ( ) : documentType . signBinaryDocument ( ) ;
EncryptionStream encryptionStream = armor ? builder . asciiArmor ( ) : builder . noArmor ( ) ;
2020-11-26 11:00:48 +01:00
Streams . pipeAll ( System . in , encryptionStream ) ;
encryptionStream . close ( ) ;
PGPSignature signature = encryptionStream . getResult ( ) . getSignatures ( ) . iterator ( ) . next ( ) ;
2020-12-22 22:05:47 +01:00
print_ln ( Print . toString ( signature . getEncoded ( ) , armor ) ) ;
2020-11-26 11:00:48 +01:00
} catch ( PGPException | IOException e ) {
2020-12-16 20:09:01 +01:00
err_ln ( " Error signing data. " ) ;
err_ln ( e . getMessage ( ) ) ;
2020-11-26 11:00:48 +01:00
System . exit ( 1 ) ;
}
}
}