第8课 账号相关概念:公钥/私钥/Public Key Hash/P2PKH

在前面第2课,我们粗略引入了比特币网络中账号的概念。在此课,我将对账号相关的几个概念,做更深入的阐释,这部分也是整个区块链技术的基础。

有兴趣朋友也可以进一步关注公众号“架构之道与术”, 获取原文。
或扫描如下二维码:
这里写图片描述

一、公/私钥
公/私钥的基本思路是:每个用户生成1对公/私钥,相当于账号与密码。

A给B转账,先用A的私钥签名,再把钱打入B的公钥,只有B能用自己的私钥解密。

这里有2个关键点:(1)这笔交易是公开的,其他人都可以看到,但只有B有私钥,可以解锁这笔钱。(2)A的公钥也是公开的,虽然B不知道A的私钥,但B可以用A的公钥来验证,这笔交易的签名用的是A的公钥对应的私钥,证明了这笔钱是A转给B的,而不是C转给B的。

反之亦然,B给A转账,先用B的私钥签名,再把钱打入A的公钥。A收到这笔交易,同样的可以验证上面的2点。

二、比特币地址(钱包地址)
在上面呢,通俗的介绍了公/私钥的大致思路。但在比特币网络里,实际是有4个概念:
私钥(Private Key)
公钥(Public Key)
公钥Hash (Public Key Hash)
钱包地址(Bitcoin Address)

下面这张图展示了这4个概念之间的关系,以及生成机制:

Private Key:随机生成的1长串数字

Public Key: 通过椭圆曲线函数,由私钥生成公钥。

Public Key Hash: 由Public Key,经过Hash160的计算得到。所谓Hash160,是指先进行1次SHA256运算,再进行1次RIPEMD160运算,最后算出来的Public Key Hash是160 bits。

Bitcoin Address: 把Public Key Hash,经过Base58Check编码,得到Bitcoin Address,也就是交易转账最终用的地址。

这里面有几个关键点:
(1)由箭头可以看出,前2个转换是单向的,不可逆。公钥是公开的,但没办法通过公钥反算出私钥;也没办法通过Public Key Hash 反算出Public Key。

(2)最后1个是可逆的,一个Encode/Decode的过程。
所以你可以认为,Public Key Hash 和 Bitcoin Address本质是一个东西,只是编码方式不一样。

(3)那为什么不直接拿Public Key当Bitcoin Address,而要再加1层 Public Key Hash呢?
这就涉及到1个抽象的问题。在比特币网络中,Bitcoin Address是一个抽象的概念,在这个场景中,背后代表的是Public Key;在其他场景中,可能是一个Script Hash,而不是Public Key Hash。
关于用Script Hash做比特币地址,是个很关键的话题,后面会专门讲述。

三、签名
签名公式如下:
Sig = Fsig(Fhash(transaction), private key)

也就是,先对Transaction进行1次Hash运算,把这个Hash值 + private key,经过一个签名函数的计算,得到签名值。

关键点:签名是用私钥来签的,以此来证明转账的钱,是来自“我”。

四、基本交易类型 P2PKH
有了比特币地址,其实也就是Public Key Hash,就有了一个最常见的交易类型,叫做P2PKH(Pay to Public Key Hash),付款给对方的Public Key Hash。

另外一个交易类型,就是P2SH(Pay to Scirpt Hash),后面会专门讲述。

五、总结
任何时候,A给B转账的一笔交易,都会先用A的私钥签名,再发给B的公钥(这里是Public Key Hash,而不是直接是Public Key)。

以此,达到2个目的:(1)证明了这笔钱的确是来自A (2)这笔钱,只有B能解锁,能使用。

A的私钥签名,叫做scriptSig;发给B的公钥,叫做scriptPubKey。
这2个东西非常关键,后面会详细讲解他们的运作机制。

你可以使用Crypto++库中的RSA类来导入RSA公钥/私钥的字符串表示。下面是一个简单的示例代码: ```c++ #include <iostream> #include <string> #include <cryptopp/rsa.h> #include <cryptopp/base64.h> using namespace CryptoPP; int main() { // RSA keys in PEM format std::string publicKeyPEM = "-----BEGIN PUBLIC KEY-----\n" "MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAvRJ9YmJ9A0seV0bSf+I6\n" "n5i6dF6qXl5Hf8b0KJvJ7eN0yTnE4t5rKQYdM+DLg1yXz+4kWv8xgJxJW9Q2gY7L\n" "wNqROnFJZrOq6zZVrWXfR4gWVv8grl2PZl6vQfGbdzPd2BhLW1QOyPZfGy1CCoMg\n" "FQd6ZqBx1UJHsUSx/PnV0i35S8zO7Zq9UxOYbRr9SiCsTJ0FNLwPz7CkC5u3VJ5D\n" "z5z2K7U0fGkO+8fOc5Qv2JUqKd6sN2oT+18+eVf/lvtlQ4U3aXyKZB7u0k8T3xKx\n" "3J2r3x4y+o9B3fz1aV0R/5N5Iz2Kt6gJyJmJyNfh0T+D5JLZL8o+Oq8rD8/8mLgV\n" "XQIDAQAB\n" "-----END PUBLIC KEY-----\n"; std::string privateKeyPEM = "-----BEGIN PRIVATE KEY-----\n" "MIIEvwIBADANBgkqhkiG9w0BAQEFAASCBKkwggSlAgEAAoIBAQCuN1Qa1iRQ9ZvZ\n" "iFfZjzKfKXk9X5Rq8Dp4CCVt1LJbXG8oU1Kd7UeJb+JyQrK+D1hViDUKvC4pDvZL\n" "7Wv8wzZ1mJN+3M+Vc7dqSaTr0z+U4d3ZKQKj1UjF9/3Ud/HXw6Ez84Zx5fX1U7P\n" "3u9Qo+6g0cva0tYcZ8E4m8osjzOZn3n5Z+qoDZ2IuoktDjQOdT7vZJc7JmLQ+6U\n" "Gyf8B4j0c6V7iJ0oqOeq27m2xY6xu9gKwDvZl9zJrFv6f9JQy6yY5ZjXVItK8o+\n" "x3DfX+eD8XO7Z0f1wO3J5lXgBuJop4B3PzZPmZw3jwN3LZwU7hAqjWQvLj5r+DqR\n" "KwvS6TJnAgMBAAECggEBAJv9zZ1N9sN7E+gTt9y/7xFG2PjgB9VjYWg6bd4QKpRq\n" "zGJNj2n8q6k8l7k2uT6sRcO5RhS8bQpO4iLl3GJXZr5kjC0Z/1kE1p4H8Y9e5bDh\n" "gNl3ZnK3Wpli8q7KqUjOY8j6Ktj7+vZnT3sW6v/qpIbQgBn7d3q0qsqzjTm8c5f\n" "V3JzUJqkVJqX1mJmJd6tZslpO8mJyZL/vkC4KszkQeE8xKu6sIiA4r6l5e0+OJ8M\n" "8XmXhV8D8ZcHgKvq7qrBvFq5Xv2mHsLdQO+J7uNLC3iQzY3u4jB6Gk8fN7N3e3jv\n" "dDmf8P0l7dOj6q5sZtqoK6fJjW+PcVnC8KzXUy4YrtkCgYEA3g9W5c7J8KmX3xSU\n" "2p/7VfGzBYC7J1Ll1fz4qWf3XZ2VQF7q6yRrA5X+H2GkZiB3vL8/3gOeO3WuGnI0\n" "bJr1lOY9xMvQj7a6KdC5h4Wvmt3qqh6VdQw7dFx8fJ8x5RQwReOuyZ9nEE5Vf+en\n" "cRg9Uk9LQl3rZ4cazH7c+Lkrj2ECgYEAzL4u8eJ5gCpUvJZJyCmlrJX0GryL1wzE\n" "5zO8m1tjwg1YONyJvR4g4bd7p+56q6v3wTzoumH6x3AWDZC8Z6Jr6i4a8+cnl+9M\n" "P+Jr5Lr2fN2Y7w3dFzHhY5NIR0ZxTQJdC5Jp+el1+Kg2y4eFJZpQz0ueH2Jy6wuz\n" "zqJUQY2RmXUCgYEAwYjQg1FnKPGvJlRrXwL9cO4I3W0gx/kD+LpT8aEguJlRf4uS\n" "ZyN8a+xLZbGzWc5wKT9z3whYf4fXf4aFh2U+ZQzXG7yUa5KdNf7xvP8QXa6omQY0\n" "sQO2e1+Vc1r7h2e0HNY0U6E0g+7l7MBZv5lZP6XG7HdY5k8n1UdbvR9uGkECgYEA\n" "xAIlWc+0qLQUjY7t2sqHjzJ3nV2GxMvW0G9fZgD6loQWtKX2Y7r/x6WLZ9Smc5ZQ\n" "4QJ1l0sT1q2YKqCwR1u+2J9lX8Pp17FZK8Xvq8kPT9lQK9o3+JvUqPvX6xrmJ2mK\n" "R7uxvYv+ZzL2R9gkt/6g1QH0aRZzZj0+6+J5PfWen9sCgYEA7fQxJYJdQdUgJvZL\n" "gH2Y1o5LJ5W1N3v9zQJLJGJ1Tt7TfB3gXzOzL/hsW68Uzr+1JqP6e9LTk5OuWVQG\n" "yR7zFv3p6K5tqT2Z0OJdS4xVw/2zB5YzJiK6I6b5aMZr9o2ZtW/0A1m5RcU6bJSo\n" "Vz5Q5O1ZoD7JdS3d+6iNq+f8dQ==\n" "-----END PRIVATE KEY-----\n"; // Base64 decode the PEM strings std::string publicKeyStr, privateKeyStr; StringSource(publicKeyPEM, true, new Base64Decoder(new StringSink(publicKeyStr))); StringSource(privateKeyPEM, true, new Base64Decoder(new StringSink(privateKeyStr))); // Load the keys from the decoded strings RSA::PublicKey publicKey; RSA::PrivateKey privateKey; StringSource(publicKeyStr, true, new PEMDecoder(new StringSink(publicKey))); StringSource(privateKeyStr, true, new PEMDecoder(new StringSink(privateKey))); return 0; } ``` 在这个示例中,我们将PEM格式的RSA公钥/私钥字符串进行Base64解码,然后使用Crypto++库中的PEMDecoder类将它们加载到RSA::PublicKey和RSA::PrivateKey对象中。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值