BLS簽名-使用PBC庫

BLS簽名-使用PBC庫

本篇博客將介紹如何使用PBC庫實現Boneh-Lynn-Shacham (BLS)簽名方案,該程序的源代碼文件是example/bls.c

我們有三個階爲素數r的羣G1、G2、GT,和一個雙線性映射,它能把一個來自G1的元素和一個來自G2的元素映射到GT對應的元素上。我們把這些與一個系統參數g一起發佈,g是G2中隨機選擇的一個元素

Alice選擇一個要簽署的消息,她通過如下的方法生成公鑰和私鑰,她的私鑰是1到r之間的隨機數,她對應的公鑰是gx

爲了簽名一個消息,Alice將這條消息的hash值映射到G1的元素h上,然後輸出這個簽名hx

爲了驗證簽名σ,Bob驗證這個等式e(h,gx)=e(σ,g)

現在我們使用PBC庫將這些轉化爲c代碼

  • 首先我們包含pbc/pbc.h文件

    
    #include <pbc.h>
    
  • 然後我們初始化一個雙線性配對

    pairing_t pairing;
    char param[1024];
    size_t count = fread(param, 1, 1024, stdin);
    if (!count) pbc_die("input error");
    pairing_init_set_buf(pairing, param, count);
  • 接着,我們通過改變我們程序的標準輸入重定向來接收雙線性配對的參數,param子目錄下的任意一個文件都可以,比如說:

    bls < param/a.param
  • 我們需要幾個element變量去保存系統參數。我們聲明並初始化他們

    element_t g, h;
    element_t public_key, secret_key;
    element_t sig;
    element_t temp1, temp2;
    
    element_init_G2(g, pairing);
    element_init_G2(public_key, pairing);
    element_init_G1(h, pairing);
    element_init_G1(sig, pairing);
    element_init_GT(temp1, pairing);
    element_init_GT(temp2, pairing);
    element_init_Zr(secret_key, pairing);
  • 生成系統參數

    element_random(g);
  • 生成密鑰

    element_random(secret_key);
  • 生成對應的公鑰

    element_pow_zn(public_key, g, secret_key);
  • 然後給一個消息去簽名。首先我們使用一些標準的hash算法去計算它的hash值。許多的庫可以這樣做,而且這個操作不涉及雙線性配對,因此PBC不提供這一步的函數。公佈這個消息的hash值是“ABCDEF”(一個48位的hash值),我們將這些比特映射到G1的一個元素h上

    element_from_hash(h, "ABCDEF", 6);
  • 生成簽名

    element_pow_zn(sig, h, secret_key);
  • 爲了驗證這個簽名,我們將簽名、系統參數g和雙線性配對生成的值與h、公鑰和雙線性配對生成的值進行比較。如果這兩個輸出匹配,說明這個簽名是有效的

    pairing_apply(temp1, sig, g, pairing);
    pairing_apply(temp2, h, public_key, pairing);
    if (!element_cmp(temp1, temp2)) {
      printf("signature verifies\n");
    } else {
      printf("signature does not verify\n");
    }
  • 爲了有用,在某些階段必須將簽名轉化爲字節才能存儲或傳輸

    int n = pairing_length_in_bytes_compressed_G1(pairing);
    // Alternatively:
    // int n = element_length_in_bytes_compressed(sig);
    unsigned char *data = malloc(n);
    element_to_bytes_compressed(data, sig);
  • 在另一方面,這個簽名必須能夠解壓

    element_from_bytes_compressed(sig, data);
  • 省略 _compressed 在上面的代碼中同樣也能工作,但是緩衝區的大小大概會變爲兩倍

  • 通過使用僅僅適用於簽名的x-coordinate,我們能夠節省更多的空間

    int n = pairing_length_in_bytes_x_only_G1(pairing);
    // Alternative:
    //   int n = element_length_in_bytes_x_only(sig);
    unsigned char *data = malloc(n);
    element_to_bytes_compressed(data, sig);
  • 但是由於有兩個不同的點有相同的x座標,在驗證的時候會比較複雜。一種解決辦法是選取一個點並試圖去驗證,如果失敗了,我們在去嘗試另外一個。可以看出這兩個點互爲逆元,避免了第二次計算雙線性映射(實際上這是一個更好的處理問題的辦法)

    int n = pairing_length_in_bytes_x_only_G1(pairing);
    //int n = element_length_in_bytes_x_only(sig);
    unsigned char *data = malloc(n);
    
    element_to_bytes_x_only(data, sig);
    
    element_from_bytes_x_only(sig, data)
    
    pairing_apply(temp1, sig, g, pairing);
    pairing_apply(temp2, h, public_key, pairing);
    
    if (!element_cmp(temp1, temp2)) {
      printf("signature verifies on first guess\n");
    } else {
      element_invert(temp1, temp1);
      if (!element_cmp(temp1, temp2)) {
          printf("signature verifies on second guess\n");
      } else {
          printf("signature does not verify\n");
      }
    }
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章