(설명 추가중... github에 써야하는데...)
AsymSecureFile은 Asymmetric기반 암호화를 이용하여 데이터 Sign/Encrypt를 구현하는 Java 라이브러리 입니다.
(추후 C++도 지원예정)
OperationType으로써 SIGN과 PUBLIC_ENCRYPT를 지원하며 RSA키와 EC키를 지원하고, Java에서는 PKCS11도 지원하여 HSM과 연동 가능합니다.
SIGN은 PrivateKey로 데이터를 서명하며 이를 통해 데이터를 조작불가하게 전달하고 보관할 수 있습니다. 라이센스 검증 등에 유용하게 사용할 수 있습니다.
PUBLIC_ENCRYPT는 PublicKey로 데이터를 암호화하여 데이터를 안전하게 전달하고 PrivateKey를 가진 자만 해당 데이터를 읽을 수 있습니다.
AuthKey를 적용하여 데이터 암호화도 함께 작동합니다.
UserChunk라는 것은 사용자 정의 데이터를 추가할 수 있습니다. 해당 데이터는 기본적으로 암호화하지 않고 Read하는 쪽에서 AsymKey를 설정하지 않은 상태에서도 읽을 수 있습니다.
비 암호화 / AuthKey로 암호화 옵션을 가지고 있으며, AuthKey로 암호화할 시 UserChunk를 보다 안전하게 전달 할 수 있습니다.
jcenter() repository에서 'kr.jclab.javautils:asymsecurefile:1.1.4' 으로 사용하실 수 있습니다.
(1.1.4 버전이후 최신걸 사용해 주세요~)
전에 만들었던 signedsecurefile도 하위 호환성을 위해 지원합니다. (읽기만)
https://github.com/jc-lab/javautils-asymsecurefile
https://bintray.com/jc-lab/java-utils/asymsecurefile
테스트코드 :
import kr.jclab.javautils.asymsecurefile.*;
import kr.jclab.javautils.signedsecurefile.InvalidKeyException;
import org.bouncycastle.jce.provider.BouncyCastleProvider;
import sun.security.pkcs11.SunPKCS11;
import javax.crypto.Cipher;
import javax.crypto.KeyAgreement;
import javax.crypto.spec.GCMParameterSpec;
import javax.crypto.spec.SecretKeySpec;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.security.*;
import java.security.cert.Certificate;
import java.security.cert.CertificateException;
import java.util.Arrays;
import java.util.Enumeration;
public class TestMain {
public static String bytesToHex(byte[] bytes) {
final char hexArray[] = "0123456789abcdef".toCharArray();
StringBuilder stringBuilder = new StringBuilder();
for ( int j = 0; j < bytes.length; j++ ) {
int v = bytes[j] & 0xFF;
if(stringBuilder.length() > 0)
stringBuilder.append(",");
stringBuilder.append("0x");
stringBuilder.append(hexArray[v >>> 4]);
stringBuilder.append(hexArray[v & 0xf]);
}
return stringBuilder.toString();
}
public static void pkcs11Test() throws Exception {
Security.insertProviderAt(new BouncyCastleProvider(), 1);
SunPKCS11 securityProvider = new SunPKCS11("D:\\SoftHSM2\\java-softhsm.cfg");
KeyStore keyStore = KeyStore.getInstance("PKCS11", securityProvider);
keyStore.load(null, "123456".toCharArray());
Certificate certificate = keyStore.getCertificate("test-1");
Key key = keyStore.getKey("test-1", null);
// RSA Test
//KeyPairGenerator keyPairGenerator = KeyPairGenerator.getInstance(AsymAlgorithm.RSA.getAlgorithm(), securityProvider);
//KeyPairGenerator keyPairGenerator = KeyPairGenerator.getInstance(AsymAlgorithm.RSA.getAlgorithm());
//keyPairGenerator.initialize(1024);
// EC Test
//KeyPairGenerator keyPairGenerator = KeyPairGenerator.getInstance(AsymAlgorithm.EC.getAlgorithm(), securityProvider);
//KeyPairGenerator keyPairGenerator = KeyPairGenerator.getInstance(AsymAlgorithm.EC.getAlgorithm());
//keyPairGenerator.initialize(256);
//KeyPair keyPair = keyPairGenerator.generateKeyPair();
KeyPair keyPair = new KeyPair(certificate.getPublicKey(), (PrivateKey)key);
//Key storedKey = keyStore.getKey("test-ec-1", null);
ByteArrayOutputStream bos = new ByteArrayOutputStream();
/*
// SignedSecureFileOutputStream test
try(SignedSecureFileOutputStream outputStream = new SignedSecureFileOutputStream(bos, keyPair.getPrivate(), "TEST")) {
for (int i = 0; i < 10000; i++) {
byte[] buf = new byte[] {10};
outputStream.write(buf);
}
outputStream.save();
}
*/
// AsymSecureFileOutputStream test
try(AsymSecureFileOutputStream outputStream = new AsymSecureFileOutputStream(OperationType.PUBLIC_ENCRYPT, bos, securityProvider)) {
outputStream.setAsymKey(keyPair);
outputStream.setAuthKey("TEST".getBytes());
outputStream.setUserChunk(
UserChunk.builder()
.withUserCode((short)1)
.withFlag(Chunk.Flag.EncryptedWithAuthEncKey)
.withData(new byte[] {0x10, 0x20, 0x30, 0x40, 0x50,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2})
.build());
for (int i = 0; i < 5766; i++) {
outputStream.write(10);
}
outputStream.finish();
}
byte[] payload = bos.toByteArray();
try(AsymSecureFileInputStream inputStream = new AsymSecureFileInputStream(new ByteArrayInputStream(payload), securityProvider))
{
while(inputStream.headerRead() == 1)
{
System.out.println("continous head reading");
}
inputStream.setAuthKey("TEST".getBytes());
inputStream.setAsymKey(keyPair);
Enumeration<UserChunk> enumeration = inputStream.userChunks();
while (enumeration.hasMoreElements()) {
UserChunk userChunk = enumeration.nextElement();
System.out.println("userChunk : " + userChunk + " / " + userChunk.getDataSize() + " / " + bytesToHex(userChunk.getData()));
}
int readlen;
byte[] buffer = new byte[8192];
while((readlen = inputStream.read(buffer)) > 0) {
System.out.println("READLEN : " + readlen + " // " + bytesToHex(Arrays.copyOf(buffer, readlen)));
}
}
System.out.println("PAYLOAD : " + bytesToHex(payload));
securityProvider.logout();
}
public static void normalTest() throws Exception {
Provider securityProvider = new BouncyCastleProvider();
// RSA Test
//KeyPairGenerator keyPairGenerator = KeyPairGenerator.getInstance(AsymAlgorithm.RSA.getAlgorithm(), securityProvider);
KeyPairGenerator keyPairGenerator = KeyPairGenerator.getInstance(AsymAlgorithm.RSA.getAlgorithm());
keyPairGenerator.initialize(1024);
// EC Test
//KeyPairGenerator keyPairGenerator = KeyPairGenerator.getInstance(AsymAlgorithm.EC.getAlgorithm(), securityProvider);
//KeyPairGenerator keyPairGenerator = KeyPairGenerator.getInstance(AsymAlgorithm.EC.getAlgorithm());
//keyPairGenerator.initialize(256);
KeyPair keyPair = keyPairGenerator.generateKeyPair();
//Key storedKey = keyStore.getKey("test-ec-1", null);
ByteArrayOutputStream bos = new ByteArrayOutputStream();
/*
// SignedSecureFileOutputStream test
try(SignedSecureFileOutputStream outputStream = new SignedSecureFileOutputStream(bos, keyPair.getPrivate(), "TEST")) {
for (int i = 0; i < 10000; i++) {
byte[] buf = new byte[] {10};
outputStream.write(buf);
}
outputStream.save();
}
*/
// AsymSecureFileOutputStream test
try(AsymSecureFileOutputStream outputStream = new AsymSecureFileOutputStream(OperationType.SIGN, bos, securityProvider)) {
outputStream.setAsymKey(keyPair);
outputStream.setAuthKey("TEST".getBytes());
outputStream.setUserChunk(
UserChunk.builder()
.withFlag(Chunk.Flag.EncryptedWithAuthEncKey)
.withData(new byte[] {0x10, 0x20, 0x30, 0x40, 0x50})
.build());
for (int i = 0; i < 10000; i++) {
outputStream.write(10);
}
outputStream.finish();
}
byte[] payload = bos.toByteArray();
try(AsymSecureFileInputStream inputStream = new AsymSecureFileInputStream(new ByteArrayInputStream(payload), securityProvider))
{
while(inputStream.headerRead() == 1)
{
System.out.println("continous head reading");
}
inputStream.setAuthKey("TEST".getBytes());
inputStream.setAsymKey(keyPair);
Enumeration<UserChunk> enumeration = inputStream.userChunks();
while (enumeration.hasMoreElements()) {
UserChunk userChunk = enumeration.nextElement();
System.out.println("userChunk : " + userChunk + " / " + userChunk.getDataSize() + " / " + bytesToHex(userChunk.getData()));
}
int readlen;
byte[] buffer = new byte[8192];
while((readlen = inputStream.read(buffer)) > 0) {
System.out.println("READLEN : " + readlen + " // " + bytesToHex(Arrays.copyOf(buffer, readlen)));
}
}
System.out.println("PublicKey : " + bytesToHex(keyPair.getPublic().getEncoded()));
System.out.println("PrivateKey : " + bytesToHex(keyPair.getPrivate().getEncoded()));
System.out.println("PAYLOAD : " + bytesToHex(payload));
}
public static void keyGen() throws Exception {
KeyPairGenerator keyPairGenerator = KeyPairGenerator.getInstance("EC");
KeyPair keyPairA = keyPairGenerator.generateKeyPair();
KeyPair keyPairB = keyPairGenerator.generateKeyPair();
System.out.println("A PUBLIC : " + bytesToHex(keyPairA.getPublic().getEncoded()));
System.out.println("A PRIVATE : " + bytesToHex(keyPairA.getPrivate().getEncoded()));
System.out.println("B PUBLIC : " + bytesToHex(keyPairB.getPublic().getEncoded()));
System.out.println("B PRIVATE : " + bytesToHex(keyPairB.getPrivate().getEncoded()));
KeyAgreement keyAgreement = KeyAgreement.getInstance("ECDH");
keyAgreement.init(keyPairA.getPrivate());
Key key = keyAgreement.doPhase(keyPairB.getPublic(), true);
//System.out.println("ENCODED : " + bytesToHex(key.getEncoded()));
System.out.println("SECRET : " + bytesToHex(keyAgreement.generateSecret()));
}
public static void main(String[] args) throws Exception {
//pkcs11Test();
normalTest();
//keyGen();
}
}
'내가만드는것_만든것 > 오픈소스' 카테고리의 다른 글
[jshttpserver-uvw] C++ & libuv & uvw 웹서버 (0) | 2019.09.18 |
---|---|
JCP (JsCryptoProvider) C++에서 Java의 SecurityProvider같은거 (0) | 2019.07.22 |
c++ stomp 프로토콜 구현 (0) | 2019.07.08 |
sqlcipher 에서 mbedtls 사용하기 (0) | 2019.05.08 |
[JsCPPBean] C++에서 Java Bean 구현하는 라이브러리 (0) | 2019.04.12 |
댓글