Sawtooth 整个框架里缺少钱包的概念, 这里我们我们探讨一下为Sawtooth建立一个钱包。
钱包用来做什么:
1. 保存个人私钥/公钥: 这应该是钱包最核心的功能。 在Sawtooth的JDK里,我们可以看到,使用私钥为Transaction header签名,来保证事务安全。
2. 收入/支出账户: 在比特币/以太坊中,都使用由私钥派生的地址,来作为接收和发送地址,这也是叫钱包都有来,所以,进行各种虚拟币交易时钱包的一个重要功能。
3. Dapp载体: 就像小程序和微信的关系,钱包可以包含各种Dapp,所以C端用户只要有个钱包,就可以有很多的应用功能。
在联盟连中,我们更关心的1和3的使用,2几乎可以忽略掉。
钱包的密钥/公钥设计
Sawtooth和以太坊一样都采用secp256k1生成密钥,256bit的私钥,64个19进制字符。所以理论上说,以太坊的钱包中生成私钥/公钥的机制是可以直接拿来用的。所以,我们可以选择使用一个开源以太坊钱包的基础上开发。
以太坊的地址是在将public 使用Keccak-256算法hash以后 取最后20 bytes获得,例如:(0x表示16进制)
0x001d3f1ef827552ae1114027bd3ecf1f086ba0f9
在Sawtooth中,我们将新建一个Account Family, 根据sawtooth的架构,一个地址由70个charactor,35个bytes。其中头三个byte用于Family的命名空间,剩余32bytes为地址寻址标志。
为了和以太坊兼容,并且支持跨链交易。最后20bytes我们用于Sawtooth钱包地址;从第倒数第21个bytes到倒数第23个bytes我们预留为跨链标志。倒数第二三位到第四位默认填充为0.
这样我们从以太坊生成的地址,以可以直接在sawtooth使用,但使用的前提是需要注册认证。 Account Family 不仅提供一个同以太坊相同的地址,同样提供身份认证功能。在联盟连中,不存在匿名,未知的身份,包括个人。所以,在使用sawtooth钱包提供的任何功能时,需要进行身份验证。
在本文中我们将使用eth-lightwallet作为创建钱包的工具,eth-lightwallet支持符合browser, 支持利用BIP32和BIP39从一个随机生成的12个word的种子派生HD树。
BIP32:hierarchical deterministic (HD) wallet : BIP32定义的使一个包含树结构的公钥/私钥钱包。主要用途是方便管理多个密钥。只要管理好母私钥,就可以随时获得所有私钥。在联盟链场景里,每个用户大多数场景只需要一个认证的私钥即可。所以默认我们只生成一个公钥/私钥对。
BIP39:IP39描述了一个助记码或助记句(一组容易记住的单词)的实现,用于生成确定性钱包。目前是业界通用的助记词规范。
钱包的功能:
1. 生成密钥及eth地址: 在联盟连里,安全保证级别较高,所以我们提供两证必要生成方式:
a, 随机自动生成密钥,本地保存。
b. 服务器生成密钥,服务器代管。(通常在企业应用场合,这个方式更容易获得使用者的接受)
两种方式都使用keystore保存, 用户在使用签名时,只需要键入对应密码。eth-lightwallet提供的方法自动完成。
2. 身份认证
认证个人身份信息, 只有完成认证的用户才可以参与区块链的交易。
3. 签名服务
一个实现对内容进行签名的服务。
密钥/地址的生成Code:
这个Demo项目使用Ionic 构建的混合项目,可以支持在web端,移动端使用。
代码示例:
generateWallet(nickname:string,password:string):Wallet{
this.mywallet={nickname:nickname,
password:password,
address:"",
privatekey:"",
seedPhrase:"",
publickey:""
};
var prikey;
var pubkey;
// generate a new BIP32 12-word seed
var seedPhrase = lightwallet.keystore.generateRandomSeed();
this.mywallet.seedPhrase=seedPhrase;
lightwallet.keystore.createVault({
password: password,
seedPhrase: seedPhrase,
hdPathString: "m/0'/0'/0'"
}, (err, ks:Keystore)=> {
if (err) throw err;
console.log("adress : /s" ,ks);
ks.keyFromPassword(password, (err, pwDerivedKey ) =>{
if (err) throw err;
// generate one new address/private key pairs
// the corresponding private keys are also encrypted
ks.generateNewAddress(pwDerivedKey, 1);
var addr = ks.getAddresses()[0];
this.mywallet.address=addr;
console.log("adress : %s" , this.mywallet.address);
prikey=ks.exportPrivateKey(addr,pwDerivedKey);
this.mywallet.privatekey=prikey;
console.log("private key : %s" , this.mywallet.privatekey);
//get public key from private key
// pubkey=ks._computePubkeyFromPrivKey(prikey, 'curve25519');
// console.log("public key : /s" , pubkey);
//let pub_key=ks._computePubkeyFromPrivKey(prikey,'curve25519');
//this.mywallet.publickey=pub_key;
//console.log("ks public key " + pub_key);
});
});
return this.mywallet;
}
代码可以从eth-lightwallet的示例中获取。
界面端我们并不想提供复杂的功能给用户。 联盟链的用户,应该轻松的建立起来账户。 所以这里,我们使用随机方式生成符合BIP 39的种子。 用户也不需要知道PrivateKey是什么, 相反用户只需要输入昵称、账户密码,客户端将帮助用户生成相应的private key, public key.
这里面的一个浅显道理, 大多数用户只需要知道这个应用是基于区块链, 但是使用起来不能比常见的互联网软件更麻烦。
生成账户以后, 用户需要填写必要的信息,来完成身份验证; 实际上,联盟链环境中,应用必须符合国家法规。一个经过实名身份验证的账户是必要的。 怎么在区块链中完成身份验证呢, 这里我们使用第三方组织验证的方式,将账户的申请和身份的验证合起来:
1. 用户在客户端生成账户: 密码,私钥,公钥
2. 用户填写个人身份验证信息, 姓名等身份信息,并签名。
3. 用户提交以上信息及签名。
4. 第三方组织审核信息,并签名,生成两个事务: 身份证明,创建地址空间。
5。提交至区块链。
6。sawtooth 区块链接收相应事务, 验证并创建身份证明, 创建个人地址空间,并带上证明。
7。到此, 用户已经在sawtooth区块链上拥有一个带有身份证明的地址(对应的是公钥)。
这里,我们使用protobuff 文件定义了一个证明对象。
message Certification{
enum Certtype{
IDENTITY_CERTIFICATION= 0;
RIGISTEDDOCTOR_CERTIFICATION= 1;
}
string address= 1;
string publickey= 2;
string name= 3;
string idnumber= 4;
string certname=5;
string orgname=6;
string orgpubkey=7;
Certtype certtype=8;
repeated Attribute certatt=9;
string issuedate=10;
}
用户需要输入以上的必要信息,并使用私钥做一个签名, 这里用了bitcoin-ts公布的接口, eth-lightwallet没有直接可用的,所以后面需要把生成钱包的方法也使用bitcoin-ts来实现。
import { instantiateSecp256k1, Secp256k1,hexToBin ,Sha256,instantiateSha256,binToHex} from 'bitcoin-ts';
const secp256k1:Secp256k1 = await instantiateSecp256k1();
const sha256b:Sha256 = await instantiateSha256();
let meshash=sha256b.hash(decodeUTF8(sgincont));
//console.log("message hash256 : " + meshash);
let signatures=secp256k1.signMessageHashCompact(hexToBin(privatekey),meshash);
完成签名后,调用后台Restful接口,提交第三方机构处理。后台调用的接口信息大体如下。
整个请求中,包含address 和 publickey address将用于在sawtooth中为用户创建地址空间, idinfo 是该用户的身份证明,以及本人的签名,确保本人信息的正确性。










网友评论