PBC Library Manual(PBC庫手冊)翻譯(二)

目錄

2.教程(Tutorial)

2.1.BLS簽名

2.2.導入與導出


2.教程(Tutorial)

本章將介紹如何使用PBC庫實現Boneh-Lynn-Shacham(BLS)簽名方案。這是基於文件example/bls.c。

給出三個素數階羣G1、G2、GT(其實這三個都是循環羣,素數階羣必定是循環羣)。雙線性映射從G1選擇一個元素,從G2中選擇一個元素,並輸出一個GT中的元素。我們將這些與系統參數g一起發佈,其中g是G2中隨機選擇的元素。

Alice想要簽名一個信息,她生成公私鑰對,私鑰是Zr中的隨機元素x,相應的公鑰是g^x。

爲了簽名一個信息,Alice先將這個信息散列(hash)到G1的一些元素h上,然後輸出簽名h^x。

爲了去驗證簽名σ,Bob檢查e(h, g^x) = e(σ, g)。

我們現在使用PBC庫將上述轉化爲C代碼。

2.1.BLS簽名

首先包含pbc/pbc.h:

#include <pbc.h>

然後初始化一個pairing:

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);

然後,我們在標準輸入上爲程序提供pairing參數。param子目錄下的任何文件都可以,例如:

$ bls < param/a.param

我們需要幾個element_t參數來保存系統參數、密鑰和其它的數量。我麼聲明並初始化它們,

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值。許多庫都可以實現這個操作,而且這個操作不涉及pairing,所以PBC庫就沒有提供這一步的函數。例如,我們的信息已經被hash,可能用到了其它的庫。

假設這個消息的hash是"ABCDEF"(一個48比特的hash)。我們將這些字節映射到一個G1的元素h,

element_from_hash(h, "ABCDEF", 6);

然後簽名它:

element_pow_zn(sig, h, secret_key);

爲了去驗證這個簽名,我們比較應用於簽名和系統參數的pairing輸出,和應用於消息hash和公鑰的pairing輸出。如果兩個pairing的輸出是匹配的則簽名是有效的。

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");
}

2.2.導入與導出

爲了使簽名有用,在某些階段簽名必須轉換爲字節進行存儲或者傳輸:

int n = pairing_length_in_bytes_compressed_G1(pairing);
// 與下一行二選一
// int n = element_length_in_bytes_compressed(sig);
unsigned char *data = malloc(n);
element_to_bytes_compressed(data, sig);

在另一端,簽名必須被解壓:

element_from_bytes_compressed();

在上面的代碼中省略_compression也可以,但是緩衝區data大約需要是兩倍。

我們也可以只使用簽名的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_compressed(data, sig);

但是,由於兩個不同的點具有相同的x座標,因此在驗證過程中比較複雜。解決這個問題的一種方法是猜一個點,然後試着去驗證。如果失敗了我們再去嘗試另一個。我們可以看出,這兩個點的pairing輸出是互逆的,避免了二次計算pairing的需要。(事實上,還有更好的辦法解決這個問題。)

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");
    }
}

 注:刪除線部分是翻譯不通順或者可能有錯誤的地方。

 
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章