Skip to content

Instantly share code, notes, and snippets.

@garcia-jj
Last active September 4, 2015 23:55
Show Gist options
  • Save garcia-jj/c091baff8cd336cd9412 to your computer and use it in GitHub Desktop.
Save garcia-jj/c091baff8cd336cd9412 to your computer and use it in GitHub Desktop.
package ot.security;
import static java.util.Objects.requireNonNull;
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.security.InvalidKeyException;
import java.security.KeyFactory;
import java.security.KeyPair;
import java.security.KeyPairGenerator;
import java.security.NoSuchAlgorithmException;
import java.security.NoSuchProviderException;
import java.security.PrivateKey;
import java.security.PublicKey;
import java.security.SecureRandom;
import java.security.Signature;
import java.security.SignatureException;
import java.security.spec.InvalidKeySpecException;
import java.security.spec.PKCS8EncodedKeySpec;
import java.security.spec.X509EncodedKeySpec;
public class FileSignature {
public static class EncryptionOperationNotPossibleException extends RuntimeException {
public EncryptionOperationNotPossibleException(String message, Throwable cause) {
super(message, cause);
}
public EncryptionOperationNotPossibleException(Throwable cause) {
super(cause);
}
}
private static final String BOUNCY_CASTLE_PROVIDER = "BC";
private static final String KEY_ALGORITHM = "RSA";
private static final String SIGNATURE_ALGORITHM = "SHA1withRSA";
public static KeyPair createKeys(Path privateKeyFile, Path publicKeyFile) {
requireNonNull(privateKeyFile, "Private key file can't be null");
requireNonNull(publicKeyFile, "Public key file can't be null");
try {
final KeyPairGenerator keyGen = KeyPairGenerator.getInstance(KEY_ALGORITHM, BOUNCY_CASTLE_PROVIDER);
keyGen.initialize(2048, new SecureRandom());
final KeyPair keyPair = keyGen.generateKeyPair();
final PKCS8EncodedKeySpec pkcs8EncodedKeySpec = new PKCS8EncodedKeySpec(keyPair.getPrivate().getEncoded());
Files.write(privateKeyFile, pkcs8EncodedKeySpec.getEncoded());
final X509EncodedKeySpec x509EncodedKeySpec = new X509EncodedKeySpec(keyPair.getPublic().getEncoded());
Files.write(publicKeyFile, x509EncodedKeySpec.getEncoded());
return keyPair;
} catch (NoSuchAlgorithmException | NoSuchProviderException e) {
throw new EncryptionOperationNotPossibleException(e);
} catch (IOException e) {
throw new EncryptionOperationNotPossibleException(e);
}
}
public static PrivateKey loadPrivateKey(Path privateKeyFile) {
requireNonNull(privateKeyFile, "Private key file can't be null");
try {
final KeyFactory keyFactory = KeyFactory.getInstance(KEY_ALGORITHM, BOUNCY_CASTLE_PROVIDER);
final byte[] encodedPrivateKey = Files.readAllBytes(privateKeyFile);
final PKCS8EncodedKeySpec privateKeySpec = new PKCS8EncodedKeySpec(encodedPrivateKey);
return keyFactory.generatePrivate(privateKeySpec);
} catch (InvalidKeySpecException e) {
throw new EncryptionOperationNotPossibleException(e);
} catch (NoSuchAlgorithmException | NoSuchProviderException e) {
throw new EncryptionOperationNotPossibleException(e);
} catch (IOException e) {
throw new EncryptionOperationNotPossibleException(e);
}
}
public static PublicKey loadPublicKey(Path publicKeyFile) {
requireNonNull(publicKeyFile, "Public key file can't be null");
try {
final KeyFactory keyFactory = KeyFactory.getInstance(KEY_ALGORITHM, BOUNCY_CASTLE_PROVIDER);
final byte[] encodedPublicKey = Files.readAllBytes(publicKeyFile);
final X509EncodedKeySpec publicKeySpec = new X509EncodedKeySpec(encodedPublicKey);
return keyFactory.generatePublic(publicKeySpec);
} catch (InvalidKeySpecException e) {
throw new EncryptionOperationNotPossibleException(e);
} catch (NoSuchAlgorithmException | NoSuchProviderException e) {
throw new EncryptionOperationNotPossibleException(e);
} catch (IOException e) {
throw new EncryptionOperationNotPossibleException(e);
}
}
public static boolean checkSignature(Path file, PublicKey publicKey, Path signatureFile) {
requireNonNull(file, "Input file can't be null");
requireNonNull(publicKey, "Public key file can't be null");
requireNonNull(signatureFile, "Signature file file can't be null");
try {
final Signature sig = Signature.getInstance(SIGNATURE_ALGORITHM, BOUNCY_CASTLE_PROVIDER);
sig.initVerify(publicKey);
final byte[] fileToCheck = Files.readAllBytes(file);
sig.update(fileToCheck);
final byte[] sigToVerify = Files.readAllBytes(signatureFile);
return sig.verify(sigToVerify);
} catch (InvalidKeyException | SignatureException e) {
throw new EncryptionOperationNotPossibleException(e);
} catch (NoSuchAlgorithmException | NoSuchProviderException e) {
throw new EncryptionOperationNotPossibleException(e);
} catch (IOException e) {
throw new EncryptionOperationNotPossibleException(e);
}
}
public static Path createSignature(Path file, PrivateKey privateKey) {
requireNonNull(file, "Input file can't be null");
requireNonNull(privateKey, "Private key file can't be null");
try {
final Signature dsa = Signature.getInstance(SIGNATURE_ALGORITHM, BOUNCY_CASTLE_PROVIDER);
dsa.initSign(privateKey);
final byte[] fileContent = Files.readAllBytes(file);
dsa.update(fileContent);
final Path signatureFile = file.resolveSibling(file.toString() + ".signature");
Files.write(signatureFile, dsa.sign());
return signatureFile;
} catch (InvalidKeyException | SignatureException e) {
throw new EncryptionOperationNotPossibleException(e);
} catch (NoSuchAlgorithmException | NoSuchProviderException e) {
throw new EncryptionOperationNotPossibleException(e);
} catch (IOException e) {
throw new EncryptionOperationNotPossibleException(e);
}
}
}
package ot.security;
import static org.hamcrest.Matchers.equalTo;
import static org.hamcrest.Matchers.is;
import static org.junit.Assert.assertThat;
import java.nio.charset.StandardCharsets;
import java.nio.file.Files;
import java.nio.file.Path;
import java.security.KeyPair;
import java.security.PrivateKey;
import java.security.PublicKey;
import java.util.UUID;
import org.junit.Before;
import org.junit.Rule;
import org.junit.Test;
import org.junit.rules.TemporaryFolder;
public class FileSignatureTest {
@Rule
public TemporaryFolder folder = new TemporaryFolder();
private Path file;
private Path privateKeyFile;
private Path publicKeyFile;
@Before
public void setup()
throws Exception {
file = folder.newFile().toPath();
Files.write(file, UUID.randomUUID().toString().getBytes(StandardCharsets.UTF_8));
privateKeyFile = file.resolveSibling("test.priv.pkcs8");
publicKeyFile = file.resolveSibling("test.pub.x509");
}
@Test
public void testKeyPairStored() {
KeyPair keyPair = FileSignature.createKeys(privateKeyFile, publicKeyFile);
PrivateKey privateKey = keyPair.getPrivate();
PublicKey publicKey = keyPair.getPublic();
PrivateKey privateKeyStored = FileSignature.loadPrivateKey(privateKeyFile);
PublicKey publicKeyStored = FileSignature.loadPublicKey(publicKeyFile);
assertThat(privateKey.getEncoded(), equalTo(privateKeyStored.getEncoded()));
assertThat(publicKey.getEncoded(), equalTo(publicKeyStored.getEncoded()));
}
@Test
public void testSignature() {
KeyPair keyPair = FileSignature.createKeys(privateKeyFile, publicKeyFile);
Path signatureFile = FileSignature.createSignature(file, keyPair.getPrivate());
boolean valid = FileSignature.checkSignature(file, keyPair.getPublic(), signatureFile);
assertThat(valid, is(true));
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment