본문 바로가기
내가만드는것_만든것/오픈소스

AsymSecureFile

by Joseph.Lee 2019. 7. 12.

(설명 추가중... 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

 

jc-lab/javautils-asymsecurefile

Contribute to jc-lab/javautils-asymsecurefile development by creating an account on GitHub.

github.com

https://bintray.com/jc-lab/java-utils/asymsecurefile

 

Package asymsecurefile - jc-lab

 

bintray.com

 

테스트코드 : 

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();
    }
}
반응형

댓글