본문 바로가기
Programming

JWT 비대칭키로 암호화 복호화 하는 법

by 개발자 염상진 2022. 9. 7.

 

프로젝트를 진행하면서 Issuer가 발급한 Verifiable Credential을 암호화해야 하는 상황이 생겼다. JWT를 이용해서 암호화 복호화 하는 방향으로 정하고, 비대칭키 방법을 적용했다. 기존에 JWT는 대칭키로만 사용해서 서버에서 인증용도로만 사용했었는데, VC를 암호화하는 방식으로 사용하는 건 이번이 처음이다.

 

JWT 비대칭키

 

비대칭키를 생성하는 알고리즘은 여러가지가 있지만, 이번 경우에는 Node.js에서 기본 제공되는 crypto 모듈을 사용해 RSA 알고리즘, pem 형식으로 비대칭키를 발급받아 publicKey와 privateKey로 사용했다.

우선 crypto module로 비대칭키를 발급받는 방법은 아래 글을 참고하면 된다.

 

 

Node.js crypto 비대칭키 대칭키 구현하기

암호화는 프로그램에서 굉장히 중요한 분야고 계속해서 연구가 진행되고 있습니다. 많은 연구자들이 좀더 안전한 암호화 알고리즘을 개발하고 있고, 현재 우리는 알게 모르게 그들의 결과물을

about-tech.tistory.com

 

비대칭키 Pairs를 발급받은 후 JWT로 암호화 복호화를 진행한다. Node.js crypto 모듈로 발급받은 비대칭키는 RSA 알고리즘을 사용하므로, JWT에서 암/복호화를 하기 위해서는 Algorithm을 명시해줘야 한다. Algorithm의 기본값이 HS256이기 때문이다.

 

JWT 암호화

 

비대칭키를 우선 생성한다.

const genKey = () => {
  try {
    const { publicKey, privateKey } = generateKeyPairSync("rsa", {
      modulusLength: 4096,
      publicKeyEncoding: {
        type: "spki",
        format: "pem",
      },
      privateKeyEncoding: {
        type: "pkcs8",
        format: "pem",
        cipher: "aes-256-cbc",
        passphrase: "top secret",
      },
    });
    
    return { publicKey, privateKey};
  } catch (error) {
    console.log(error)
  }
};

 

암호화에 사용되는 PrivateKey는 추가적으로 다시 생성해줘야 한다. pem 형식으로 기존에 발급된 privateKey가 아니라 Object 형식으로 반환되는 Key를 사용해 암호화가 가능하다.

암호화에 사용할 Key를 생성하는 함수를 하나 만들어 주고,

const genPrivateKey = (k) => {
  const key = crypto.createPrivateKey({
    key: k,
    format: "pem",
    passphrase: "top secret",
  });
  return key;
};

 

Issuer로 부터 발급된 VC를 암호화한다.

const key = genPrivateKey(privateKey);

    // JWT Sign (개인키로 암호화)
    const messageSign = jwt.sign(
        {
          sub: "did:klay:0x435df3eda57154cf8cf7926079881f2912f54db4",
          nbf: 1562950282,
          vc: {
            "@context": ["https://www.w3.org/2018/credentials/v1"],
            type: ["VerifiableCredential"],
            credentialSubject: {
              degree: {
                type: "BachelorDegree",
                name: "Baccalauréat en musiques numériques",
              },
            },
          },
        },
        key,
        {
          issuer: "AboutTech",
          algorithm: "RS256",
        }
      );

 

3번째 인자로 만료기간, 알고리즘, 발행자 등을 명시할 수 있는데, alogorithm에 RS256을 지정해준다. 암호화된 Message를 출력하면 다음처럼 나온다.

eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiJkaWQ6a2xheToweDQzNWRmM2VkYTU3MTU0Y2Y4Y2Y3OTI2MDc5ODgxZjI5MTJmNTRkYjQiLCJuYmYiOjE1NjI5NTAyODIsInZjIjp7IkBjb250ZXh0IjpbImh0dHBzOi8vd3d3LnczLm9yZy8yMDE4L2NyZWRlbnRpYWxzL3YxIl0sInR5cGUiOlsiVmVyaWZpYWJsZUNyZWRlbnRpYWwiXSwiY3JlZGVudGlhbFN1YmplY3QiOnsiZGVncmVlIjp7InR5cGUiOiJCYWNoZWxvckRlZ3JlZSIsIm5hbWUiOiJCYWNjYWxhdXLDqWF0IGVuIG11c2lxdWVzIG51bcOpcmlxdWVzIn19fSwiaWF0IjoxNjYyNTE5MTE3LCJpc3MiOiJBYm91dFRlY2gifQ.X9TFCpirMWZF6rpgKKAJ4exoN0wxvEXDueZC-InA6D67YBH2gJYCz7FbWCug7SCCYJL6r1h9vBtxdgU390L-FpBIiP5oxkmpf8C8OOwZX3w_hyAhjWynnrP2s8Dv0zsNJJH1DMgIa3QOwudi-dOl1xavp6Wq2tzOXVf_ZecQLH-Ik1sHjQTNR9kNcVmh57bD9UQvPcPpa3EQXxhYGnSBTjAZJpDZiqsPWI8jo6qeQwvFDVpDxY4XGsHU6h_bBxNuhsvYpNflhtvxDfR9Czo4EQNf7a3SH7gWICKUi7fxzKrDN2m9PX7CF0jOs6LGm0UZ7RrOYsshVO8fBKFCh4dRFtgiDvxyYbhwC5tWsXJfO9vo7e14Yz5c0i_S0UgsYyd6tInfp9lSaQ-UoOvZlOOM5yKNwnEGcHxWTqGKZFbrWfBXhKLAc9FtjODc2CXFx3hrRJ8x50a61Iet2iwZL0UXNNrLRiZzKvC0pYeA4fXvJAeEvpOWRCF5MbCa9DUXv4wXTpM75d-t1BFzdFYiV6X5mJYTwjWGsUMG2Xop9cgavEtyNFokcR0IqZotUeGe4HS6Rvx9l3CY59Ubkl-rdxIUslKAafkVhsvGB_p73G5A1Dt8-J8tfxpLLQZFt_BlQY4aekewdZPxm6hpEqJo99xaUGRKsegmeNe_WAPO60YMQPw

 

JWT 복호화

 

비대칭키를 사용해 암/복호화를 진행하므로, 암호화는 PrivateKey를 사용했지만 복호화에는 PublicKey를 사용한다. 

const verifiedMessage = jwt.verify(messageSign, pubKey);

 

복호화를 진행하면 JWT payload에 담았던 정보가 그대로 출력된다. 

 

JWT.io 에서 Debugging 한 데이터
Server에서 반환한 데이터

 

더 알아볼 내용

 

문제는 Key Pair을 생성하는 방법과 어떻게 안전하게 관리할 것인가에 대한 다음 step이 남아있다. did-jwt-vc 모듈을 사용하면 DID Resolver에서 DID Document를 가져와서 pubkey를 추출해 복호화 하는 로직을 지원한다. 즉, wallet의 secret Key값과 주소값으로 암복호화가 가능한데, baobab 테스트 환경에서 사용자의 secret값을 입력받는 로직은 사용자의 거부감을 일으킬 수 있어 제작을 하지 못했다.

또한 지갑 주소와 지갑 시크릿 값을 사용해 암복호화 하는 방법을 찾아보면 Klip에서 QR 코드를 찍는 방식으로 시크릿 값을 가져와 암/복호화 하는 방식을 사용할 수도 있겠다.

 

 

 

Node.js Error Handling Object 에러 처리하기

코드를 작성하다보면 100% 에러를 만나게 됩니다. 누군가에게는 불편한 메시지일 수 있지만 개발자 입장에서는 반가운 존재입니다. 코드가 엄격하게 짜질 수록 예외처리를 쉽게 할 수 있고 어떤

about-tech.tistory.com

 

 

Truffle Testing 방법 (Mocha, chai 사용)

Truffle 에서 개발, 배포, 테스팅 까지 원큐에 끝낼 수 있습니다. Truffle Test Truffle에서 테스트를 할 수 있는 방법은 2가지가 있습니다. solidity파일로도 가능하고, test.js 파일로도 가능합니다. 두가지

about-tech.tistory.com

 

 

[회고록] 코드스테이츠 인센티브 기반 커뮤니티 프로젝트 2 후기

프로젝트 1에 이어서 2주간 이어지는 프로젝트 2가 진행되었다. 4명의 팀원이 모여서 인센티브 기반 토큰 이코노미를 적용한 커뮤니티 웹 서비스를 개발하는것이 프로젝트의 메인 주제고, 클라

about-tech.tistory.com

 

댓글