view go/crypto.go @ 13:f5ffc34f045a

manage DB.
author pyon@macmini
date Wed, 14 Nov 2018 19:43:40 +0900
parents e3b10fb860b3
children
line wrap: on
line source

/*
 crypto.go  : crypto-program.
 Version    : 1.1
 Last Change: 2018-11-14 水 13:27:48.

 install to: rsearcher_root/
             server_root/
*/
package main

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

var version string

func init() {
	version = "1.1"	// output file version
}

func main() {
	salt := flag.String( "s", "dummysalt", "salt." )
	enca := flag.String( "a", "", "encrypt plaintext." )
	encb := flag.String( "b", "", "encrypt csv-file." )
	coll := flag.String( "c", "", "collate user/password." )

	key  := flag.String( "k", "1234567890abcdef1234567890abcdef", "key" )	// len = 32
	encr := flag.String( "e", "", "encrypt hhs." )
	decr := flag.String( "d", "", "decrypt hhs." )
	ghhs := flag.String( "f", "", "get hhs info." )

	opf  := flag.String( "o", "", "output file." )

	pver := flag.Bool( "v", false, "print version." )

	flag.Parse()

	if *pver {
		fmt.Println( "crypto [", version, "]" )
		os.Exit( 0 )
	}

	/* Hash ( 1 word ) */
	if *enca != "" {
		buf := *salt + enc_sha256( *enca ) + *salt
		fmt.Println( enc_sha256( buf ) )
		os.Exit( 0 )	// done.
	}

	/* Hash ( csv ) */
	if *encb != "" {
		f, err := os.Open( *encb ); if err != nil {
			log.Fatal( err )
		}
		defer f.Close()

		r := csv.NewReader( f )
		for {
			record, err := r.Read()
			if err == io.EOF {
				break
			}
			if err != nil {
				log.Fatal( err )
			}
			buf := *salt + enc_sha256( record[ 1 ] ) + *salt
			fmt.Println( record[ 0 ], enc_sha256( buf ) )
		}
		os.Exit( 0 )	// done.
	}

	/* Password Check */
	if *coll != "" {
		f, err := os.Open( *coll ); if err != nil {
			log.Fatal( err )
		}
		defer f.Close()

		if flag.NArg() != 2 {
			fmt.Fprintf( os.Stderr, "bad argument\n" )
			os.Exit( 1 )
		}
		user := flag.Arg( 0 )
		pw   := flag.Arg( 1 )

		r := csv.NewReader( f )
		r.Comma = ' '
		for {
			record, err := r.Read()
			if err == io.EOF {
				break
			}
			if err != nil {
				log.Fatal( err )
			}

			if record[ 0 ] == user {
				buf := *salt + enc_sha256( pw ) + *salt
				if record[ 1 ] == enc_sha256( buf ) {
					fmt.Println( "valid" )
					os.Exit( 39 )
				}
			}
		}
		os.Exit( 0 )	// done.
	}

	/* Encrypto & Decrypto */
	k, _ := hex.DecodeString( *key )	// len = 32
	block, err := aes.NewCipher( k )
	if err != nil {
		panic( err )
	}

	// encrypto file
	if *encr != "" {
		plaintext, err := ioutil.ReadFile( *encr )	// 入力CSVは S-JIS
		if err != nil {
			log.Fatal( err )
		}

		// IV は公開してもいいので先頭につけておく
		ciphertext := make( []byte, aes.BlockSize + len( plaintext ) )
		iv := ciphertext[ :aes.BlockSize ]
		if _, err := io.ReadFull( rand.Reader, iv ); err != nil {
			panic( err )
		}

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

		//fmt.Printf( "%s", ciphertext )
		output( *opf, string( ciphertext ) )
		os.Exit( 0 )
	}

	// decrypt file
	if *decr != "" {
		ciphertext, err := ioutil.ReadFile( *decr )
		if err != nil {
			log.Fatal( err )
		}

		iv := ciphertext[ :aes.BlockSize ]
		plaintext := make( []byte, len( ciphertext[ aes.BlockSize: ] ) )
		stream := cipher.NewCTR( block, iv )
		stream.XORKeyStream( plaintext, ciphertext[ aes.BlockSize: ] )

		//fmt.Printf( "%s", plaintext )
		output( *opf, string( plaintext ) )
		os.Exit( 0 )
	}

	/* Etc */
	if *ghhs != "" {
		os.Exit( 0 )
	}

	/* Error */
	fmt.Fprintf( os.Stderr, "bad argument\n" )
	os.Exit( 1 )
}

/* Hash Function */
func enc_sha256( text string ) string {
	h := sha256.New()
	h.Write( []byte( text ) )
	return fmt.Sprintf( "%x", h.Sum( nil ) )
}

/* Output Function */
func output( file, str string ) {
	if file == "" {
		fmt.Fprint( os.Stdout, str )
	} else {
		os.Remove( file )
		f, err := os.OpenFile( file, os.O_RDWR|os.O_CREATE, 0644 )
		if err != nil {
			log.Fatal( err )
		}
		defer f.Close()
		fmt.Fprint( f, str )
	}
}