Last active
September 4, 2015 23:55
-
-
Save garcia-jj/c091baff8cd336cd9412 to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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); | |
} | |
} | |
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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