All Articles

ECDSA 서명으로 JWT 토큰 생성 및 검증하기


안녕하세요. 안피곤입니다.

ECDSA는 암호화폐에 가장 많이 사용되는 암호화 알고리즘입니다. 그리고 RSA 보다 성능이 더 좋다고 알려져 있습니다. 그리고 JWT(JSON Web Token)은 보안 및 인증에 가장 많이 사용되고 있습니다. 이 2개를 가지고 토큰을 생성하고 인증 하는 방법을 구현합니다.

보통은 JWT 생성에 SHA 해시 알고리즘을 사용하는 HMAC을 사용합니다. 이것은 단방향 암호화 방식입니다. 하지만 ECDSA를 사용하면 비대칭키를 사용하기 때문에 부인 방지 및 메세지 인증을 처리 할수 있습니다. 참고로 부인은 여러분이 생각하는 그 부인은 아닙니다.

갑자기 영화 “마담 프루스트의 비밀정원”에 나왔던 푸르스트 부인이 생각나네요. ㅋ


* * *

구현을 위해선는 아래 두 라이브러리가 필요합니다.

const jwt = require("jsonwebtoken");
const ECDSA = require('ecdsa-secp256r1');

참고: https://www.npmjs.com/package/jsonwebtoken https://www.npmjs.com/package/ecdsa-secp256r1


ECDSA 키 생성

const privateKey = ECDSA.generateKey()
 
privateKey.toJWK()
/*
{ kty: 'EC',
  crv: 'P-256',
  x: '4YdUIhIDncVu5tScgjxthiXOO_el11FWb56gR3qnhVQ',
  y: 'UyEvWOJbMZa9PtggGeRC9iQcAzOZZsyXpFE1qaF6jFk',
  d: 'TYVI2fW-nHSPGCx0MhWasg2Ggiyl1E_Kq4D1A5LmkxU' }
*/
 
privateKey.asPublic().toJWK()
/*
{ kty: 'EC',
  crv: 'P-256',
  x: '4YdUIhIDncVu5tScgjxthiXOO_el11FWb56gR3qnhVQ',
  y: 'UyEvWOJbMZa9PtggGeRC9iQcAzOZZsyXpFE1qaF6jFk' }
*/
 
privateKey.toPEM()
/*
-----BEGIN PRIVATE KEY-----
MIGHAgEAMBMGByqGSM49AgEGCCqGSM49AwEHBG0wawIBAQQgTYVI2fW+nHSPGCx0
MhWasg2Ggiyl1E/Kq4D1A5LmkxWhRANCAAThh1QiEgOdxW7m1JyCPG2GJc4796XX
UVZvnqBHeqeFVFMhL1jiWzGWvT7YIBnkQvYkHAMzmWbMl6RRNamheoxZ
-----END PRIVATE KEY-----
*/
 
privateKey.asPublic().toPEM()
/*
-----BEGIN PUBLIC KEY-----
MFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAE4YdUIhIDncVu5tScgjxthiXOO/el
11FWb56gR3qnhVRTIS9Y4lsxlr0+2CAZ5EL2JBwDM5lmzJekUTWpoXqMWQ==
-----END PUBLIC KEY-----
*/
 
privateKey.toCompressedPublicKey()
/*
A+GHVCISA53FbubUnII8bYYlzjv3pddRVm+eoEd6p4VU
*/

ECDSA 서명 하기

const message = { text: 'hello' }
privateKey.sign(JSON.stringify(message))
/*
lY3Lf9xDtcsqom5IKu+ZyikxeYHlEuxnPfme4lMxp76NMkIm5BiLxVjbqBSo4itfT/LEuBCzMXl11cB0w/X8dA==
*/

ECDSA 서명 검증

const key = 'A+GHVCISA53FbubUnII8bYYlzjv3pddRVm+eoEd6p4VU'
const publicKey = ECDSA.fromCompressedPublicKey(key) // or ECDSA.fromJWK
const message = { text: 'hello' }
const signature = 'lY3Lf9xDtcsqom5IKu+ZyikxeYHlEuxnPfme4lMxp76NMkIm5BiLxVjbqBSo4itfT/LEuBCzMXl11cB0w/X8dA=='
 
publicKey.verify(JSON.stringify(message), signature)
/*
true
*/

* * *

JWT 토큰 생성하기

ES256는 P-256 곡선과 SHA-256 해시 알고리즘을 사용하는 ECDSA입니다. 다른 알고리즘은 여기 문서를 참고하세요.

const privateKey = fs.readFileSync('private.key'); // or privateKey.toPEM();
const payload = { accessKey: 'hello' };
const jwtToken = jwt.sign(payload, privatekey, { algorithm: 'ES256' });

JWT 토큰 검증하기

const publicKey = publicKey.toPEM();
const result = jwt.verify(jwtToken, publicKey, { algorithm: 'ES256' });

# JWT 토큰 복호화하기

jwt 토큰 복호화 하여 내용을 확인합니다.

const decodedToken = jwt.decode(jwtToken, { algorithm: 'HS256' });


해피 코딩하세요~!


![](https://steemitimages.com/400x0/https://cdn.steemitimages.com/DQmQmWhMN6zNrLmKJRKhvSScEgWZmpb8zCeE2Gray1krbv6/BC054B6E-6F73-46D0-88E4-C88EB8167037.jpeg)
Published 14 Jun 2019

안피곤의 블로그입니다.