Chave Privada WIF

Wallet Import Format

Uma chave privada WIF (Wallet Import Format) é um formato no estilo de endereço para uma chave privada.

É usada ao exportar e importar chaves privadas entre carteiras de bitcoin.

É principalmente uma codificação Base58 da chave privada, mas também inclui alguns dados extras úteis e um checksum.

Chave Privada WIF

crua e o Wallet Import Format.>Converta entre uma

1 byte
Red
0 bytes
1 byte
Comprimida
0 bytes

Base58 dos dados anteriores

0 caracteres

    Nunca introduza sua chave privada em um site, nem use uma chave privada gerada por um site. Os sites podem guardar facilmente a chave privada e usá-la para roubar seus bitcoins.

    Uma chave privada WIF é só outra forma de representar a sua chave privada. Se você tem uma chave privada WIF, sempre pode convertê-la de volta para uma chave privada bruta.

    Nunca revele a sua chave privada WIF. Uma chave privada WIF não é criptografada de forma alguma, então você precisa protegê-la tanto quanto protegeria uma chave privada bruta.

    Benefícios

    Por que usamos chaves privadas WIF?

    O principal benefício da WIF é que ela é uma codificação Base58 de uma chave privada, então é mais curta e mais fácil de copiar.

    Há alguns outros benefícios:

    Codificação

    Converter uma chave privada para WIF

    Diagrama mostrando como converter uma chave privada para WIF.

    Converter uma chave privada bruta para WIF é bem simples:

    1. Comece com uma chave privada hexadecimal de 32 bytes.
    2. Adicione um byte de versão no início. Isso indica se a chave privada está sendo usada em mainnet ou testnet:
      • 80 = mainnet
      • ef = testnet
    3. Adicione um byte de compressão no fim (opcional). Isso indica se a chave privada está sendo usada para criar uma chave pública comprimida ou não comprimida:
      • 01 = chave pública comprimida (mais comum)
      • (nenhum byte) = chave pública não comprimida
    4. Crie um checksum a partir dos dados acima e adicione-o ao fim.
      • Um checksum no Bitcoin são os primeiros 4 bytes do Hash256 de alguns dados.
    5. Converta todos os dados acima para Base58.

    E aí você tem uma chave privada WIF.

    Por exemplo:

                 1 byte                                  32 bytes              1 byte (opcional)    4 bytes
                 byte de versão                          chave privada         byte de compressão   checksum
                            ↓                                 ↓                               ↓     ↓
                            --|--------------------------------------------------------------|--|------|
    data                  = 80ef235aacf90d9f4aadd8c92e4b2562e1d9eb97f0df9ba3b508258739cb013db20166557e53
    
    base58encode(data)    = L5EZftvrYaSudiozVRzTqLcHLNDoVn7H5HSfM9BAN6tMJX8oTWz6

    Não use esta chave privada. Isto é apenas um exemplo. Você vai perder suas moedas se usá-la.

    Ícone Ferramenta Chave Privada

    Chave Privada

    Gere um número aleatório de 256 bits.

    Bits

    0b
    0 bits
    0d
    0x
    0 bytes

    Nunca use uma chave privada gerada por um site, nem digite sua chave privada em um site. Sites podem facilmente salvar a chave privada e usá-la para roubar seus bitcoins.

    Ícone Ferramenta Checksum

    Checksum

    Crie um checksum para alguns dados.

    Alguns bytes de dados para os quais você quer criar um checksum

    0 bytes

    Primeiros 4 bytes de hash256(dados)

    Esperado:

    Os dados originais com o checksum anexado

    0 bytes
    Ícone Ferramenta Base58

    Base58

    Converta entre hexadecimal e a codificação Base58.

    0 bytes

    ou uma chave privada WIF, por exemplo>Uma

    0 dígitos
     

    Código

    Ruby

    # ---------
    # Funções
    # ---------
    
    require 'digest'
    
    # função hash256 (checksums usam hash256)
    def hash256(hex)
      binary = [hex].pack("H*")
      hash1 = Digest::SHA256.digest(binary)
      hash2 = Digest::SHA256.digest(hash1)
      result = hash2.unpack("H*")[0]
      return result
    end
    
    # função checksum
    def checksum(hex)
      hash = hash256(hex) # passa os dados pelo SHA256 duas vezes
      return hash[0...8]  # retorna os primeiros 4 bytes (8 caracteres)
    end
    
    # função de codificação base58
    def base58_encode(hex)
      chars = %w[
          1 2 3 4 5 6 7 8 9
        A B C D E F G H   J K L M N   P Q R S T U V W X Y Z
        a b c d e f g h i j k   m n o p q r s t u v w x y z
    ]
      base = chars.length
    
      i = hex.to_i(16)
      buffer = String.new
    
      while i > 0
        remainder = i % base
        i = i / base
        buffer = chars[remainder] + buffer
      end
    
      # adiciona '1's no início conforme o número de bytes zero à esquerda
      leading_zero_bytes = (hex.match(/^([0]+)/) ? $1 : '').size / 2
    
      ("1"*leading_zero_bytes) + buffer
    end
    
    # ----------
    # WIF Encode
    # ----------
    
    # 1. comece com uma chave privada hexadecimal de 32 bytes
    privatekey = "ef235aacf90d9f4aadd8c92e4b2562e1d9eb97f0df9ba3b508258739cb013db2" # exemplo, não use
    
    # 2. adicione o prefixo (80 = mainnet, ef = testnet)
    data = "80" + privatekey
    
    # 3. adicione o byte de compressão (opcional)
    data = data + "01"
    
    # 4. adicione o checksum
    data = data + checksum(data)
    
    # 5. codifique em base58
    wif = base58_encode(data)
    
    # resultado
    puts wif #=> L5EZftvrYaSudiozVRzTqLcHLNDoVn7H5HSfM9BAN6tMJX8oTWz6

    Python

    import hashlib # função de hash SHA-256
    
    # 1. comece com uma chave privada hexadecimal de 32 bytes
    privatekey = "ef235aacf90d9f4aadd8c92e4b2562e1d9eb97f0df9ba3b508258739cb013db2" # exemplo, não use
    
    # 2. adicione o prefixo (80 = mainnet, ef = testnet)
    data = "80" + privatekey
    
    # 3. adicione o byte de compressão (opcional)
    data = data + "01"
    
    # 4. adicione o checksum (hash256 de prefixo+dados, depois pegue os primeiros 4 bytes)
    hash1 = hashlib.sha256(bytes.fromhex(data)).digest() # converte a string hex em bytes brutos antes de fazer o hash
    hash2 = hashlib.sha256(hash1).hexdigest() # retorna o resultado como string hex
    checksum = hash2[0:8] # o checksum são os primeiros 4 bytes
    data = data + checksum # adiciona o checksum ao fim dos dados
    
    # 5. defina os caracteres base58
    characters = ['1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'J', 'K', 'L', 'M', 'N', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z', 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z']
    
    # 6. converta os dados hex em inteiro para podermos convertê-los em base58
    i = int(data, 16)
    
    # 7. cria um buffer para guardar a string base58
    base58 = ''
    
    # 8. divide o inteiro por 58 repetidamente e pega o resto para descobrir cada caractere base58
    while i > 0:
      i, remainder = divmod(i, 58) # divide e pega o resto
      base58 = characters[remainder] + base58 # usa o resto para obter o caractere e o adiciona no início da string
    
    # nota: na codificação base58 normal você converte bytes 00 à esquerda em hex para 1s em base58, mas bytes zero à esquerda não aparecem ao criar uma chave privada WIF, então pulamos esse passo aqui
    
    # 9. mostra o resultado (chave privada WIF)
    print(base58) #=> L5EZftvrYaSudiozVRzTqLcHLNDoVn7H5HSfM9BAN6tMJX8oTWz6
    • Na mainnet, uma WIF deve começar com K, L ou 5.
    • Na testnet, uma WIF deve começar com c ou 9.

    Decodificação

    Converter de WIF para uma chave privada

    Diagrama mostrando como converter uma WIF para uma chave privada.

    É bem fácil extrair uma chave privada bruta de uma WIF:

    1. Comece com a chave privada WIF de 51 ou 52 caracteres.
    2. Decodifique-a de Base58.
      • Isso vai lhe dar 37 ou 38 bytes hexadecimais.
    3. A chave privada está contida nos bytes 1 a 33 (ou seja, ignore os primeiros 2 caracteres e depois pegue os 64 caracteres seguintes).

    Por exemplo:

    address               = L5EZftvrYaSudiozVRzTqLcHLNDoVn7H5HSfM9BAN6tMJX8oTWz6
    
    base58decode(address) = 80ef235aacf90d9f4aadd8c92e4b2562e1d9eb97f0df9ba3b508258739cb013db20166557e53
                            --|--------------------------------------------------------------|--|------|
                            ↑                                 ↑                               ↑     ↑
                            byte de versão               chave privada         byte de compressão   checksum
                            1 byte                       32 bytes              1 byte (opcional)    4 bytes

    Não use esta chave privada. Isto é apenas um exemplo. Você vai perder suas moedas se usá-la.

    Ícone Ferramenta Chave Privada WIF

    Chave Privada WIF

    crua e o Wallet Import Format.>Converta entre uma

    1 byte
    Red
    0 bytes
    1 byte
    Comprimida
    0 bytes

    Base58 dos dados anteriores

    0 caracteres

      Nunca introduza sua chave privada em um site, nem use uma chave privada gerada por um site. Os sites podem guardar facilmente a chave privada e usá-la para roubar seus bitcoins.

      Ícone Ferramenta Base58

      Base58

      Converta entre hexadecimal e a codificação Base58.

      0 bytes

      ou uma chave privada WIF, por exemplo>Uma

      0 dígitos
       

      Você também pode extrair dados adicionais da chave privada WIF (se precisar):

      • O primeiro byte é o byte de versão, que é usado para determinar se a chave privada deve ser usada em mainnet ou testnet.
        • 80 = mainnet
        • ef = testnet
      • O byte opcional após a chave privada é o byte de compressão, que é usado para determinar se a chave privada foi usada para criar uma chave pública comprimida ou não comprimida. Se ele não estiver lá (ou seja, você tem apenas 37 bytes depois de decodificar de Base58), isso indica uma chave pública não comprimida.
        • 01 = chave pública comprimida (mais comum)
        • (nenhum byte) = chave pública não comprimida
      • Os últimos 4 bytes são o checksum, que permite verificar se a WIF é válida ou não.

      Código

      Ruby

      # ---------
      # Funções
      # ---------
      
      # função de decodificação base58
      def base58_decode(base58_string)
      
        # caracteres base58
        base58_chars = "123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz"
      
        # define o valor inteiro inicial
        integer = 0
      
        # percorre cada caractere da string, da direita para a esquerda
        base58_string.reverse.each_char.with_index do |char, index|
      
          # obtém a posição do caractere na lista de caracteres base58
          char_index = base58_chars.index(char)
      
          # verifica se é um caractere base58 válido
          if !char_index
           puts "Não é um caractere Base58 válido: #{char}"
           exit
          end
      
          # multiplica a posição do caractere por uma potência de 58 (crescente conforme o índice de cada caractere)
          integer += char_index * (58**index)
        end
      
        # converte o inteiro em uma string hexadecimal
        hexadecimal = integer.to_s(16)
      
        # completa para garantir um número par de bytes
        if hexadecimal.bytesize.odd?
          hexdecimal = "0" + hexadecimal
        end
      
        # ignora strings base58 vazias
        if hexadecimal == "00"
          hexadecimal = ""
        end
      
        # conta o número de '1's à esquerda
        leading_zero_bytes = (base58_string.match(/^([1]+)/) ? $1 : '').size
      
        # converte os '1's à esquerda em '00's à esquerda
        if leading_zero_bytes > 0
          hexadecimal = ("00" * leading_zero_bytes) + hexadecimal
        end
      
        # retorna os bytes hexadecimais
        return hexadecimal
      end
      
      # ----------
      # WIF Decode
      # ----------
      
      # 1. comece com uma chave privada WIF
      wif = "L5EZftvrYaSudiozVRzTqLcHLNDoVn7H5HSfM9BAN6tMJX8oTWz6" # exemplo, não use
      
      # 2. decodifique de base58
      data = base58_decode(wif)
      
      # 3. extraia a chave privada (bytes 1 a 33)
      privatekey = data[2...66]
      
      # resultado
      puts privatekey #=> ef235aacf90d9f4aadd8c92e4b2562e1d9eb97f0df9ba3b508258739cb013db2

      Python

      # 1. comece com uma chave privada WIF
      wif = "L5EZftvrYaSudiozVRzTqLcHLNDoVn7H5HSfM9BAN6tMJX8oTWz6" # exemplo, não use
      
      # 2. defina os caracteres base58
      characters = ['1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'J', 'K', 'L', 'M', 'N', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z', 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z']
      
      # 3. converte a string base58 em inteiro
      
      # 3a. inverte a string base58 para trabalharmos da direita para a esquerda
      wif = wif[::-1]
      
      # 3b. define o valor inicial
      sum = 0
      
      # 3c. percorre cada caractere da chave privada WIF (a string base58)
      for i, c in enumerate(wif):
      
        # 3d. obtém o índice deste caractere a partir da lista de caracteres base58
        for index, base58_character in enumerate(characters): # forma simples de achar a chave na lista, mas funciona
          if (c == base58_character):
            character_index = index
            break # para de procurar
      
        # 3e. multiplica o índice do caractere por uma potência de 58 (aumentando a potência conforme a posição do caractere na string base58) e soma ao total
        sum += character_index * (58**i)
      
      # 4. converte o inteiro em hexadecimal
      hexadecimal = hex(sum)[2:] # remove o prefixo 0x usando [2:]
      
      # nota: na decodificação base58 normal você converte 1s à esquerda em base58 para bytes 00 à esquerda em hex, mas chaves privadas WIF nunca começam com 1, então pulamos esse passo aqui
      
      # 5. extrai a chave privada (ignora o prefixo, o byte de compressão e o checksum)
      privatekey = hexadecimal[2:66]
      
      # 6. completa a chave privada para que sempre apareça com 32 bytes (64 caracteres hexadecimais)
      privatekey = privatekey.zfill(64) # zfill completa com zeros no início até o comprimento desejado
      
      # 6. mostra o resultado
      print(privatekey) #=> ef235aacf90d9f4aadd8c92e4b2562e1d9eb97f0df9ba3b508258739cb013db2

      Uso

      Onde as chaves privadas WIF são usadas no Bitcoin?

      Captura de tela da ferramenta de varredura de chave privada na carteira Sparrow.
      A carteira Sparrow exige que você use WIF ao importar chaves privadas.

      Como mencionado, a WIF é usada quando você está exportando ou importando chaves privadas entre carteiras.

      Alguns exemplos de carteiras populares que usam WIF são:

      Pela minha experiência, é mais comum que as carteiras exijam que você trabalhe com chaves privadas WIF em vez de permitir importar/exportar chaves privadas brutas.

      História

      Quando as chaves privadas WIF foram introduzidas no Bitcoin?

      Pieter Wuille criou o formato WIF em 2011 para importar e exportar chaves privadas via Bitcoin Core.

      https://github.com/bitcoin/bitcoin/pull/574

      Agradecimentos a Murch e Ava Chow pela ajuda com a origem das chaves privadas WIF.

      Resumo

      A WIF foi projetada apenas para ser uma codificação mais amigável de uma chave privada.

      Você consegue identificar uma chave privada WIF porque ela é uma string Base58 e começa com K ou L. Em raras ocasiões ela começa com 5 (se, por algum motivo, você estiver trabalhando com chaves públicas não comprimidas). Por exemplo:

      Estes são exemplos estáticos de chaves privadas WIF. Não as use.

      Então, se você está trabalhando na mainnet com chaves públicas comprimidas como uma pessoa normal, procure o K ou o L no início.

      Pela minha experiência, pode ser um pouco chato ter que converter entre chave privada bruta e WIF quando você quer importar uma chave privada em uma carteira, mas é prática comum as carteiras trabalharem com WIF em vez de chaves privadas brutas, então é melhor você se acostumar.

      Se você trabalha com chaves privadas brutas localmente (e ocasionalmente quer importá-las/exportá-las), é uma boa ideia escrever o seu próprio codificador/decodificador WIF. A última coisa que você quer fazer é confiar suas chaves privadas a um site ou ferramenta, e não é difícil criar você mesmo uma ferramenta que converte entre WIF e uma chave privada bruta.

      Isso vai economizar tempo e estresse mais adiante. Confie em mim.

      Porque, como diz aquele velho ditado famoso: "Not Your Own WIF Tool, Not Your Coins" (Se a ferramenta WIF não é sua, as moedas não são suas).

      Ou algo assim.

      Recursos

      Ferramentas