지돌이의 블로그 입니다!

Test Code:

import sun.security.pkcs11.SunPKCS11;
import sun.security.pkcs11.wrapper.PKCS11;
import sun.security.pkcs11.wrapper.PKCS11Exception;

import javax.crypto.Cipher;
import javax.crypto.KeyGenerator;
import javax.crypto.SecretKey;
import javax.security.auth.login.FailedLoginException;
import java.io.IOException;
import java.security.Key;
import java.security.KeyStore;
import java.security.UnrecoverableKeyException;

public class TestMain {
    public static void main(String[] args) throws Exception {
        TestMain app = new TestMain();
        app.run();
    }

    private boolean checkFailedLoginException(Throwable e){
        if(e instanceof FailedLoginException) {
            return true;
        }
        if(e.getCause() != null) {
            return checkFailedLoginException(e.getCause());
        }
        return false;
    }

    String dumpbin(byte[] input) {
        StringBuilder sb = new StringBuilder();
        for(byte a : input) {
            sb.append(String.format("%02x ", a & 0xff));
        }
        return sb.toString();
    }

    void run() throws Exception {
        SunPKCS11 p11Provider = new SunPKCS11("G:\\java-etoken-0.cfg");
        KeyStore keyStore = KeyStore.getInstance("PKCS11", p11Provider);
        try {
            keyStore.load(null, "P@ssw0rd".toCharArray());
        }catch (IOException loadException){
            if(checkFailedLoginException(loadException)) {
                System.err.println("LOGIN FAILED");
                return ;
            }else{
                throw loadException;
            }
        }

        Key key = keyStore.getKey("test-aes-1", null);
        System.out.println("key => " + key.getAlgorithm() + " / " + key.getFormat() + " / " + key);

        for(int i=0; i<4; i++) {
            long begin = System.nanoTime();
            Cipher cipher = Cipher.getInstance("AES/CBC/NoPadding", p11Provider);
            cipher.init(Cipher.ENCRYPT_MODE, key);
            System.out.println("IV => " + dumpbin(cipher.getIV()));
            byte[] out = cipher.doFinal("0123456789abcdef0123456789abcdef".getBytes());
            System.out.println("IV => " + dumpbin(cipher.getIV()));
            long end = System.nanoTime();
            long diff = end - begin;
            System.out.println("DIFF = " + (((double) diff) / 1000000));
            System.out.println("dumpbin => " + out.length + " / " + dumpbin(out));
        }
    }
}

결과

key => AES / null / SunPKCS11-eToken AES secret key, 0 bits (id 236257286, token object, not sensitive, unextractable)
IV => 5f 89 21 65 63 56 05 2f 30 74 16 bd ed c3 53 48 
IV => 5f 89 21 65 63 56 05 2f 30 74 16 bd ed c3 53 48 
DIFF = 4196.6191
dumpbin => 32 / db e4 66 14 9f ff e8 23 8e 82 f4 0b f7 21 8a 70 f3 ef 6d a0 90 14 48 2d 7f 8b 91 9c a7 21 3f 95 
IV => 0e a3 14 ff 4c 80 94 5f 7a f0 dd b4 37 cf bc b5 
IV => 0e a3 14 ff 4c 80 94 5f 7a f0 dd b4 37 cf bc b5 
DIFF = 3.1933
dumpbin => 32 / c4 23 3c 93 8d f7 b4 8a 66 fb 8c 82 b5 27 b3 54 b4 df 8f 32 39 dc 5e 3a 93 db a4 55 5e 39 d4 f1 
IV => 40 49 64 32 f9 bd d4 43 65 eb 44 bc 9f 5d b9 c2 
IV => 40 49 64 32 f9 bd d4 43 65 eb 44 bc 9f 5d b9 c2 
DIFF = 2.836
dumpbin => 32 / ac 9c e5 68 da a4 f7 bd 4f d4 40 40 d0 c7 c0 20 90 b6 49 fb 9b 87 ac 80 3a 28 b6 75 38 8e 71 5f 
IV => c9 65 8c f3 06 80 80 5d 86 ff 85 55 44 9c 68 d6 
IV => c9 65 8c f3 06 80 80 5d 86 ff 85 55 44 9c 68 d6 
DIFF = 2.9097
dumpbin => 32 / 60 0d 1f b3 b7 db 85 1e e2 f9 99 3d 0d b2 5b 74 a5 dc 51 ba 6f fd a8 2b 9f 7f 77 75 62 7a 26 cd 

첫번째는 초기화(?) 때문에 4초란 오랜 시간이 걸리고..

동일한 Session에서는 이후 4ms 이하의 시간이 걸리는 듯 한다.

참고로 AES 256bit의 Key이다.

전에 SafeNet 5110으로 Key pair generate 테스트 할 때 시간이 오래 걸렸었는데 초기화 시간이 포함된 시간이었다.

Comment +0

https://www.npmjs.com/package/asn1-stream

 

asn1-stream

ASN1 parser with a stream interface

www.npmjs.com

asn1을 stream으로 파싱하는걸 찾았는데 없네요...

infinite length 파싱은 구현은 대충 해 놓았지만 동작하지 않을겁니다...

ASN1에 대해 잘 아시는 분은 infinite length 을 사용하는 예제 Payload좀 만들어 주세요...ㅠㅠ

아님 구현하셔서 PR주시면 매우감사!

Comment +1

  • 참고로.. 최상위 객체만 next stream으로 출력하기 때문에 최상위 객체속에 여러 객체가 있고 큰 데이터가 있으면 메모리 이슈가 발생할 수 있습니다.
    asn1으로 대용량 데이터 전송 스키마를 만드신다면 최상위 객체에 데이터를 잘라서(chunk) 길게 전달해야 합니다.

ResourceHandlerRegistry의 setOrder(0)을 줬더니 이걸 먼저 타버린다...ㅠㅠ

 

덕분에 몇시간동안 삽질을..

 

 

 

Comment +0

node.js를 runtime그대로 사용하지 않고 libnode를 이용해서 C++ Project내에 embedding하여 사용하고 있습니다.

이에 대해서는 제가 만든 node-app 소스를 이용하여 쉽게 접근할 수 있습니다.

일단 일반적인 상황에서는 테스트를 해 보았고 잘 동작하는거 같습니다만...

몇가지 Issue들이 있으며, 최근 Worker를 활용하면서 몇 가지 큰 이슈 상황이 있습니다.

(필독) 일단 기본적인 embedding에 대해

* 필수적으로 tracing관련하여 Fix된 commit을 적용해야 합니다.

#PR 31217 코멘트를 참고해 주세요. 이 PR을 모티브해서 감사하게도 #PR 31245 을 올려주셨습니다.

* NODE_USE_V8_PLATFORM=1 으로 빌드된 경우 문제되는 상황이 있습니다.

NODE_USE_V8_PLATFORM=1인 경우 libnode 내부적으로 per_process::v8_platform(export되지 않아 외부에서 사용할 수 없는 객체)을 이용하는 부분이 몇군데 있습니다. 따라서 v8_platform으로 초기화하지 않은경우 Crash가 발생하게 됩니다.

* node.js Javascript 코드 종료시 Crash 발생

제가 올린 PR #31260 에 해당 내용을 적어놓았습니다. PR은 통과되지 못하였고, 사실 좋은 방법도 아니며 Test도 통과하지 못합니다.

하지만 임시 방편으로 전 사용중입니다.

DisposePlatform() 함수를 호출하면 per_process::v8_platform.Dispose()을 하는데 v8_platform을 통해 초기화 되었는지 확인하지 않고 무조건 호출하기 때문에 v8_platform을 사용하지 못하고 직접 CreateEnvironment한 경우 Crash가 발생합니다.

threads_worker관련 Issue사항들

Embedding하여 node를 사용하면서 Worker를 사용할 때 필수적인 부분이 있습니다.

구 버전의 node인 경우 위에 v8_platform과 연관된것인데 worker의 isolate를 생성하면서 v8_platform의 Platform을 사용하는 문제가 있습니다.

따라서 6db45bf7def22eedfd95dac95713e850c366b169 커밋 이후 버전으로 빌드된 libnode.dll이 필요합니다. (PR #31217 코멘트 참고)

* Inspect초기화 문제 (Critical)

Issue #31256를 참고해 주세요.

PR #30467을 통해 해결될 수 있는데 아직 머지되지 못하였으며 코멘트들을 보면 참 많은 의견들이 있습니다..

그리고 그 사이에 또 변한 부분들이 여럿 있어서 v13 브랜치에 머지하면 현재는 다른 부분들에서 문제가 발생하기도 합니다.

저두 코드를 고쳐가며 나름 테스트를 해 보고 있습니다..

하지만 아직 Embedding환경에서 Worker사용은 시기상조인거 같습니다.

많은 분들이 관심을 가지고 nodejs측에 관심을 표현해 주심 빨리 해결되리라 생각합니다..!

참고로.. 문제가 발생하단 부분은 NodeZeroIsolateTestFixture.IsolatePlatformDelegateTest 테스트 실패인데,

(그나저나 일단 Environment Test에서 commit 1350eea23ad1da56d26bc60213734a264439aaa6 Fix가 필요하고..)

PR #30324 해당 내용 때문입니다.
PR #30467에서 FreeEnvironment할 때 DrainTasks가 추가되었는데, IsolatePlatformDelegate을 통해 Isolate를 Register했을 때 node_platform.cc의 ForNodeIsolate에서 오류가 발생합니다. shared_ptr\<PerIsolatePlatformData\>가 없기 때문에...

commit 8ab6756984c36d8b69732a71a2df5d28b03c3db5제대로된 방법일진 모르겠으나 Test는 통과합니다.

참고로 Embedding과 별개로 문제가 발생하는 경우가 있는데 PR #31215 이런 상황입니다.

그냥 제 예상으로는 worker사용시 v8 compilation cache관련하여 문제가 생기는게 아닌가 그냥 추측만 해 봅니다.

정확하게는 분석해보지 못해서 알지 못하겠구요..

암튼 코드엔 문제가 없지만 v8 engine이 잘못 해석할 수 있는 코드는 조심해야 할 것 같습니다.

저두 코드를 수정하여 해결하였습니다.

Comment +0