[์ปดํ“จํ„ฐ ๋ณด์•ˆ] ํƒ€์›๊ณก์„  DSA ๋””์ง€ํ„ธ ์„œ๋ช… ์„ค๋ช… ๋ฐ ๊ตฌํ˜„์ฝ”๋“œ

ํƒ€์›๊ณก์„  DSA ๋””์ง€ํ„ธ ์„œ๋ช…

์ž๋ฃŒ์กฐ์‚ฌ

DSA๋ž€?

๋””์ง€ํ„ธ ์„œ๋ช… ์•Œ๊ณ ๋ฆฌ์ฆ˜(Digital Signature Algorithm, DSA)์€ ๋””์ง€ํ„ธ ์„œ๋ช…์„ ์œ„ํ•œ ํ‘œ์ค€์ด๋‹ค. NIST๊ฐ€ 1991๋…„ 8์›” DSS๋ผ๋Š” ๋ฏธ๊ตญ ์ „์ž์„œ๋ช… ํ‘œ์ค€์—์„œ ์ด์šฉํ•˜๊ธฐ ์œ„ํ•ด ์ •๋ถ€์šฉ ์ „์ž์„œ๋ช… ์•Œ๊ณ ๋ฆฌ์ฆ˜์œผ๋กœ ๋ฐœํ‘œํ–ˆ์œผ๋ฉฐ, ํ˜„์žฌ๋Š” DSA์™€ ํ•จ๊ป˜ ECDSA, RSA๋ฅผ ์‚ฌ์šฉํ•˜๊ณ  ์žˆ๋‹ค.

 

๋””์ง€ํ„ธ ์„œ๋ช… ์ธ์ฆ ๋ฐฉ์‹

์ „์ž์„œ๋ช…(๋””์ง€ํ„ธ ์„œ๋ช…)์€ ๋ฌด๊ฒฐ์„ฑ, ์ธ์ฆ, ๋ถ€์ธ๋ฐฉ์ง€๋ฅผ ๋งŒ์กฑํ•ด์•ผํ•œ๋‹ค.

์ „์ž์„œ๋ช…์—๋Š” ๊ณต๊ฐœํ‚ค ์•”ํ˜ธํ™” ์•Œ๊ณ ๋ฆฌ์ฆ˜์ด ์“ฐ์ด๋ฉฐ ํฌ๊ฒŒ 3๊ฐ€์ง€ ์ข…๋ฅ˜์˜ ์•Œ๊ณ ๋ฆฌ์ฆ˜์ด ์žˆ๋‹ค.

  1. ํ•ฉ์„ฑ์ˆ˜์˜ ์†Œ์ธ์ˆ˜๋ถ„ํ•ด๋ฌธ์ œ๊ฐ€ ์–ด๋ ต๋‹ค๋Š” ๋ฐ์— ๊ธฐ์ดˆํ•œ RSAํ˜• ์•Œ๊ณ ๋ฆฌ์ฆ˜
  2. ์œ ํ•œ์ฒด์˜ ์ด์‚ฐ๋Œ€์ˆ˜ ๋ฌธ์ œ๊ฐ€ ์–ด๋ ต๋‹ค๋Š” ๋ฐ์— ๊ธฐ์ดˆํ•œ ElGamalํ˜• ์•Œ๊ณ ๋ฆฌ์ฆ˜
  3. ํƒ€์›๊ณก์„ ์„ ์ด์šฉํ•œ EC-DSA, EC-KCDSA

DSA๋Š” ์ด ์ค‘ ElGamalํ˜• ์•Œ๊ณ ๋ฆฌ์ฆ˜์œผ๋กœ ๊ธฐ๋ฐ€์„ฑ์€ ๊ฐ€์ง€๊ณ  ์žˆ์ง€ ์•Š์œผ๋ฉฐ ์ „์ž์„œ๋ช… ๊ธฐ๋Šฅ์„ ์ œ๊ณตํ•œ๋‹ค. ์ด๋Ÿฌํ•œ ์„œ๋ช… ์•Œ๊ณ ๋ฆฌ์ฆ˜๋“ค์€ ์ฃผ๋กœ 3๊ฐ€์ง€ ํ•จ์ˆ˜๋กœ ๋‚˜๋ˆ„์–ด ๋™์ž‘ํ•˜๋ฉฐ, ๊ฐ๊ฐ 'ํ‚ค ์ƒ์„ฑ', '์„œ๋ช…', '๊ฒ€์ฆ' ์—ญํ• ์„ ํ•˜๋Š” ํ•จ์ˆ˜์ด๋‹ค.

์ด์‚ฐ๋Œ€์ˆ˜ ๋ฌธ์ œ

์ด์‚ฐ ๋Œ€์ˆ˜ ๋ฌธ์ œ๋ž€ Y = g^x mod p๋ผ๋Š” ๋ฌธ์ œ์—์„œ Y, g, p๋ฅผ ๊ณต๊ฐœํ•˜๋”๋ผ๋„ x๋ฅผ ๊ณ„์‚ฐํ•˜๊ธฐ ์–ด๋ ค์šด ๋ฌธ์ œ๋ฅผ ๋œปํ•œ๋‹ค.

RSA์™€์˜ ๋น„๊ต

๋””์ง€ํ„ธ ์„œ๋ช…๊ณผ ์ธ์ฆ ๋ฐฉ์‹์€ ์›๋ž˜ RSA ๊ณต๊ฐœํ‚ค ์•”ํ˜ธํ™”์‹œ์Šคํ…œ์„ ์ด์šฉํ•˜๊ณ  ์žˆ์—ˆ๋‹ค. RSA์™€ DSA์˜ ์ฐจ์ด์ ์€ ๋‹ค์Œ ๊ทธ๋ฆผ๊ณผ ๊ฐ™๋‹ค.

RSA๋Š” ๊ฐœ์ธํ‚ค๋กœ ์ „์ž ์„œ๋ช… ๊ฐ’์„ ๋งŒ๋“ค์ง€ ์•Š๊ณ , ์›๋ณธ ๋ฉ”์‹œ์ง€๋ฅผ ์••์ถ• ํ•จ์ˆ˜๋กœ ์••์ถ•ํ•œ ํ›„ ์••์ถ• ํ•ด์‹œ๊ฐ’์„ ์•”ํ˜ธํ™”ํ•˜์—ฌ ์ „์ž์„œ๋ช… ๊ฐ’์„ ๋งŒ๋“ ๋‹ค. ๋ฉ”์‹œ์ง€ ์ธ์ฆ ์‹œ์—๋Š” ๋ฉ”์‹œ์ง€๋ฅผ ๋‹ค์‹œ ์••์ถ• ํ•ด์‹œ๊ฐ’์œผ๋กœ ๋งŒ๋“ค๊ณ , ๋ณตํ˜ธํ™”๋œ ์ „์ž์„œ๋ช… ๊ฐ’๊ณผ ๋น„๊ตํ•˜์—ฌ ์ธ์ฆํ•  ์ˆ˜ ์žˆ๋‹ค.

DSA๋„ ๋ฉ”์‹œ์ง€์˜ ์••์ถ• ๊ฐ’์„ ์•”ํ˜ธํ™”ํ•ด์„œ ์ „์ž์„œ๋ช…์„ ๋งŒ๋“œ๋Š” ๊ฒƒ์€ ๊ฐ™์ง€๋งŒ ๋ฉ”์‹œ์ง€ ์ธ์ฆ๊ณผ์ •์ด ๋‹ค๋ฅด๋‹ค. DSA ์•Œ๊ณ ๋ฆฌ์ฆ˜์€ ์ „์ž์„œ๋ช…๋งŒ์„ ์œ„ํ•œ ์•Œ๊ณ ๋ฆฌ์ฆ˜์ด๋ฏ€๋กœ ๋น„๊ต์—†์ด ๋ฐ”๋กœ ์ธ์ฆ์ด ๊ฐ€๋Šฅํ•˜๋‹ค.

RSA๋ณด๋‹ค ํ‚ค ์ƒ์„ฑ, ๋ณตํ˜ธํ™”(๊ฒ€์ฆ) ๊ณผ์ •์ด ๋น ๋ฅด๋ฉฐ ์•”ํ˜ธํ™”(์„œ๋ช…) ๊ณผ์ •์€ ๋น„๊ต์  ๋Š๋ฆฐ ํŽธ์ด๋‹ค.

 

ํŠน์ง•

  • RSA๋ณด๋‹ค ํ‚ค ์ƒ์„ฑ์ด ๋น ๋ฅด๋‹ค.
  • ๊ฒ€์ฆ์†๋„๋Š” RSA๋ณด๋‹ค ๋Š๋ฆฌ๋‹ค.
  • ์ด์‚ฐ ๋Œ€์ˆ˜ ๋ฌธ์ œ์˜ ์–ด๋ ค์›€์„ ์ด์šฉํ•œ ๋ฐฉ๋ฒ•์ด๋‹ค.
  • 320bit ์„œ๋ช…์„ ๋งŒ๋“ค์–ด ๋‚ธ๋‹ค.
  • ํ•ด์‹œ ํ•จ์ˆ˜๋กœ๋Š” SHA1์„ ์ด์šฉํ•œ๋‹ค.

 

๋ฌธ์ œ์ 

Nonce reuse ๋ฌธ์ œ๊ฐ€ ์žˆ๋‹ค. ์„œ๋ช… ์ƒ์„ฑ ๊ณผ์ •์—์„œ ์“ฐ์ธ k ๊ฐ’์„ ๋‹ค์‹œ ์‚ฌ์šฉํ•˜๋Š” ๊ฒƒ์ด๋‹ค. k๊ฐ’์ด ๊ฐ™์„ ๋•Œ์˜ ๋‘ ์„œ๋ช… (r,s1), (r,s2)๊ฐ€ ์žˆ๋‹ค๊ณ  ํ•˜๋ฉด

s1 − s2 = k^(−1)(H(m1)+xr−H(m2)−xr) = k^(−1)(H(m1)−H(m2))(mod q)

์ด๋ฏ€๋กœ

k = (H(m1)−H(m2))/(s1−s2)(mod q)

๋ฅผ ํ†ตํ•ด k๋ฅผ ๋ณต๊ตฌํ•  ์ˆ˜ ์žˆ๋‹ค. k๊ฐ’์„ ๋ณต๊ตฌํ•˜๋ฉด ์ด๋ฅผ ์ด์šฉํ•ด s1, r, H(m1), k๋ฅผ ๊ตฌํ•ด์„œ ๋น„๋ฐ€ํ‚ค x๋ฅผ ๋ณต๊ตฌํ•  ์ˆ˜ ์žˆ๋‹ค.

 

 

์•Œ๊ณ ๋ฆฌ์ฆ˜ ๋ถ„์„

๊ณผ์ •

์ค€๋น„

  • ํ‚ค ๊ธธ์ด๋ฅผ ์ •ํ•œ๋‹ค.

    L, N์„ ์ •ํ•ด์•ผํ•˜๋ฉฐ ์ผ๋ฐ˜์ ์œผ๋กœ (1024, 160), (2048, 224), (2048, 256), (3072, 256) ์ค‘ ํ•˜๋‚˜์ด๋‹ค.

  • ๋ฉ”์„ธ์ง€ ํ•ด์‹ฑ ํ•จ์ˆ˜ H๋ฅผ ์ •์˜ํ•œ๋‹ค.

    H์˜ output ๊ธธ์ด๋Š” N ์ด์ƒ์ด์–ด์•ผํ•œ๋‹ค.

  • ์„œ๋ช…์˜ ๋งค๊ฐœ๋ณ€์ˆ˜ (p,q,g)๋ฅผ ๊ณต์œ ํ•œ๋‹ค.

    p๊ฐ’์€ 2^(L-1) < p < 2^L๋ฅผ ๋งŒ์กฑํ•˜๋ฉฐ L bit ๊ธธ์ด์ธ ์†Œ์ˆ˜์ด๋‹ค.

    q๊ฐ’์€ 2^(N-1) < q < 2^N ์„ ๋งŒ์กฑํ•˜๋ฉฐ N bit ์‚ฌ์ด์˜ ๊ธธ์ด๋ฅผ ๊ฐ€์ง„ ์ˆ˜์ด๋‹ค.

    => ์—ฌ๊ธฐ์„œ p-1์ด q์˜ ๋ฐฐ์ˆ˜์—ฌ์•ผํ•œ๋‹ค.

    g๊ฐ’์€ g = h^((p-1)/q) mod p ๋ฅผ ๋งŒ์กฑํ•˜๋ฉฐ 1 < q < p์ธ ์ˆ˜์ด๋‹ค.

    ์ด ๋•Œ, 1 < h < p-1 && g > 1 ์ด๊ณ  ์ผ๋ฐ˜์ ์œผ๋กœ h๋Š” 2๋ฅผ ๊ณ ๋ฅธ๋‹ค.

ํ‚ค ์ƒ์„ฑ

  • ๊ณต๊ฐœํ‚ค y๋ฅผ ์ƒ์„ฑํ•œ๋‹ค.

    0 < x < q์ธ x(๊ฐœ์ธํ‚ค)๋ฅผ ๊ผฝ์€ ํ›„, y=g^x mod p๋กœ ๊ณต๊ฐœํ‚ค์ธ y๋ฅผ ๊ณ„์‚ฐํ•œ๋‹ค.

    ์ด์‚ฐ๋Œ€์ˆ˜ ๋ฌธ์ œ๋กœ y๊ฐ’์œผ๋กœ๋ถ€ํ„ฐ x๋ฅผ ์‰ฝ๊ฒŒ ๊ตฌํ•  ์ˆ˜ ์—†๋‹ค.

์„œ๋ช… ์ƒ์„ฑ

  1. ๋žœ๋คํ•œ ์ˆ˜๋ฅผ ์ƒ์„ฑํ•œ๋‹ค.

    0๋ณด๋‹ค ํฌ๊ณ  q๋ณด๋‹ค ์ž‘์€ ๋žœ๋ค ์ˆ˜ k๋ฅผ ์ƒ์„ฑํ•œ๋‹ค.

  2. ์ „์ž ์„œ๋ช…์„ ํ•œ๋‹ค.

    r = (g^k mod p) mod q
    s = (k^(-1)(H(M) +xr)) mod q
  3. (r, s, M)์„ ์ „์†กํ•œ๋‹ค.

์„œ๋ช… ๊ฒ€์ฆ

  1. (r, s, M)์„ ๋ฐ›๋Š”๋‹ค.

  2. ๊ฐ’์„ ๊ณ„์‚ฐํ•œ๋‹ค.

    w = s^-1 mod q
    u1 = (H(M)w) mod q
    u2 = rw mod q
    v = ((g^u1*y^u2) mod p ) mod q
  3. v๊ฐ€ r์ด๋ผ๋ฉด ์ธ์ฆ ์™„๋ฃŒ์ด๋‹ค.

 

Correctness of the algorithm

์•Œ๊ณ ๋ฆฌ์ฆ˜์—์„œ g = h^((p-1)/q) mod p์ด์—ˆ์œผ๋ฏ€๋กœ g^q = h^(p-1) = 1 mod p์ด๋‹ค. ๋”ฐ๋ผ์„œ a = b (mod q) ์ธ ์กฐ๊ฑด์—์„œ g^a = g^b (mod p)๊ฐ€ ์„ฑ๋ฆฝํ•จ์„ ์•Œ ์ˆ˜ ์žˆ๋‹ค.

์œ„์˜ ์•Œ๊ณ ๋ฆฌ์ฆ˜์—์„œ s = (k^(-1)(H(M) +xr)) mod q ์ด๋ฏ€๋กœ ์œ„์˜ ์„ฑ์งˆ์„ ์ด์šฉํ•˜๋ฉด k = (s^(-1)(H(M) +xr)) mod q๋กœ ๋‚˜ํƒ€๋‚ผ ์ˆ˜ ์žˆ๋‹ค. ๋”ฐ๋ผ์„œ

r = (g^k mod p) mod q = ((g^u1*y^u2) mod p) mod q = v

์ด๊ธฐ ๋•Œ๋ฌธ์— ์•Œ๊ณ ๋ฆฌ์ฆ˜์ด ์„ฑ๋ฆฝํ•œ๋‹ค.

 

 

ํ”„๋กœ๊ทธ๋žจ ๊ตฌํ˜„

์–ธ์–ด๋Š” C++๋กœ IDE๋Š” Visual Studio๋ฅผ ์ด์šฉํ•˜์—ฌ ๊ตฌํ˜„ํ•˜๊ธฐ๋กœ ํ•œ๋‹ค.

 

์ฃผ์š” ์ฝ”๋“œ ๊ตฌ์„ฑ

์ฝ”๋“œ๋Š” ์†ก์‹ ์ž์ธ Sender์™€ ์ˆ˜์‹ ์ž์ธ Receiver class๋กœ ๋‚˜๋ˆ„์–ด ๊ตฌํ˜„ํ•˜์˜€์œผ๋ฉฐ, ์ค‘๊ฐ„์„ ๋งค๊ฐœํ•˜๋Š” mainํ•จ์ˆ˜๋Š” ์„œ๋น„์Šค ์ œ๊ณต ์‹œ์Šคํ…œ์ด๋ผ๊ณ  ๋ณด๋ฉด ๋œ๋‹ค.

Sender ํด๋ž˜์Šค๋Š” 4๊ฐ€์ง€ ํ•จ์ˆ˜๋กœ ์ด๋ฃจ์–ด์ ธ์žˆ์œผ๋ฉฐ, ๊ฐ ํ•จ์ˆ˜์—์„œ ์“ฐ์ด๋Š” ๋ณ€์ˆ˜๋“ค์€ private์œผ๋กœ ์„ ์–ธ๋˜์–ด์žˆ๋‹ค.

๋จผ์ € ์†ก์‹ ์ž๋Š” initialize ํ•จ์ˆ˜๋ฅผ ์ด์šฉํ•˜์—ฌ ์ง€์ •๋œ ํ•ด์‹œํ•จ์ˆ˜๋ฅผ ์ด์šฉํ•œ ๋ฉ”์„ธ์ง€์˜ ํ•ด์‹œ๊ฐ’, ๋ณ€์ˆ˜ ๊ธธ์ด ๊ฒฐ์ • ๋ณ€์ˆ˜, ๋งค๊ฐœ๋ณ€์ˆ˜๋“ค์„ ์„ธํŒ…ํ•˜๋Š” ์—ญํ• ์„ ํ•œ๋‹ค. ๊ทธ ํ›„ generateKey ํ•จ์ˆ˜๋ฅผ ์ด์šฉํ•˜์—ฌ ํ•ด๋‹น ๋งค๊ฐœ๋ณ€์ˆ˜๋“ค๋กœ ๋น„๋ฐ€ํ‚ค x์™€ ๊ณต๊ฐœํ‚ค y๋ฅผ ๋งŒ๋“ค์–ด๋‚ธ๋‹ค. ํ•ด๋‹น ํ•จ์ˆ˜์—์„œ ํ˜ธ์ถœ๋˜๋Š” generateSign์œผ๋กœ ์„œ๋ช…์„ ๋งŒ๋“ค์–ด๋‚ด๊ณ , ์„œ๋ช…์ด๋ผ๊ณ  ์ผ์ปซ๋Š” r๊ณผ s๋ฅผ sendRS ํ•จ์ˆ˜๋กœ Receiver์—๊ฒŒ ๋ณด๋‚ธ๋‹ค.

Receiver ํด๋ž˜์Šค๋Š” verifySign์ด๋ผ๋Š” ํ•˜๋‚˜์˜ ํ•จ์ˆ˜๋กœ ์ด๋ฃจ์–ด์ ธ์žˆ๋‹ค. Sender์™€ ๋งˆ์ฐฌ๊ฐ€์ง€๋กœ ํ•„์š”ํ•œ ๋ณ€์ˆ˜๋“ค์€ private์œผ๋กœ ์„ ์–ธ๋˜์–ด์žˆ๋‹ค.

์ˆ˜์‹ ์ž๋Š” ์ „๋‹ฌ๋ฐ›์€ r, s, M์„ ๊ฐ€์ง€๊ณ  ๊ฒ€์ฆ์„ ์‹œ์ž‘ํ•œ๋‹ค. ๊ณ„์‚ฐ ๊ฒฐ๊ณผ ๋„์ถœ๋œ v ๋ณ€์ˆ˜ ๊ฐ’๊ณผ ์†ก์‹ ์ž๋กœ๋ถ€ํ„ฐ ๋ฐ›์€ r๊ฐ’์ด ๊ฐ™์œผ๋ฉด ์„œ๋ช…์ด ์ผ์น˜ํ•˜๋ฏ€๋กœ ๊ฒ€์ฆ์ด ์™„๋ฃŒ๋˜๊ณ  ์ „๋‹ฌ๋ฐ›์€ ๋ฉ”์„ธ์ง€๋ฅผ ์ถœ๋ ฅํ•œ๋‹ค. ๊ฐ™์ง€ ์•Š๋‹ค๋ฉด ๊ฒ€์ฆ์— ์‹คํŒจํ•œ๋‹ค.

 

๋„์›€ ํ•จ์ˆ˜

์ „์—ญ ๊ตฌ๊ฐ„์— ์กด์žฌํ•˜๋Š” ๋‘ ๊ฐ€์ง€ ๋„์›€ํ•จ์ˆ˜๊ฐ€ ์žˆ๋‹ค. bigModuler ํ•จ์ˆ˜๋Š” unsigned long์˜ ๋ฒ”์œ„๋ฅผ ๋ฒ—์–ด๋‚˜๋Š” ๋ชจ๋“ˆ๋Ÿฌ ๊ณ„์‚ฐ์„ ์œ„ํ•ด ์žฌ๊ท€ํ•จ์ˆ˜์˜ ํ˜•ํƒœ๋กœ ๋ถ„ํ• ์ •๋ณตํ•˜๋Š” ํ•จ์ˆ˜์ด๋‹ค. isPrime ํ•จ์ˆ˜๋Š” ํ•ด๋‹น ๋ณ€์ˆ˜๊ฐ€ ์†Œ์ˆ˜์ธ์ง€๋ฅผ ํŒ๋‹จํ•˜๋Š” ๋„์›€ํ•จ์ˆ˜๋กœ ๋งค๊ฐœ๋ณ€์ˆ˜ p๊ฐ’์„ ๊ฒฐ์ •ํ•  ๋•Œ ์‚ฌ์šฉ๋œ๋‹ค.

 

ํ—ค๋”ํŒŒ์ผ

ํ—ค๋”ํŒŒ์ผ๋กœ๋Š” Euclid.h์™€ SHA1.h๊ฐ€ ์žˆ๋‹ค. ์ฝ”๋“œ ์ƒ์—์„œ ์‚ฌ์šฉ๋˜๋Š” ํ•ด์‹œ ํ•จ์ˆ˜๋Š” ์ง์ ‘ ๊ตฌํ˜„ํ•ด๋‘” SHA1 ํ•จ์ˆ˜๋ฅผ ์‚ฌ์šฉํ•˜์˜€๋‹ค.

๋˜ํ•œ ์•Œ๊ณ ๋ฆฌ์ฆ˜ ์ค‘ ๋ชจ๋“ˆ๋Ÿฌ ๊ณฑ์˜ ์—ญ์›์„ ๊ตฌํ•˜๋Š” ๋ถ€๋ถ„์ด ์žˆ๋Š”๋ฐ, ์ด๋ฅผ ๊ตฌํ˜„ํ•˜๋ ค๋ฉด 2๊ฐ€์ง€ ๋ฐฉ๋ฒ•์„ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ๋‹ค.

  1. ์ˆœ์ฐจ์ ์œผ๋กœ ์ฆ๊ฐ€ํ•˜๋ฉด์„œ ์—ญ์› ์ฐพ๊ธฐ

  2. ํ™•์žฅ๋œ ์œ ํด๋ฆฌ๋“œ ํ˜ธ์ œ๋ฒ• ์ด์šฉํ•˜๊ธฐ

    ๋ณธ์ธ์€ ์ฒ˜์Œ์— 1๋ฒˆ ๋ฐฉ๋ฒ•์„ ์ด์šฉํ•˜์—ฌ ์ฝ”๋“œ๋ฅผ ๊ตฌํ˜„ํ•˜์˜€์œผ๋‚˜, ์—ญ์›์„ ์ฐพ๋Š” ๋ฐ์— ์‹œ๊ฐ„์ด ๋„ˆ๋ฌด ์˜ค๋ž˜ ๊ฑธ๋ ค์„œ ์œ ํด๋ฆฌ๋“œ ํ˜ธ์ œ๋ฒ•์„ ๊ตฌํ˜„ํ•œ Euclid.h ํŒŒ์ผ์„ ๋งŒ๋“ค์—ˆ๋‹ค.

 

๋ถ€์กฑํ•œ ์ 

์œ„์˜ ์•Œ๊ณ ๋ฆฌ์ฆ˜ ๋ถ„์„ ํŒŒํŠธ์—์„œ ์„ค๋ช…ํ–ˆ๋“ฏ์ด L๊ณผ N์€ ์ฃผ์–ด์ง„ bit ์Œ์ด ์กด์žฌํ•œ๋‹ค. L์€ ์ตœ์†Œ 1024bit ๋ถ€ํ„ฐ ์‹œ์ž‘ํ•˜๋ฏ€๋กœ ๊ณ„์‚ฐ์˜ ๋ฒ”์œ„๊ฐ€ ๋„ˆ๋ฌด ์ปค์ ธ ๋‹ค๋ฃจ๊ธฐ๊ฐ€ ์–ด๋ ค์› ๋‹ค. ๋”ฐ๋ผ์„œ ๋ณธ์ธ์€ L๊ณผ N์„ ๋‚ฎ์€ ์ˆ˜๋กœ ๊ณ ์ •ํ•ด๋‘ ์œผ๋กœ์จ unsigned long์˜ ๋ฒ”์œ„๋‚ด์—์„œ ๊ณ„์‚ฐ ๊ฐ€๋Šฅํ•œ ์ฝ”๋“œ๋กœ ๊ตฌํ˜„ํ–ˆ๋‹ค.

 

์ฝ”๋“œ

<Euclid.h>

#include <iostream>

using namespace std;
typedef unsigned long ulong;

ulong Euclid_module(ulong, ulong);

ulong Inverse(ulong n1, ulong n2) {
    int inv = 0;

    if (n1 > n2)
        inv = Euclid_module(n1, n2);
    else
        inv = Euclid_module(n2, n1);

    return inv;
}

ulong Euclid_module(ulong r1, ulong r2) {
    int r, q, s, s1 = 1, s2 = 0, t, t1 = 0, t2 = 1, tmp = r1;

    while (r2)
    {
        q = r1 / r2;
        r = r1 % r2;
        s = s1 - q * s2;
        t = t1 - q * t2;

        r1 = r2;
        r2 = r;
        s1 = s2;
        s2 = s;
        t1 = t2;
        t2 = t;
    }

    if (r1 == 1) // ์—ญ์ˆ˜ ์กด์žฌ
    {
        if (t1 < 0)
            t1 += tmp;
        return t1;
    }

    return 0;
}

<SHA1.h>

#include <cmath>
#include <vector>
#include <string>
#include <sstream>
#include <iomanip>
#include <iostream>

using namespace std;

std::string m;
uint64_t ml;
uint32_t weight[80];
uint32_t k_sha[80];

int exe = 0;

unsigned int h_sha[5] = {
    0x67452301,
    0xEFCDAB89,
    0x98BADCFE,
    0x10325476,
    0xC3D2E1F0
};

unsigned int rotl32(unsigned int value, unsigned int count) {
    return ((value << count) & 0xFFFFFFFF) | ((value & 0xFFFFFFFF) >> (32 - count));
}

void padding() {
    // m์— padding์„ ์ถ”๊ฐ€ํ•˜๊ธฐ ์ „ length (bit size)
    ml = m.size() * CHAR_BIT; // m.size() => 64bit (8byte)

                              // 0x80 = 2^7 = 10000000
                              // ์›๋ž˜ ๋ฉ”์„ธ์ง€์— bit '1' ์ถ”๊ฐ€
                              // ์–ด์ฐจํ”ผ ๋‹ค์Œ ๋‹จ๊ณ„์—์„œ 0์„ ์ฑ„์šฐ๊ธฐ ๋•Œ๋ฌธ์— ๋ฏธ๋ฆฌ 7๊ฐœ ์ถ”๊ฐ€
    m += (char)0x80;

    // 64byte(512bit)๋กœ ๋‚˜๋ˆ„์–ด๋–จ์–ด์ง€๋„๋ก 0 ์ฑ„์›Œ์ฃผ๊ธฐ
    // m.size()๊ฐ€ 64(byte)๊ฐ€ ๋  ๋•Œ๊นŒ์ง€
    while (m.size() % 64 != 64 - sizeof(ml)) {
        m += (char)0x00;
    }

    // ๋งจ ๋’ค์—๋Š” ๋ฉ”์„ธ์ง€ size ๋„ฃ๊ธฐ
    // 8bit ์”ฉ
    for (int i = 7; i >= 0; i--) {
        char byte = (ml >> 8 * i) & 0xff;
        m += byte;
    }

    // ์ด์ œ m์€ 64bytes(512bit)๋กœ ๋‚˜๋ˆ„์–ด ๋–จ์–ด์ง„๋‹ค.
}

void wSetting() {

    // m์„ w ์ฒ˜์Œ์— ์ฑ„์šฐ๊ธฐ
    // m (64byte(512bit)) => 16๊ฐœ์˜ w => ํ•˜๋‚˜์˜ w๋‹น 4byte(4๊ธ€์ž = 4*char)์˜ m์ด ํ• ๋‹น๋จ
    for (int i = 0; i < 16; i++) {
        weight[i] = (m[4 * i + 3] & 0xff)
            | (m[4 * i + 2] & 0xff) << 8
            | (m[4 * i + 1] & 0xff) << 16
            | (m[4 * i + 0] & 0xff) << 24;
    }

    // weight ๊ฐ€๊ณตํ•ด์„œ ๋‚˜๋จธ์ง€ weight ์ฑ„์šฐ๊ธฐ
    for (int i = 16; i < 80; i++) {
        weight[i] = rotl32(weight[i - 16] ^ weight[i - 14] ^ weight[i - 8] ^ weight[i - 3], 1);
    }

}

void kSetting() {
    for (int i = 0; i < 20; i++)
        k_sha[i] = 0x5A827999;
    for (int i = 20; i < 40; i++)
        k_sha[i] = 0x6ED9EBA1;
    for (int i = 40; i < 60; i++)
        k_sha[i] = 0x8F1BBCDC;
    for (int i = 60; i < 80; i++)
        k_sha[i] = 0xCA62C1D6;
}

uint32_t F(unsigned int b, unsigned int c, unsigned int d) {
    if (exe < 20) {
        return (b&c) | ((~b)&d);
    }
    else if (exe < 40) {
        return (b^c^d);
    }
    else if (exe < 60) {
        return ((b&c) | (b&d) | (c&d));
    }
    else if (exe < 80) {
        return (b^c^d);
    }
}

void SHA() {
    uint32_t a = h_sha[0]; uint32_t b = h_sha[1]; uint32_t c = h_sha[2]; uint32_t d = h_sha[3]; uint32_t e = h_sha[4];

    // 80๋ฒˆ loop
    uint32_t temp;
    while (exe != 80) {
        temp = rotl32(a, 5) + F(b, c, d) + e + weight[exe] + k_sha[exe];
        e = d;
        d = c;
        c = rotl32(b, 30);
        b = a;
        a = temp;
        exe++;
    }

    h_sha[0] = h_sha[0] + a;
    h_sha[1] = h_sha[1] + b;
    h_sha[2] = h_sha[2] + c;
    h_sha[3] = h_sha[3] + d;
    h_sha[4] = h_sha[4] + e;
}

unsigned int SHA1(string message) {
    m = message;

    padding(); // 1. ๋ฉ”์„ธ์ง€ padding ์ฒ˜๋ฆฌ
    wSetting(); // 2. w ์„ธํŒ…
    kSetting(); // 3. k ์„ธํŒ…
    SHA(); // 4. SHA 

    unsigned int result=0;
    for (int i = 0; i < 5; i++) {
        result += h_sha[i];
    }

    return result;
}

<DSA.cpp>

#include <iostream>
#include <random>
#include <math.h>
#include <Windows.h>
#include <vector>
#include "SHA1.h"
#include "Euclid.h"

using namespace std;

typedef unsigned long ulong;

random_device rd;
mt19937 gen(rd());

ulong p, q, g;
ulong y;
ulong Hm;
string M;

ulong bigModuler(ulong n, ulong e, ulong m) { // ํฐ ์ˆ˜์˜ ๋ชจ๋“ˆ๋Ÿฌ ๊ณ„์‚ฐ์„ ์œ„ํ•œ ํ•จ์ˆ˜
    if (e <= 3) {
        return ((int)pow(n, e)) % m;
    }

    if (e % 2 == 0) { // ์ง์ˆ˜์ด๋ฉด
        ulong tmp = bigModuler(n, e / 2, m);
        return (tmp*tmp) % m;
    }
    else {
        ulong tmp = bigModuler(n, (int)e / 2, m);
        ulong tmp2 = bigModuler(n, e-(int)e / 2, m);
        return (tmp*tmp2) % m;
    }
}

bool isPrime(ulong num) { // ์†Œ์ˆ˜๋ฅผ ํŒ๋ณ„ํ•˜๊ธฐ ์œ„ํ•œ ํ•จ์ˆ˜
    for (int i = 2; i <= (int)sqrt(num); i++) {
        if (num%i == 0)
            return false;
    }
    return true;
}


class Receiver {
private:
    ulong w, u1, u2, v;

public:
    void verifySign(ulong r, ulong s) { // ์ „์ž์„œ๋ช… ์ธ์ฆ ๊ณผ์ •
        cout << "verifying..." << endl;
        ulong inv_s = Inverse(s, q);
        w = inv_s % q;
        u1 = (Hm*w) % q;
        u2 = (r*w) % q;
        v = ((bigModuler(g,u1,p)*bigModuler(y,u2,p)) % p) % q;

        if (v == r) { // ์„œ๋ช…์ด ์ผ์น˜ํ•˜๋ฉด ํ†ต๊ณผ => ๋ฉ”์„ธ์ง€ ์ถœ๋ ฅ
            cout << "authentication success :>" << endl;
            cout << "message : " << M << endl;
        }
        else {
            cout << "authentication denied :<" << endl;
        }
    }
};

class Sender {
private:
    ulong L, N;
    ulong h = 2;
    ulong k, r, s;

public :
    vector<ulong> sendRS() {
        cout << "sending..." << endl;
        vector<ulong> rs;
        rs.push_back(r);
        rs.push_back(s);

        cout << "send complete!" << endl << endl; // r,s,M ์ „์†ก

        return rs;
    }

    void generateSign(ulong x) {
        uniform_int_distribution<> dis4(1, q - 1);

        k = dis4(gen); // ๋žœ๋ค ์ˆ˜ k ์ƒ์„ฑ
        ulong inv_k = Inverse(k, q); 

        r = bigModuler(g, k, p) % q;
        s = (inv_k*(Hm + x * r)) % q;

        if (s == 0) { // s๊ฐ€ 0์ด๋ฉด ๋‹ค์‹œ ํ•˜๊ธฐ
            generateKey(); 
        }
    }

    void generateKey() {
        uniform_int_distribution<> dis3(1, q - 1);
        ulong x = dis3(gen); // ๋žœ๋ค ์ˆ˜ x ์ƒ์„ฑ
        y = bigModuler(g, x, p); 

        generateSign(x); // ์ „์ž์„œ๋ช… ์ƒ์„ฑ
    }

    void initialize() {
        L = 5; N = 2; // length ์„ค์ •
        Hm = SHA1(M); // ํ•ด์‹œ ํ•จ์ˆ˜ ์ด์šฉ => ๋ฉ”์„ธ์ง€ ํ•ด์‹œ๊ฐ’ ์ƒ์„ฑ


        uniform_int_distribution<> dis((ulong)pow(2, L - 1) + 1, (ulong)pow(2, L) - 1);
        do {
            p = dis(gen);
        } while (!isPrime(p)); // ์ฃผ์–ด์ง„ ๋ฒ”์œ„ ๋‚ด์˜ ์†Œ์ˆ˜ p ์ฐพ๊ธฐ

        int flag = 0;
        for (ulong i = (ulong)pow(2, N - 1) + 1; i >= (ulong)pow(2, N) - 1; i--) {
            if ((p - 1) % i == 0) {
                q = i;
                flag = 1;
            }
        }
        if (!flag) {
            initialize();
        }

        g = bigModuler(h, (ulong)((p - 1) / q), p);
    }
};

int main() {
    cout << "๋ฌธ์ž์—ด์„ ์ž…๋ ฅํ•ด์ฃผ์„ธ์š”." << endl;
    cin >> M;
    cout << endl;

    Sender* s = new Sender(); // ์ˆ˜์‹ ์ž ์ƒ์„ฑ
    Receiver* r = new Receiver(); // ์†ก์‹ ์ž ์ƒ์„ฑ

    s->initialize(); // ์ดˆ๊ธฐํ™”
    s->generateKey(); // ํ‚ค ์ƒ์„ฑ
    cout << "๊ณต๊ฐœํ‚ค : " << y << endl; // ๊ณต๊ฐœํ‚ค ๊ณต๊ฐœ

    vector<ulong> tmp = s->sendRS(); // r,s,M ์ „์†ก

    r->verifySign(tmp[0],tmp[1]); // ์ „์ž์„œ๋ช… ์ธ์ฆ
    cin >> M;
}

์‹คํ–‰ํ™”๋ฉด

์‹œ์Šคํ…œ์„ ์‹œ์ž‘ํ•˜๊ณ  ๋ฌธ์ž์—ด์„ ์ž…๋ ฅํ•˜๋ฉด ๊ณต๊ฐœํ‚ค๊ฐ€ ์ถœ๋ ฅ๋œ๋‹ค. Sender๊ฐ€ Receiver์—๊ฒŒ ๋ณด๋‚ด๋Š” ๊ณผ์ •์ด ์ง€๋‚œ ํ›„, Receiver๊ฐ€ ๊ฒ€์ฆํ•  ๋•Œ, ์ฃผ์–ด์ง„ ๊ณต๊ฐœํ‚ค์™€ ์ „๋‹ฌ๋ฐ›์€ ๋งค๊ฐœ๋ณ€์ˆ˜๋ฅผ ๊ฐ€์ง€๊ณ  ๊ฒ€์ฆ์ ˆ์ฐจ๋ฅผ ๊ฑฐ์นœ๋‹ค. ๊ฒ€์ฆ์— ์„ฑ๊ณตํ•˜๋ฉด ์„ฑ๊ณตํ‘œ์‹œ์™€ ํ•จ๊ป˜ Sender๊ฐ€ ๋ณด๋‚ธ ๋ฉ”์„ธ์ง€๊ฐ€ ์ถœ๋ ฅ๋œ๋‹ค.

 

 

์ฐธ๊ณ ๋ฌธํ—Œ

https://www.nist.gov/publications/digital-signature-standard-dss-0?pub_id=902984

http://blog.naver.com/PostView.nhn?blogId=turbo0815&logNo=60049190798

https://medium.com/@kwoncharles/%EC%A0%84%EC%9E%90%EC%84%9C%EB%AA%85-digital-signature-%EC%96%B4%EB%96%BB%EA%B2%8C-%ED%95%B4-66d1335f2e36

http://www.parkjonghyuk.net/lecture/modernCrypto/lecturenote/chap09-1.pdf

http://www.secmem.org/blog/2019/07/21/Digital-Signature-and-Nonce-Ruse/

https://eunplay.tistory.com/122

http://www.secmem.org/blog/2019/07/21/Digital-Signature-and-Nonce-Ruse/

https://blog.naver.com/techshare/220921626310

https://nvlpubs.nist.gov/nistpubs/FIPS/NIST.FIPS.186-4.pdf

https://lyb1495.tistory.com/25

https://www.cryptopp.com/

๋ฐ˜์‘ํ˜•