2012-06-07 20 views
7

Tôi đang phát triển chữ ký số phân phối ký một tài liệu và gửi nó qua mạng đến Máy chủ ứng dụng. Tôi đang sử dụng lập trình socket trong java để thực hiện. Tôi nghĩ rằng khóa công khai nên được mã hóa hoặc nén tức là giá trị x và y bằng cách nào đó được biểu diễn dưới dạng dữ liệu nhị phân đơn và được lưu trong đăng ký hoặc mạng công cộng. Nhưng tôi không biết cách thực hiện trong java.Làm cách nào để tôi nén hoặc mã hóa khóa công khai đường cong Elliptic và đặt nó qua mạng?

 // I have class like this 
      public class CryptoSystem{     

       EllipticCurve ec = new EllipticCurve(new P192()); 

       //------------------- 
       //-------------------- 

       public ECKeyPair generatekeyPair() 
       { 
        return ECKeyPair(ec); 

       } 


      }  
     // i don't think i have problem in the above 


    CryptoSystem crypto = new CryptoSystem(); 
    ECKeyPair keyPair = crypto.generateKeyPair(); 
    BigInteger prvKey = keyPair.getPrivateKey(); 
    ECPoint pubKey = keyPair.getPublicKey(); 
    // recommend me here to compress and send it the public key to a shared network. 

Tôi muốn biết làm thế nào để mã hóa phím và miền thông số công cộng, do đó người xác minh của chữ ký sẽ giải mã nó để sử dụng it.because khi bạn gửi cho họ trên mạng để người xác minh u gonna phải mã hóa như là một mảng byte đơn.i không sử dụng Bouncy Castle Provider. Việc thực thi toàn bộ thuật toán ECDSA là dự án của tôi là

+0

Làm thế nào để bạn đại diện cho họ trong bộ nhớ? Họ là số nguyên chỉ lớn, serializing họ nên dễ dàng. – CodesInChaos

+0

Bạn muốn sử dụng nén điểm? Đó là một kỹ thuật mà bạn chỉ tuần tự hóa tọa độ x và dấu của toạ độ y, và sau đó sử dụng phương trình đường cong để khôi phục toạ độ y. – CodesInChaos

+0

có, nhưng ngoài nén tôi muốn đặt nén khóa công khai trong mạng đăng ký chia sẻ vì vậy hai hoặc nhiều máy chủ ứng dụng sẽ sử dụng nó để xác minh chữ ký –

Trả lời

9

Các đường cong Elliptic hầu như luôn được mã hóa bằng cách sử dụng mã hóa được chỉ định trong X9.62.

Tùy chọn sử dụng nén điểm là tùy chọn. Nó là tầm thường để mã hóa bằng cách sử dụng nén điểm, nhưng giải mã một điểm nén cần nhiều công việc hơn một chút, vì vậy trừ khi bạn thực sự cần phải lưu thêm byte, tôi sẽ không bận tâm. Hãy cho tôi biết nếu bạn cần nó, và tôi sẽ thêm các chi tiết. Bạn có thể nhận ra các điểm mã hóa X9.62 với nén điểm bằng byte đầu tiên, sẽ là 0x02 hoặc 0x03.

Mã hóa mà không cần nén điểm thực sự đơn giản: bắt đầu bằng 0x04 (để cho biết không nén). Sau đó, hãy làm theo đầu tiên với tọa độ x, sau đó là tọa độ y, cả hai không đệm ở bên trái lên đến kích thước tính bằng byte của trường:

int qLength = (q.bitLength()+7)/8; 
byte[] xArr = toUnsignedByteArray(x); 
byte[] yArr = toUnsignedByteArray(y); 
byte[] res = new byte[1+2*qLength]; 
res[0] = 0x04; 
System.arraycopy(xArr, 0, res, qLength - xArr.length, xArr.length); 
System.arraycopy(yArr, 0, res, 2* qLength - yArr.length, nLength); 

Giải mã điều này là tất nhiên không đáng kể.

+0

cảm ơn, tôi hiểu câu trả lời của bạn. nơi mà khóa công khai tôi nên lưu để được sử dụng bởi một hoặc nhiều máy chủ ứng dụng trên vùng sâu vùng xa? –

+0

những gì về các thông số tên miền (q, a, b, G, n, h), làm thế nào để họ vượt qua để các ứng dụng xác minh chữ ký từ xa, bởi vì có tự động lựa chọn đường cong elliptic như dấu hiệu u. p-192, p-224, ...., p-512 Các tham số tên đường cong elliptic được đề nghị –

+0

@Clickmit: Tôi giả sử bạn có tham số miền tĩnh và chỉ mã hóa chúng ở mỗi đầu. Nếu bạn chỉ có một danh sách nhỏ các đường cong được hỗ trợ, tôi sẽ chỉ làm một cái gì đó như thêm một số nguyên xác định đường cong bạn đang sử dụng. Nếu bạn muốn mã hóa tất cả các tham số miền, có những tiêu chuẩn cho điều đó (tra cứu cấu trúc ECDomainParameters ASN.1), nhưng tôi nghĩ bạn nên tìm một bộ mã hóa DER ASN.1 cho điều đó. Mã hóa tay mã hóa của một cấu trúc như vậy không phải là tầm thường. –

3

Tôi khá chắc chắn rằng triển khai BC sử dụng mã hóa X9.63, vì vậy đây sẽ là mã hóa được chuẩn hóa. Bạn sẽ cần phải thêm các nhà cung cấp Bouncy Castle để JRE của bạn (Security.addProvider(new BouncyCastleProvider()), xem tài liệu bouncy.

public static void showECKeyEncodings() { 

    try { 
     KeyPairGenerator kp = KeyPairGenerator.getInstance("ECDSA"); 
     ECNamedCurveParameterSpec ecSpec = ECNamedCurveTable 
       .getParameterSpec("prime192v1"); 
     kp.initialize(ecSpec); 
     KeyPair keyPair = kp.generateKeyPair(); 

     PrivateKey privKey = keyPair.getPrivate(); 
     byte[] encodedPrivKey = privKey.getEncoded(); 
     System.out.println(toHex(encodedPrivKey)); 

     PublicKey pubKey = keyPair.getPublic(); 
     byte[] encodedPubKey = pubKey.getEncoded(); 
     System.out.println(toHex(encodedPubKey)); 

     KeyFactory kf = KeyFactory.getInstance("ECDSA"); 
     PublicKey pubKey2 = kf.generatePublic(new X509EncodedKeySpec(encodedPubKey)); 
     if (Arrays.equals(pubKey2.getEncoded(), encodedPubKey)) { 
      System.out.println("That worked for the public key"); 
     } 

     PrivateKey privKey2 = kf.generatePrivate(new PKCS8EncodedKeySpec(encodedPrivKey)); 
     if (Arrays.equals(privKey2.getEncoded(), encodedPrivKey)) { 
      System.out.println("That worked for the private key"); 
     } 

    } catch (GeneralSecurityException e) { 
     throw new IllegalStateException(e); 
    } 

} 
+0

Tôi không tái sử dụng lâu đài Bouncy thực hiện ECDSA.Tôi đang thực hiện trên của riêng tôi nhưng tôi đã gặp khó khăn về mã hóa của các thông số Domain để gửi chúng qua mạng như là một mảng byte duy nhất và họ nên được giải mã ở bên xác minh –

+1

Trong trường hợp đó tôi sẽ yêu cầu bạn nhìn vào permissive cơ bản Bouncy Castle thực hiện, nếu không để sao chép thì chỉ cần nhìn mã hóa X9.62 chuẩn của các tham số miền. BSI TR-03111 cũng có một phương pháp mã hóa (đơn giản) hơn. –

+1

Ví dụ này cũng có vẻ hoạt động trong JDK 1.8 ngoại trừ bạn cần chuyển "EC" cho KeyPairGenerator và KeyFactory. – kravietz

Các vấn đề liên quan