Go与php的加密通信aes-128-ecb

通过go语言进行加密,可利用php openssl扩展进行解密。

package encrypt

import (
	"bytes"
	"crypto/aes"
	"crypto/cipher"
	"encoding/base64"
	"fmt"
)

type ecb struct {
	b         cipher.Block
	blockSize int
}

func newECB(b cipher.Block) *ecb {
	return &ecb{
		b:         b,
		blockSize: b.BlockSize(),
	}
}

type ecbEncrypter ecb

// NewECBEncrypter returns a BlockMode which encrypts in electronic code book
// mode, using the given Block.
func NewECBEncrypter(b cipher.Block) cipher.BlockMode {
	return (*ecbEncrypter)(newECB(b))
}

func (x *ecbEncrypter) BlockSize() int { return x.blockSize }

func (x *ecbEncrypter) CryptBlocks(dst, src []byte) {
	if len(src)%x.blockSize != 0 {
		panic("crypto/cipher: input not full blocks")
	}
	if len(dst) < len(src) {
		panic("crypto/cipher: output smaller than input")
	}
	for len(src) > 0 {
		x.b.Encrypt(dst, src[:x.blockSize])
		src = src[x.blockSize:]
		dst = dst[x.blockSize:]
	}
}

type ecbDecrypter ecb

// NewECBDecrypter returns a BlockMode which decrypts in electronic code book
// mode, using the given Block.
func NewECBDecrypter(b cipher.Block) cipher.BlockMode {
	return (*ecbDecrypter)(newECB(b))
}

func (x *ecbDecrypter) BlockSize() int { return x.blockSize }

func (x *ecbDecrypter) CryptBlocks(dst, src []byte) {
	if len(src)%x.blockSize != 0 {
		panic("crypto/cipher: input not full blocks")
	}
	if len(dst) < len(src) {
		panic("crypto/cipher: output smaller than input")
	}
	for len(src) > 0 {
		x.b.Decrypt(dst, src[:x.blockSize])
		src = src[x.blockSize:]
		dst = dst[x.blockSize:]
	}
}

func encodeBase64(b []byte) string {
	return base64.StdEncoding.EncodeToString(b)
}

func decodeBase64(s string) []byte {
	data, err := base64.StdEncoding.DecodeString(s)
	if err != nil {
		panic(err)
	}
	return data
}

func PKCS5Padding(ciphertext []byte, blockSize int) []byte {
	padding := blockSize - len(ciphertext)%blockSize
	padtext := bytes.Repeat([]byte{byte(padding)}, padding)
	return append(ciphertext, padtext...)
}
func PKCS5UnPadding(origData []byte) []byte {
	length := len(origData)
	// 去掉最后一个字节 unpadding 次
	unpadding := int(origData[length-1])
	return origData[:(length - unpadding)]
}
func EncryptECB(src string, hexKey string) string {
	var hasError = false
	block, err := aes.NewCipher([]byte(hexKey))
	if err != nil {
		fmt.Println("key error")
		hasError = true
	}

	if src == "" {
		fmt.Println("plain content empty")
		hasError = true
	}

	if hasError {
		return ""
	}
	ecbn := NewECBEncrypter(block)
	content := []byte(src)
	content = PKCS5Padding(content, block.BlockSize())
	crypted := make([]byte, len(content))
	ecbn.CryptBlocks(crypted, content)
	return base64.StdEncoding.EncodeToString(crypted)
}
func DecryptECB(src string, hexKey string) string {
	var hasError = false
	block, err := aes.NewCipher([]byte(hexKey))
	if err != nil {
		fmt.Println("key error")
		hasError = true
	}

	if src == "" {
		fmt.Println("plain content empty")
		hasError = true
	}

	if hasError {
		return ""
	}
	ecbn := NewECBDecrypter(block)
	content := decodeBase64(src)
	//fmt.Println(content)
	//content = PKCS5Padding(content, block.BlockSize())
	crypted := make([]byte, len(content))
	ecbn.CryptBlocks(crypted, content)
	return string(PKCS5UnPadding(crypted))
}

简单几条命令搭建共享式samba

有时候在公司需要一个共享的空间,samba最适合做这个,不需要太高的安全级别,只是最简单方便的文件共享 。

yum install samba
chkconfig smb on
vim /etc/samba/smb.conf

调配置文件的两个地方,第一个改为share用户模式,并设置用户为root.
继续阅读简单几条命令搭建共享式samba

Go并发编程

package main
import "fmt"
import "sync"
import "runtime"

var counter int = 0
func Count(lock *sync.Mutex) { lock.Lock()
        counter++
        fmt.Println(z)
        lock.Unlock()
}
func main() {
lock := &sync.Mutex{}
   for i := 0; i < 10; i++ { go Count(lock)
}
for { lock.Lock()
c := counter
    lock.Unlock()
runtime.Gosched()
 if c >= 10 {
  } }
}

在上面的例子中,我们在10个goroutine中共享了变量counter。每个goroutine执行完成后, 将counter的值加1。因为10个goroutine是并发执行的,所以我们还引入了锁,也就是代码中的 lock变量。每次对n的操作,都要先将锁锁住,操作完成后,再将锁打开。在主函数中,使用for 循环来不断检查counter的值(同样需要加锁)。当其值达到10时,说明所有goroutine都执行完 毕了,这时主函数返回,程序退出。
继续阅读Go并发编程

面试题:一个HTTP请求的过程

我们平时浏览网页的时候,会打开浏览器,输入网址后按下回车键,然后就会显示出你想要浏览的内容。在这个看似简单的用户行为背后,到底隐藏了些什么呢?
对于普通的上网过程,系统其实是这样做的:浏览器本身是一个客户端,当你输入URL的时候,首先浏览器会去请求DNS服务器,通过DNS获取相应的域名对应的IP,然后通过IP地址找到IP对应的服务器后,要求建立TCP连接,等浏览器发送完HTTP Request(请求)包后,服务器接收到请求包之后才开始处理请求包,服务器调用自身服务,返回HTTP Response(响应)包;客户端收到来自服务器的响应后开始渲染这个Response包里的主体(body),等收到全部的内容随后断开与该服务器之间的TCP连接。
继续阅读面试题:一个HTTP请求的过程

linux chmod -R 777 / 之后的修复过程

如果一旦误操作导致linux根目录下面的所有文件改为了777。

那么这时候一定不要重启电脑,找一台新的机器执行

getfacl -R / > acl.bak

然后传到这台机器上再执行

setfacl --restore=acl.bak

如果出故障机器已经重启过了,那可能就麻烦一些。因为帐户认证系统已经损坏了,登录不成功。 继续阅读linux chmod -R 777 / 之后的修复过程

win10 sqlserver2016开启远程访问

1 先以window用户登录Microsoft SQL Server Management Studio

在Sql链接上面右键属性=>安全性=>服务器身份验证=>修改为【Sql Server和Windows身份验证模式】

返回到链接界面打开链接=>点击安全性=>登录名=>选择sa右键属性=>修改为Sql Server身份验证并设置密码,然后点击左侧状态将登录选择为已启用

继续阅读win10 sqlserver2016开启远程访问

ES6中用起来很爽的几点

1 剪头函数的this指针问题

this指向的固定化,并不是因为箭头函数内部有绑定this的机制,实际原因是箭头函数根本没有自己的this,而是引用外层的this。这也避免了之前js代码中保存this指针的代码.


// ES6
function foo() {
setTimeout(() => {
console.log('id:', this.id);
}, 100);
}

// ES5
function foo() {
var _this = this;

setTimeout(function () {
console.log('id:', _this.id);
}, 100);
}

继续阅读ES6中用起来很爽的几点

ES6语法中常量对象的一个有趣的问题

对于复合类型的变量,变量名不指向数据,而是指向数据所在的地址。const命令只是保证变量名指向的地址不变,并不保证该地址的数据不变,所以将一个对象声明为常量必须非常小心。

const foo = {};
foo.prop = 123;
foo.prop
// 123
foo = {}; // TypeError: "foo" is read-only

继续阅读ES6语法中常量对象的一个有趣的问题

Gearman static变量注意的点

记录下Gearman下面static变量会遇到的问题.


class Ticket{
static public function config(){
return []//从数量库中获取;
}

static public function getTicketConfig($itype){
static $configHash;
$configHash or $configHash = self::config();
return $configHash[$itype]?$configHash[$itype]:[];
}
}

 

这行代码如果在常规的BS架构中是可以减少数据库请求次数的,config()方法中的数据会在下一次请求的时候同步变化,在本次请求中是保持不变的.

继续阅读Gearman static变量注意的点