关于手机App的Https抓包

我喜欢用 Mitmproxy 来处理手机 App 抓包之类的工作,本来用它来抓 Https 包是很容易的一件事,只要设置好代理,浏览 mitm.it 按提示安装证书即可,可是当 Android 版本升级到 7 以后,此方法就失效了,为什么呢?因为新版 Android 缺省情况下只信任系统级证书,而不再信任用户级证书,问题详细描述可以参考:听说安卓微信 7.0 不能抓 https?

继续阅读

聊聊AES

说起加密,通常分为对称加密和非对称加密,所谓对称加密中的对称,指的是加密和解密使用的是同一个密钥,如此说来什么是非对称就不用我多做解释了。对称加密相对于非对称加密而言,优点是速度快,缺点是安全性相对低一点,不过只要能保证密钥不泄露,其安全性还是有保证的,所以在实际项目中,对称加密的使用非常广泛。

继续阅读

To panic or not to panic

大家都知道 Golang 推荐的错误处理的方式是使用 error,这主要得益于 Golang 方法可以返回多个值,我们可以很自然的用最后一个值来表示是否有错误,这一点是其它很多编程语言所不具备的,不过这多少让那些习惯了 exception 的程序员无所适从,虽然 Golang 没有 exception,但是实际上可以通过 panic/recover 来模拟出类似的效果,于是很多 Gopher 在错误处理的时候开始倾向于直接 panic。

继续阅读

推导利滚利公式

自从开始学习智能合约之后,接触到了很多「资金盘」游戏,比如前段时间大火的 Fomo3D,不过自从 333ETH 崩盘之后,此类游戏暂时已经没有市场了,因为本质上来说,它们都属于庞氏骗局,在研究相关代码后,让我对利滚利公式产生了一点兴趣,其实很简单,但我年纪大了,实实在在推导了好几遍才搞定,索性把推导过程记录下来。

继续阅读

以太坊地址区分大小写么

以太坊地址区分大小写么?要搞清楚这个问题,我们不妨先在私链上做个实验:

geth> eth.sendTransaction({
    from: eth.accounts[0],
    to: "0xaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa",
    value: web3.toWei(1, 'ether')
})

geth> eth.sendTransaction({
    from: eth.accounts[0],
    to: "0xAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA",
    value: web3.toWei(1, 'ether')
})

geth> eth.getBalance("0xaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa")
geth> eth.getBalance("0xAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA")

从实验结果上来看,纯小写地址和纯大写地址实际上是同一个地址,那么是不是由此可以得出以太坊地址不区分大小写呢?我们再看下面这个 remix 上的实验:

pragma solidity ^0.5.0;

contract Foo {
    address bar = 0xaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa;
}

代码运行结果如下图所示:

remix

remix

结果提示错误,并给了一个大小写混合的正确地址:

This looks like an address but has an invalid checksum. Correct checksummed address: “0xaAaAaAaaAaAaAaaAaAAAAAAAAaaaAaAaAaaAaaAa”. If this is not used as an address, please prepend ’00’. For more information please see https://solidity.readthedocs.io/en/develop/types.html#address-literals

怎么回事?实际上这是因为 EIP-55 规范引入了 checksum 机制。它有什么用处?设想一下,如果你在输入长长的以太坊地址的时候,不小心输错了一个字符,那么很难发现这样的错误,有了 checksum 机制,我们就能在业务程序里校验地址的准确性,从而降低用户输入错误地址的风险,给出一个 golang 代码的例子:

package main

import (
    "flag"
    "fmt"

    "github.com/ethereum/go-ethereum/common"
)

var (
    address = flag.String("address", "", "address")
)

func init() {
    flag.Parse()
}

func main() {
    addressWithChecksum := common.HexToAddress(*address).Hex()

    if addressWithChecksum != *address {
        fmt.Println("  valid: " + addressWithChecksum)
        fmt.Println("invalid: " + *address)
    } else {
        fmt.Println("This address is valid.")
    }
}

代码运行结果如下图所示:

checksum

checksum

如果你没有 Golang 的运行环境,实际上还有更简单的验证方法:通过 Etherscan 来获取带 checksum 的地址,留意地址栏中的地址和下面 Address 旁边的地址:

etherscan

etherscan

总结:以太坊地址本身不区分大小写,但是出于安全性的考虑,我们应该尽可能使用符合 EIP-55 规范的地址,当然了,业务程序要有相应的 checksum 校验逻辑才行。