比特币地址表单验证JavaScript和PHP

比特币地址表单验证JavaScript和PHP,javascript,php,validation,bitcoin,Javascript,Php,Validation,Bitcoin,,但令人惊讶的是,对于两种常见的web语言,Javascript和PHP,却找不到任何东西 这里有一个用于Python的,但是有一个用于PHP和/或JS的吗 from hashlib import sha256 digits58 = '123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz' def decode_base58(bc, length): n = 0 for char in bc: n

,但令人惊讶的是,对于两种常见的web语言,Javascript和PHP,却找不到任何东西

这里有一个用于Python的,但是有一个用于PHP和/或JS的吗

from hashlib import sha256

digits58 = '123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz'

def decode_base58(bc, length):
    n = 0
    for char in bc:
        n = n * 58 + digits58.index(char)
    return n.to_bytes(length, 'big')

def check_bc(bc):
    bcbytes = decode_base58(bc, 25)
    return bcbytes[-4:] == sha256(sha256(bcbytes[:-4]).digest()).digest()[:4]

if __name__ == '__main__':
    bc = '1AGNa15ZQXAZUgFiqJ2i7Z2DPU2J6hW62i'
    assert check_bc(bc)
    assert not check_bc( bc.replace('N', 'P', 1) )
    assert check_bc('1111111111111111111114oLvT2')
    assert check_bc("17NdbrSGoUotzeGCcMMCqnFkEvLymoou9j")

:


var address=“1Eym7pyJcaambv8FG4ZoU8A4xsiL9us2zz”;
如果(检查(地址)){
document.getElementById('text').innerHTML+=“有效”;
}否则{
document.getElementById('text').innerHTML+=“无效”;
}
功能检查(地址){
var decoded=base58_decode(地址);
如果(decoded.length!=25)返回false;
var cksum=decoded.substr(decoded.length-4);
var rest=decoded.substr(0,decoded.length-4);
var good_cksum=hex2a(sha256_摘要)(hex2a(sha256_摘要(rest)))。substr(0,4);
如果(cksum!=good_cksum)返回false;
返回true;
}
函数base58_解码(字符串){
变量表='123456789abcdefghjklmnpqrstuvxyzabcdefghijkmnopqrstuvxyz';
var table_rev=新数组();
var i;
对于(i=0;i<58;i++){
表_rev[表[i]]=int2bigInt(i,8,0);
} 
var l=字符串长度;
var long_值=int2bigInt(0,1,0);
var num_58=int2bigInt(58,8,0);
var c;
对于(i=0;i0)输出=重复(“\0”,nPad)+str;
返回输出;
}
函数hex2a(hex){
var-str='';
对于(变量i=0;i


基于上述答案,我编写了一个简单的PHP库。可以找到:


以下是@Tim Peterson的答案的更好版本。它修复了他正在使用的base58实现(该实现不会验证地址“12ejmb3cmgrinveskza7g7kxw32gsbo2dhf”)

我将验证代码与所有需要的库结合起来,删除了许多不需要的库。它只公开了一个api:“checkAddress”。我为它创建了一个小主页,您可以在其中下载模块源代码或简化版本:

已纠正的base58_解码(从):

//来自https://github.com/cryptocoinjs/bs58
//Base58编码/解码
//最初由Mike Hearn为BitcoinJ撰写
//版权所有(c)2011谷歌公司
//由Stefan Thomas移植到JavaScript
//Stephen Pair从base58本机进行的合并缓冲区重构
//版权所有(c)2013比特支付公司
变量字母表='123456789ABCDEFGHJKLMNPQRSTUVWXYZABDEFGHJKMNOPQRSTUVWXYZ'
var字母表_映射={}
对于(变量i=0;i>8
字节[j]&=0xff
}
while(携带){
字节数。推送(进位和0xff)
进位>>=8
}
}
//处理前导零
对于(i=0;字符串[i]='1'&&i

下面是一个简短而现代的Javascript实现,它依赖于:

从“crypto js/sha256”导入sha256
从“crypto js”导入CryptoJS
函数isbtcadAddress(地址){
如果(!/^[13][a-km-zA-HJ-NP-Z1-9]{25,34}$/.test(address))返回false
常量缓冲长度=25
let buffer=new Uint8Array(bufferLength)
常量数字58='123456789abcdefghjklmnpqrstuvxyzabefghijkmnopqrstuvxyz'
对于(变量i=0;i=0;--j){
//num<256,所以我们只需将其添加到最后一个
const result=buffer[j]*58+进位+(j==bufferLength-1?num:0)

buffer[j]=result%(1对于使用javascript的用户,可以使用javascript插件

<script src="wallet-address-validator.min.js"></script>

// WAValidator is stored in the windows object
这是一个很好的正则表达式,我已经把它变成了一个函数,只适用于非segwit地址

function validate_bitcoin_address(btc_address)
 {
     return btc_address.match("^[13][a-km-zA-HJ-NP-Z1-9]{25,34}$") !== null;
 }

 alert(validate_bitcoin_address("16CbQcqDtBak5NzPbmFP1v9Pi4DwP5G4Wn")); //example usage
正则表达式匹配以下字符串:

  • 以1或3开头
  • 之后,输入a-z、a-z或0-9的25到34个字符,但不包括l、I、O和0

正则表达式不包括比特币地址中不允许的字符(l、I、O和0)

这个问题似乎离题了,因为它是关于为您编写代码的。我还能问什么呢?我只是举了一个Python的例子。只是想了解一些真知灼见……您可以自己尝试一下——如果您对某个特定部分有问题,在彻底研究之后,您可以询问该部分。如果您想做些什么完成了,雇佣。如果你想自己做,试着问为什么人这么有毒?Q+a网站也是。他在问一个问题。不是所有的代码问题都需要你
<?php
class Btc_address_validator {

    /**
     * [validate description]
     * @param  String $address BTC Address string
     * @return Boolean validation result
     */
    public function validate($address)
    {        
        $addr = $this->decode_base58($address);
        if (strlen($addr) != 50)
        {
          return false;
        }        
        $check = substr($addr, 0, strlen($addr) - 8);
        $check = pack("H*", $check);
        $check = strtoupper(hash("sha256", hash("sha256", $check, true)));
        $check = substr($check, 0, 8);
        return $check == substr($addr, strlen($addr) - 8);
    }
    private function encode_hex($dec)
    {
        $hexchars = "0123456789ABCDEF";
        $return = "";
        while (bccomp($dec, 0) == 1)
        {
            $dv = (string) bcdiv($dec, "16", 0);
            $rem = (integer) bcmod($dec, "16");
            $dec = $dv;
            $return = $return . $hexchars[$rem];
        }
        return strrev($return);
   }
    /**
    * Convert a Base58-encoded integer into the equivalent hex string representation
    *
    * @param string $base58
    * @return string
    * @access private
    */
    private function decode_base58($base58)
    {
        $origbase58 = $base58;    
        $base58chars = "123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz"; 
        $return = "0";
        for ($i = 0; $i < strlen($base58); $i++)
        {
          $current = (string) strpos($base58chars, $base58[$i]);
          $return = (string) bcmul($return, "58", 0);
          $return = (string) bcadd($return, $current, 0);
        }
        $return = $this->encode_hex($return);
        //leading zeros
        for ($i = 0; $i < strlen($origbase58) && $origbase58[$i] == "1"; $i++)
        {
          $return = "00" . $return;
        }
        if (strlen($return) % 2 != 0)
        {
          $return = "0" . $return;
        }
        return $return;
    }
}
// from https://github.com/cryptocoinjs/bs58
// Base58 encoding/decoding
// Originally written by Mike Hearn for BitcoinJ
// Copyright (c) 2011 Google Inc
// Ported to JavaScript by Stefan Thomas
// Merged Buffer refactorings from base58-native by Stephen Pair
// Copyright (c) 2013 BitPay Inc

var ALPHABET = '123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz'
var ALPHABET_MAP = {}
for(var i = 0; i < ALPHABET.length; i++) {
  ALPHABET_MAP[ALPHABET.charAt(i)] = i
}
var BASE = 58

function base58_decode(string) {
  if (string.length === 0) return []

  var i, j, bytes = [0]
  for (i = 0; i < string.length; i++) {
    var c = string[i]
    if (!(c in ALPHABET_MAP)) throw new Error('Non-base58 character')

    for (j = 0; j < bytes.length; j++) bytes[j] *= BASE
    bytes[0] += ALPHABET_MAP[c]

    var carry = 0
    for (j = 0; j < bytes.length; ++j) {
      bytes[j] += carry

      carry = bytes[j] >> 8
      bytes[j] &= 0xff
    }

    while (carry) {
      bytes.push(carry & 0xff)

      carry >>= 8
    }
  }

  // deal with leading zeros
  for (i = 0; string[i] === '1' && i < string.length - 1; i++) bytes.push(0)

  bytes = bytes.reverse()
  output = '';
  for (i=0; i<bytes.length; i++) {
      output += String.fromCharCode(bytes[i]);
  }
  return output;
}
import sha256 from 'crypto-js/sha256'
import CryptoJS from 'crypto-js'

function isBTCAddress (address) {
  if (!/^[13][a-km-zA-HJ-NP-Z1-9]{25,34}$/.test(address)) return false
  const bufferLength = 25
  let buffer = new Uint8Array(bufferLength)
  const digits58 = '123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz'
  for (var i = 0; i < address.length; i++) {
    const num = digits58.indexOf(address[i])
    // buffer = buffer * 58 + num
    let carry = 0
    for (var j = bufferLength - 1; j >= 0; --j) {
      // num < 256, so we just add it to last
      const result = buffer[j] * 58 + carry + (j === bufferLength - 1 ? num : 0)
      buffer[j] = result % (1 << 8)
      carry = Math.floor(result / (1 << 8))
    }
  }
  // check whether sha256(sha256(buffer[:-4]))[:4] === buffer[-4:]
  const hashedWords1 = sha256(CryptoJS.lib.WordArray.create(buffer.slice(0, 21)))
  const hashedWords = sha256(hashedWords1).words
  // get buffer[-4:] with big-endian
  const lastWordAddress = new DataView(buffer.slice(-4).buffer).getInt32(0, false)
  const expectedLastWord = hashedWords[0]
  return lastWordAddress === expectedLastWord
}
<script src="wallet-address-validator.min.js"></script>

// WAValidator is stored in the windows object
var valid = WAValidator.validate('12h7E1q5UUoPgZ1VtcYb57maFF9Cbk4u5X','BTC','both');
if(valid){
    alert('This is a valid address');
} else {
    alert('Address INVALID');
}
// will alert "This is a valid address"

var valid = WAValidator.validate('12h7E1q5UUoPgZ1VtcYb57maFF9Cbk4u5X', 'ETH', 'both');
if(valid){
    alert('This is a valid address');
} else {
    alert('Address INVALID');
}
// will alert "Address INVALID"
function validate_bitcoin_address(btc_address)
 {
     return btc_address.match("^[13][a-km-zA-HJ-NP-Z1-9]{25,34}$") !== null;
 }

 alert(validate_bitcoin_address("16CbQcqDtBak5NzPbmFP1v9Pi4DwP5G4Wn")); //example usage