Back to Home

ECDSA - Chữ ký số trên đường cong elliptic

Nếu bạn chưa biết gì hoặc mới tìm hiểu về Elliptic Curve, bạn có thể đọc lại các bài trước của series này:

Ở các bài viết trước, chúng ta đã biết rằng có thể tạo ra một nhóm con cyclic với phép cộng từ một điểm GOG \ne O bất kỳ trên đường cong EE. Đây là cơ sở để xây dựng lược đồ chữ ký số dựa trên đường cong elliptic (ECDSA - Ellipti Curve Digital Signature Algorithm)

Ưu điểm của hệ mật mã trên đường cong elliptic (ECC - Elliptic Curve Cryptography) là nó sử dụng khóa có độ dài nhỏ hơn RSA truyền thống. Hãy xem lại bảng thống kê dưới đây để thấy rõ điều đó:

Hiện nay tất cả các hệ mã hóa được sử dụng trong công nghệ blockchain đều dùng ECC cho mọi kỹ thuật: mã hóa, trao đổi khóa, chữ ký số, ZKP, … Trong bài này mình sẽ giới thiệu kỹ thuật chữ ký số trên ECC.

Elliptic Curve Digital Signature Algorithm

Chữ ký số cho phép:

  • Xác thực người gửi

  • Đảm bảo dữ liệu không bị thay đổi

  • Không thể chối bỏ

ECDSA được sử dụng rộng rãi trong nhiều hệ thống:

  • Bitcoin

  • Ethereum

  • Transport Layer Security

Nhờ sử dụng elliptic curve, ECDSA đạt mức bảo mật cao với kích thước khóa nhỏ hơn nhiều so với RSA.

Một hệ thống chữ ký số thường gồm 3 bước:

  1. Key Generation – tạo khóa

  2. Signing – ký dữ liệu

  3. Verification – xác minh chữ ký

ECDSA thực hiện các bước này dựa trên toán học của elliptic curve.

Tạo khóa

  • Cho điểm GG là điểm sinh của nhóm con bậc nn trên đường cong EE.

  • Chọn dA,0<dA<nd_A, 0 \lt d_A \lt n ngẫu nhiên làm secret key.

  • Tính public key QA=dA×GQ_A = d_A \times G

Sinh chữ ký cho message MM

  • Gọi m=Hash(M)m = Hash(M) là giá trị hash của message MM, tính z=mmodnz = m \bmod n.

    Chú ý: việc tính zz là để nhằm đảm bảo giá trị zz trong khoảng [0,n1][0, n-1]

  • Chọn giá trị ngẫu nhiên k[1,n1]k \in [1, n-1], tính điểm K(xK,yK)=k×G()K(x_K,y_K) = k \times G (*). Lưu ý rằng giá trị kk phải ngẫu nhiên và chỉ dùng 1 lần duy nhất vì nếu hai chữ ký sử dụng cùng một gia trị kk, attacker có thể tính ngược lại được secret key. Lịch sử đã từng có nhiều sự cố bảo mật do lỗi này, ví dụ trong hệ thống của Sony khi triển khai chữ ký số cho PlayStation 3. Do đó trong thực tế người ta thường sử dụng chuẩn deterministic ECDSA (RFC 6979) để tạo kk.

  • Tính r=xKmodnr = x_K \bmod n. Nếu r=0r=0, chọn lại kk với giá trị khác.

  • Tính s=k1(z+rdA)modns = k^{-1} (z + rd_A) \bmod n. Nếu s=0s=0, chọn lại kk với giá trị khác.

  • Chữ ký là cặp số (r,s)(r,s). Lưu ý là cặp số (r,s)(r,-s) cũng là một chữ ký hợp lệ.

Xác minh chữ ký (r,s)(r,s) cho mm

Dùng public key QAQ_A:

  • Tính z=mmodnz = m \bmod n

  • Tính u1=z×s1modnu_1 = z \times s^{-1} \bmod n, tính u1×Gu_1 \times G

  • Tính u2=r×s1modnu_2 = r \times s^{-1} \bmod n, tính u2×Gu_2 \times G

  • Tính S(x,y)=u1×G+u2×QAS(x,y) = u_1 \times G+ u_2 \times Q_A

  • Chữ ký hợp lệ nếu r=xr=x

Lý do tại sao thuật toán này hoạt động?

Xét điểm S(x,y)S(x,y):

S(x,y)=u1×G+u2×QA=u1×G+u2dA×G=(u1+u2dA)×G=(zs1+rdAs1)×G=(z+rdA)s1×G=(z+rdA)(k1(z+rdA))1×G=(z+rdA)(k1)1(z+rdA)1×G=k×G\begin{align*} S(x,y) &= u_1 \times G + u_2 \times Q_A\\ &= u_1 \times G + u_2d_A \times G \\ &= (u_1 + u_2d_A) \times G \\ &= (zs^{-1} + rd_As^{-1}) \times G \\ &= (z + rd_A)s^{-1}\times G \\ &= (z + rd_A)\left(k^{-1}(z + rd_A)\right)^{-1}\times G \\ &= (z + rd_A)(k^{-1})^{-1}(z+rd_A)^{-1} \times G \\ &= k \times G \end{align*}

Như vậy ta có:

S(x,y)=k×G=K(xK,yK)()S(x,y) = k \times G = K(x_K,y_K) (*)

r=xKmodn    r=xr = x_K \bmod n \implies r = x, vì thế thuật toán chính xác!

Lý do tại sao giá trị kk không được sử dụng nhiều lần?

Trong quá trình ký, ta có:

s=k1(z+rdA)(modn)s = k^{-1}(z + rd_A) \pmod n

trong đó:

  • dAd_A : private key

  • kk : số ngẫu nhiên chỉ dùng một lần

  • zz : hash của message

  • r,sr,s : chữ ký

  • nn : order của điểm sinh

Giả sử attacker biết được một giá trị kk dùng cho 2 message, ta có 2 chữ ký:

  • Message m1m1: s1=k1(z1+rdA)(modn)s_1 = k^{-1}(z_1 + r d_A) \pmod n

  • Message m2m_2​: s2=k1(z2+rdA)(modn)s_2 = k^{-1}(z_2 + r d_A) \pmod n

Mà:

  • rr giống nhau vì r=x(kG)r = x(kG)

  • kk giống nhau vì bị reuse

Trừ hai phương trình ta có:

s1s2=k1(z1+rdAz2rdA)=k1(z1z2)s_1 - s_2 = k^{-1}(z_1 + rd_A - z_2 - rd_A) = k^{-1}(z_1 - z_2)

Suy ra:

k=z1z2s1s2(modn)k = \frac {z_1 - z_2} {s_1 - s_2} \pmod n

Như vậy attacker tính được kk. Và từ kk có thể tính ra private key bằng cách:

  • Quay lại phương trình ban đầu s=k1(z+rdA)s=k^{-1}(z+rd_A)

  • Nhân 2 vế với kk: ks=z+rdAks = z+rd_A

  • Suy ra: dA=kszr(modn)\displaystyle d_A = \frac {ks-z} r \pmod n

Mà attack đã biết tất cả giá trị k,s,z,rk,s,z,r nên chúng tính được private key dAd_A.

Demo

Các bước trong demo này:

  • Chọn tham số đường cong, update

  • Chọn một điểm trên đường cong để làm điểm sinh GG

  • Chọn khóa bí mật, chọn giá trị để ký, sinh chữ ký

  • Verify chữ ký

Comments

0/300

Leave name/email blank to comment anonymously

No comments yet. Be the first to comment!