海运的博客

golang/php使用aes加密文件

发布时间:April 28, 2020 // 分类:PHP // 1 Comment

兼容于golang语言版本:https://github.com/eliben/code-for-blog/blob/master/2019/aes-encrypt-file/aes-file.go
使用aes-256-cbc加密,加密文件前8字节为原始文件大小数字,跟着是16字节随机字节用作iv,再跟着是先补全的明文加密内容。

<?php
function decrypt($key, $infilename, $outfilename = "") {
  if (!$outfilename) {
    $outfilename = $infilename.'.dec';
  }
  $cipher_str = file_get_contents($infilename);
  if (!$cipher_str) {
    die("empty file".PHP_EOL);
  }
  $file_size = substr($cipher_str, 0, 8);
  $file_size = unpack("P", $file_size);
  $iv = substr($cipher_str, 8, 16);
  $cipher_str = substr($cipher_str, 24);
  $plain_str = openssl_decrypt($cipher_str, "aes-256-cbc", $key, 3, $iv);
  $plain_str = substr($plain_str, 0, $file_size[1]);
  file_put_contents($outfilename, $plain_str);
  echo "decrypted output file ".$outfilename.PHP_EOL;
}
function encrypt($key, $infilename, $outfilename) {
  if (!$outfilename) {
    $outfilename = $infilename.'.enc';
  }
  $plain_str = file_get_contents($infilename);
  if (!$plain_str) {
    die("empty file".PHP_EOL);
  }
  $file_size = strlen($plain_str);
  $file_size = pack("P", $file_size);
  $iv = random_bytes(16);
  if (strlen($plain_str) % 16 != 0) {
    $bytesToPad = 16 - (strlen($plain_str) % 16);
    $plain_str = $plain_str . random_bytes($bytesToPad);
  }
  $cipher_str = openssl_encrypt($plain_str, "aes-256-cbc", $key, 3, $iv);
  $cipher_str = $file_size.$iv.$cipher_str;
  file_put_contents($outfilename, $cipher_str);
  echo "encrypted output file ".$outfilename.PHP_EOL;
}
$arg = getopt('e::d::k:i:o:');
if (isset($arg['i']) && !empty($arg['i'])) {
  $infilename = $arg['i'];
} else {
  die("please input filename".PHP_EOL);
}
if (isset($arg['o']) && !empty($arg['o'])) {
  $outfilename = $arg['o'];
} else {
  $outfilename = "";
}
if (isset($arg['k']) && !empty($arg['k'])) {
  $key = $arg['k'];
} else {
  $key = "pass";
}
$key = hash('sha256', $key, true);
if (isset($arg['d'])) {
  decrypt($key, $infilename, $outfilename);
} elseif (isset($arg['e'])) {
  encrypt($key, $infilename, $outfilename);
}

golang cbc使用pkcs7补全版:

package main

import (
        "bytes"
        "crypto/aes"
        "crypto/cipher"
        "crypto/rand"
        "crypto/sha256"
        //"encoding/binary"
        "flag"
        "fmt"
        "io/ioutil"
        "log"
        "os"
)
func pkcs7strip(data *[]byte, blockSize int) (int, error) {
        length := len(*data)
        if length == 0 {
                return 0, fmt.Errorf("pkcs7: Data is empty")
        }
        if length%blockSize != 0 {
                return 0, fmt.Errorf("pkcs7: Data is not block-aligned")
        }
        padLen := int((*data)[length-1])
        ref := bytes.Repeat([]byte{byte(padLen)}, padLen)
        if padLen > blockSize || padLen == 0 || !bytes.HasSuffix(*data, ref) {
                return 0, fmt.Errorf("pkcs7: Invalid padding")
        }
        return length-padLen, nil
}

func pkcs7pad(data *[]byte, blockSize int) error {
        if blockSize < 0 || blockSize > 256 {
                return fmt.Errorf("pkcs7: Invalid block size %d", blockSize)
        } else {
                padLen := blockSize - len(*data) % blockSize
                padding := bytes.Repeat([]byte{byte(padLen)}, padLen)
                *data = append(*data, padding...)
                return nil
        }
}

func encryptFile(key []byte, filename string, outFilename string) (string, error) {
        if len(outFilename) == 0 {
                outFilename = filename + ".enc"
        }

        plaintext, err := ioutil.ReadFile(filename)
        if err != nil {
                return "", err
        }

        of, err := os.Create(outFilename)
        if err != nil {
                return "", err
        }
        defer of.Close()

        if  err := pkcs7pad(&plaintext, aes.BlockSize) ; err != nil {
                return "", err
        }

        iv := make([]byte, aes.BlockSize)
        if _, err := rand.Read(iv); err != nil {
                return "", err
        }
        if _, err = of.Write(iv); err != nil {
                return "", err
        }

        ciphertext := make([]byte, len(plaintext))

        block, err := aes.NewCipher(key)
        if err != nil {
                return "", err
        }
        mode := cipher.NewCBCEncrypter(block, iv)
        mode.CryptBlocks(ciphertext, plaintext)

        if _, err = of.Write(ciphertext); err != nil {
                return "", err
        }
        return outFilename, nil
}

func decryptFile(key []byte, filename string, outFilename string) (string, error) {
        if len(outFilename) == 0 {
                outFilename = filename + ".dec"
        }

        ciphertext, err := ioutil.ReadFile(filename)
        if err != nil {
                return "", err
        }

        of, err := os.Create(outFilename)
        if err != nil {
                return "", err
        }
        defer of.Close()

        buf := bytes.NewReader(ciphertext)
        iv := make([]byte, aes.BlockSize)
        if _, err = buf.Read(iv); err != nil {
                return "", err
        }

        paddedSize := len(ciphertext) - aes.BlockSize
        if paddedSize%aes.BlockSize != 0 {
                return "", fmt.Errorf("want padded plaintext size to be aligned to block size")
        }
        plaintext := make([]byte, paddedSize)

        block, err := aes.NewCipher(key)
        if err != nil {
                return "", err
        }
        mode := cipher.NewCBCDecrypter(block, iv)
        mode.CryptBlocks(plaintext, ciphertext[aes.BlockSize:])

        origSize, err := pkcs7strip(&plaintext, aes.BlockSize)
        if err != nil {
          return "", err
        }
        if _, err := of.Write(plaintext[:origSize]); err != nil {
                return "", err
        }
        return outFilename, nil
}

func main() {
        var keyFlag string
        encFlag := flag.Bool("e", false, "encrypt")
        decFlag := flag.Bool("d", false, "decrypt")
        flag.StringVar(&keyFlag, "k", "password", "encrypt password")

        flag.Parse()
        filename := flag.Arg(0)

        key := sha256.Sum256([]byte(keyFlag))
        fmt.Println("use password", keyFlag)
        //fmt.Println(key)
        if *encFlag {
                outFilename, err := encryptFile(key[:], filename, "")
                if err != nil {
                        log.Fatal(err)
                }
                fmt.Println("Encrypted output file:", outFilename)
        } else if *decFlag {
                outFilename, err := decryptFile(key[:], filename, "")
                if err != nil {
                        log.Fatal(err)
                }
                fmt.Println("Decrypted output file:", outFilename)
        } else {
                fmt.Println(flag.Usage)
                os.Exit(1)
        }
}

golang使用aes cfb:

package main

import (
        //"bytes"
        "crypto/aes"
        "crypto/cipher"
        "crypto/rand"
        "crypto/sha256"
        //"encoding/binary"
        "flag"
        "fmt"
        "io"
        "io/ioutil"
        "log"
        "os"
)

func encryptFile(key []byte, filename string, outFilename string) (string, error) {
        if len(outFilename) == 0 {
                outFilename = filename + ".enc"
        }

        plaintext, err := ioutil.ReadFile(filename)
        if err != nil {
                return "", err
        }

        of, err := os.Create(outFilename)
        if err != nil {
                return "", err
        }
        defer of.Close()

        block, err := aes.NewCipher(key)
        if err != nil {
                panic(err)
        }

        ciphertext := make([]byte, aes.BlockSize+len(plaintext))
        iv := ciphertext[:aes.BlockSize]
        if _, err := io.ReadFull(rand.Reader, iv); err != nil {
                panic(err)
        }

        stream := cipher.NewCFBEncrypter(block, iv)
        stream.XORKeyStream(ciphertext[aes.BlockSize:], plaintext)

        fmt.Printf("iv:\t%x\n", iv)
        fmt.Printf("cipher text:\t%x\n", ciphertext)
        if _, err = of.Write(ciphertext); err != nil {
                return "", err
        }
        return outFilename, nil
}

func decryptFile(key []byte, filename string, outFilename string) (string, error) {
        if len(outFilename) == 0 {
                outFilename = filename + ".dec"
        }

        ciphertext, err := ioutil.ReadFile(filename)
        fmt.Printf("cipher text:\t%x\n", ciphertext)
        if err != nil {
                return "", err
        }

        of, err := os.Create(outFilename)
        if err != nil {
                return "", err
        }
        defer of.Close()

        block, err := aes.NewCipher(key)
        if err != nil {
                panic(err)
        }

        iv := ciphertext[:aes.BlockSize]
        ciphertext = ciphertext[aes.BlockSize:]
        fmt.Printf("cipher2 text:\t%x\n", ciphertext)
        fmt.Printf("iv:\t%x\n", iv)

        stream := cipher.NewCFBDecrypter(block, iv)

        stream.XORKeyStream(ciphertext, ciphertext)

        if _, err := of.Write(ciphertext); err != nil {
                return "", err
        }
        return outFilename, nil
}

func main() {
        var keyFlag string
        encFlag := flag.Bool("e", false, "encrypt")
        decFlag := flag.Bool("d", false, "decrypt")
        flag.StringVar(&keyFlag, "k", "password", "encrypt password")

        flag.Parse()
        filename := flag.Arg(0)

        key := sha256.Sum256([]byte(keyFlag))
        fmt.Println("use password", keyFlag)
        //fmt.Println(key)
        if *encFlag {
                outFilename, err := encryptFile(key[:], filename, "")
                if err != nil {
                        log.Fatal(err)
                }
                fmt.Println("Encrypted output file:", outFilename)
        } else if *decFlag {
                outFilename, err := decryptFile(key[:], filename, "")
                if err != nil {
                        log.Fatal(err)
                }
                fmt.Println("Decrypted output file:", outFilename)
        } else {
                fmt.Println(flag.Usage)
                os.Exit(1)
        }
}

btc/比特币确定性hd钱包bip32/bip39工具hd-wallet-derive使用

发布时间:April 21, 2020 // 分类: // No Comments

git clone https://github.com/dan-da/hd-wallet-derive.git
cd hd-wallet-derive
composer.phar install

生成bip39钱包,指定助记词数量24个,使用256位随机种子,结果包含b39 seed,助记词,主私钥root-key等。

hd-wallet-derive.php -g --gen-key --gen-words=24

使用主私钥生成path /m/0下的btc地址和私钥:

./hd-wallet-derive.php -g --key=xprv9s21ZrQH143K3mnXKMLng2WiMv8NHtk68CqTSA9Yb8TAeAdT4V3WdKFVnZBBpHejT6ascYfBWu8WvgVFK5VwoP6pk8iQGnW3aVhAZD7r9Cx --path=m/0 --cols=path,address,privkey  

使用助记词生成path /m/0下的btc地址和私钥:

./hd-wallet-derive.php -g --mnemonic="impose tiny skirt crowd scheme thumb episode flat pumpkin junior wonder manual split crane feed seat lady title seek betray next comfort mimic base" --path=m/0 --cols=path,address,privkey

也可使用内置的path,查看列表:

./hd-wallet-derive.php --help-presets

使用electrum preset,和上面使用path=m/0等效。

./hd-wallet-derive.php -g --key=xprv9s21ZrQH143K3mnXKMLng2WiMv8NHtk68CqTSA9Yb8TAeAdT4V3WdKFVnZBBpHejT6ascYfBWu8WvgVFK5VwoP6pk8iQGnW3aVhAZD7r9Cx --preset=electrum --cols=path,address,privkey

安全保存btc/bch/bsv的方法

发布时间:April 19, 2020 // 分类: // No Comments

1.在离线的机器上使用安全程序通过bip32生成主公钥/私钥或bip39生成助记词/主公钥/私钥
2.在离线的机器上钱包导入主私钥,将主公钥备份到联网的机器上并导入,这样联网机器只能查看不能发送交易
3.地址类型使用三者都支持的P2PKH
4.发送时在联网的钱包上生成交易,复制到离线机器上签名,然后用第三方web网站解码查看签名的交易,正常再广播出去。

注意:
为保持和从主秘钥/公钥导入的地址一致,从备份的bip39助词恢复时要将Derivation Path设置为m/

最好离线和在线机器不直接通过u盘间接传递,联网机器通过网络和第三台机器交换签名文件,第三台再通过u盘和离线机器交换签名文件。

生成bip32/bip39可使用:
https://github.com/tyler-smith/go-bip32
https://github.com/tyler-smith/go-bip39
只要保证初始种子随机安全即可,上面程序通过rand.Read()生成,相同的种子生成相同的主秘钥/公钥/助记词,bip39助记词和初始种子可相互转换。

初始随机种子也可通过其它程序生成:
php7:

php -r "echo bin2hex(random_bytes(32)).PHP_EOL;"

python2:

python2 -c 'import os;print os.urandom(32).encode("hex")'

python3.5以上:

python3 -c 'import os;print(os.urandom(32).hex())'

在线生成验证,也可下载单文件bip39-standalone.html离线版本,或使用hd-wallet-derive验证。
https://iancoleman.io/bip39/

bsv钱包:ElectrumSV
bch钱包:Electron Cash
btc钱包:Electrum

使用gpg校验下载的软件签名:

wget https://download.electrum.org/3.3.8/Electrum-3.3.8.tar.gz.asc
wget https://download.electrum.org/3.3.8/Electrum-3.3.8.tar.gz
wget https://raw.githubusercontent.com/spesmilo/electrum/master/pubkeys/ThomasV.asc
gpg --import ThomasV.asc 
gpg --verify Electrum-3.3.8.tar.gz.asc 

wget https://github.com/Electron-Cash/Electron-Cash/releases/download/4.0.14/Electron-Cash-4.0.14.tar.gz
wget https://github.com/Electron-Cash/Electron-Cash/releases/download/4.0.14/Electron-Cash-4.0.14.tar.gz.asc
wget https://github.com/Electron-Cash/Electron-Cash/raw/master/pubkeys/jonaldkey2.txt
gpg --import jonaldkey2.txt 
gpg --verify Electron-Cash-4.0.14.tar.gz.asc 


wget https://electrumsv.io/download/1.2.5/ElectrumSV-1.2.5.tar.gz.asc
wget https://electrumsv-downloads.s3.us-east-2.amazonaws.com/releases/1.2.5/ElectrumSV-1.2.5.tar.gz
wget https://raw.githubusercontent.com/electrumsv/electrumsv/master/pubkeys/rt121212121.asc
gpg --import rt121212121.asc 
gpg --verify ElectrumSV-1.2.5.tar.gz.asc 
分类
最新文章
最近回复
  • opnfense: 谢谢博主!!!解决问题了!!!我之前一直以为内置的odhcp6就是唯一管理ipv6的方式
  • liyk: 这个方法获取的IPv6大概20分钟之后就会失效,默认路由先消失,然后Global IPV6再消失
  • 海运: 不好意思,没有。
  • zongboa: 您好,請問一下有immortalwrt設定guest Wi-Fi的GUI教學嗎?感謝您。
  • 海运: 恩山有很多。
  • swsend: 大佬可以分享一下固件吗,谢谢。
  • Jimmy: 方法一 nghtp3步骤需要改成如下才能编译成功: git clone https://git...
  • 海运: 地址格式和udpxy一样,udpxy和msd_lite能用这个就能用。
  • 1: 怎么用 编译后的程序在家里路由器内任意一台设备上运行就可以吗?比如笔记本电脑 m参数是笔记本的...
  • 孤狼: ups_status_set: seems that UPS [BK650M2-CH] is ...