There is a decryption and signature interface. I want to move from PHP to Golang. The PHP function is as follows:
function getSignature($param){
if (is_string($param)) {
$file_private = 'file.p12';
if (!$cert_store = file_get_contents($file_private)) {
return "Error: Unable to read the cert file\n";
}
$signature = "";
$algo = "sha256WithRSAEncryption";
$password = "PASSWORD";
$private_key_file = openssl_pkcs12_read($cert_store, $cert_info, $password);
if ($private_key_file)
{
$private_key = $cert_info['pkey'];
openssl_sign($param, $signature, $private_key, $algo);
return htmlentities(base64_encode($signature));
}
}
return false;
}
I want to use golang to achieve.
How can I convert into golang?
SOLVED
This is what actually my code in golang:
func Sign(privateKey *rsa.PrivateKey, data string) (string, error) {
h := crypto.SHA256.New()
h.Write([]byte(data))
hashed := h.Sum(nil)
sign, err := rsa.SignPKCS1v15(rand.Reader, privateKey, crypto.SHA256, hashed)
if err != nil {
return "", err
}
return base64.RawURLEncoding.EncodeToString(sign), err
}
func read_keys() {
b, err := ioutil.ReadFile("file.p12")
if err != nil {
fmt.Println(err)
}
password := "PASSWORD"
privk, _, err := pkcs12.Decode(b, password)
if err != nil {
fmt.Println(err)
}
pv := privk.(*rsa.PrivateKey)
sign, _ := Sign(pv, "Your String Data")
fmt.Print(sign)
}
this is the package you're looking for
data, err := ioutil.ReadFile(*in)
if err != nil {
log.Fatal(err)
}
privateKey, certificate, err := pkcs12.Decode(data, *password)
if err != nil {
log.Fatal(err)
}
pv := privateKey.(*rsa.PrivateKey)
signature, err := rsa.SignPKCS1v15(rand.Reader, privateKey, rypto.SHA256, hash)
if err != nil {
log.Fatal(err)
}
Related
I have some php code like this
$signature = '';
$data = strval($aMessage);
if (!openssl_sign($data, $signature, $key, OPENSSL_ALGO_SHA1)) {
return null;
}
$signature = base64_encode($signature);
I make a plan to move it into golang. so I have the code like this
var rpk *rsa.PrivateKey
var bs []byte
if rpk, err = c.getRSAPrivateKey(); err != nil {
return
}
if bs, err = json.Marshal(c); err != nil {
return
}
var hash = crypto.SHA1.New()
hash.Write(bs)
if bs, err = rsa.SignPKCS1v15(rand.Reader, rpk, crypto.SHA1, hash.Sum(nil)); err != nil {
return
}
return base64.RawURLEncoding.EncodeToString(bs), err
when bs have a small length it works well and the result is the same as php code, but it works bad
when bs has a big length. where is my wrong?
I hope the result is always the same
Updated:
the problem is. golang base64encoding , I hav solved with below codes
var b64s = base64.URLEncoding.EncodeToString(bs)
b64s = strings.ReplaceAll(b64s, "-", "+")
b64s = strings.ReplaceAll(b64s, "_", "/")
I'm trying to compare the hash of a password, but when I compare it I get hieroglyphs and can't match whether it's true or false.
analog php function:
/*
* Split hash into pieces
* ([0] = ??, [1] = master key, [2] = salt len, [3] = salt, [4] = iteration count, [5] = salt position, [6] = ??, [7] == ??, [8] == ??)
*/
$passHashArray = explode('$', $passHash);
/*
* Combine passphrase and salt
*/
$passToHash = $testPassphrase.hex2bin($passHashArray[3]);
/*
* Hash $passToHash $passHasArray[4] times with SHA512
*/
for($i = 0; $i < $passHashArray[4]; $i++){
$passToHash = hash('SHA512', $passToHash, true);
}
/*
* Get Key and Iv from $passToHash for final encryption
*/
$key = substr($passToHash, 0, 32);
$iv = substr($passToHash, 32, 16);
/*
* final passphrase encryption
*/
if(in_array('aes-256-cbc', openssl_get_cipher_methods())){
if(openssl_decrypt(hex2bin($passHashArray[1]), 'aes-256-cbc', $key, OPENSSL_RAW_DATA, $iv)){
echo 'password correct';
}else{
echo 'decrypt failed';
}
}
go function:
var passwordHash = "64$718eadbd49dbee69e2b3e5f9659c361129cc07199d421d01892694477331ad8a$16$dce01545e0c918e7$76012$2$00$2$00"
var password = "12345678910"
func main() {
var passwordHashArray = strings.Split(passwordHash, "$")
/*
* Convert to hex to bin passphrase and salt
*/
hex2Bin, err := hex.DecodeString(passwordHashArray[3])
if err != nil {
log.Printf("error hex decode string password hash array: %s", err)
}
/*
* Combine passphrase and salt
*/
passwordToHash := strings.Join([]string{ password, string(hex2Bin)}, "")
/*
* Hash $passToHash $passHasArray[4] times with SHA512
*/
intVar, err := strconv.Atoi(passwordHashArray[4])
if err != nil {
log.Printf("error password hash array string to int: %s", err)
}
passwordToHashBinary := make([]byte, 32)
passwordToHashBinary = hashSHA512([]byte(passwordToHash))
for i := 1; i < intVar; i++ {
passwordToHashBinary = hashSHA512(passwordToHashBinary)
}
/*
* Get Key and Iv from $passToHash for final encryption
*/
var encKeyDecoded = make([]byte, 32)
copy(encKeyDecoded, passwordToHashBinary[:32])
var ivDecoded = make([]byte, 16)
copy(ivDecoded, passwordToHashBinary[32:48])
cipherTextDecoded, err := hex.DecodeString(passwordHashArray[1])
if err != nil {
log.Printf("error hex decode string password hash array: %s", err)
}
results, err := decrypt(cipherTextDecoded, encKeyDecoded, ivDecoded)
if err != nil {
log.Printf("error result decode password: %s", err)
}
log.Printf("%s", string(results))
log.Printf("%x", string(results))
}
func decrypt(cipherTextDecoded []byte, encKeyDecoded []byte, ivDecoded []byte) ([]byte, error) {
block, err := aes.NewCipher(encKeyDecoded)
if err != nil {
return nil, err
}
if len(cipherTextDecoded) < aes.BlockSize {
return nil, fmt.Errorf("ciphertext too short")
}
if len(cipherTextDecoded)%aes.BlockSize != 0 {
return nil, fmt.Errorf("ciphertext is not a multiple of the block size")
}
mode := cipher.NewCBCDecrypter(block, ivDecoded)
mode.CryptBlocks(cipherTextDecoded, cipherTextDecoded)
return cipherTextDecoded, nil
}
func hashSHA512(crypto []byte) []byte {
hash := sha512.New()
hash.Write(crypto)
sha := hash.Sum(nil)
return sha
}
it is worth noting that in php the password is displayed correctly, but on the go I get a line like:
���Pʎ&L�t→]��f�►►►►►►►►►►►►►►►►
First of all, I don't understand where it comes from:
►►►►►►►►►►►►►►►►
How can I check if a password is valid in golang?
if () {good} else {bad}
out php:
https://onecompiler.com/php/3xqvgkhbr
out go:
https://go.dev/play/p/HUxoD29fM4c
i never tried using AES on my site to store password but here's how i do it i'm using PDO prepared statement and bcrypt
$read_username = $pdo->prepare("SELECT * FROM users WHERE username = :username LIMIT 1");
$read_username->execute([':username' => $username]);
if ($read_username->rowCount() > === 1) {
$row = $write_account->fetch(PDO::FETCH_ASSOC);
$read_username = null; // close connection we already got what we need
$pdo = null; // close connection we already got what we need
$stored_hash = $row['password']; // bind the hash stored on db as $stored_hash
if (password_verify($password, $stored_hash)) { // compare user input to $stored_hash
$_SESSION['username'] = $username . bin2hex(random_bytes(12));
header('location: index.php');
die("ACCESS GRANTED!");
} else {
array_push($errors, "Incorrect password!");
}
} else {
array_push($errors, "Account does not exist!");
}
also your if else concern is easy it goes like this
$hotdog = 123;
if ($hotdog == 123) {
echo "hotdog";
} else {
echo "not hotdog";
}
I am working on a legacy code written in PHP that I have to migrate to GO. We are required to store encrypted data, and decrypt on demand.
Because the legacy code will still have to run until everything is migrated to GO, I need to use the same encrypt / decrypt methods in GO too.
I have been strugling with this issue for the last 10 hours. I have tried (I think) all the Stackoverflow suggestions + many others.
The servers are running OpenSSL 1.1.1a. I have found and tested something helpful, but without success:
https://dequeue.blogspot.com/2014/11/decrypting-something-encrypted-with.html
I do not have to much knowledge about encryption in general, but I can understand it's basics.
So, if there is anyone kind enough to give me some suggestions ... please.
PHP legacy code
var $encryption_key = 'XXX';
var $cipher = 'aes-256-cbc';
function encrypt($text) {
global $encryption_key, $cipher;
$iv = openssl_random_pseudo_bytes(openssl_cipher_iv_length($cipher));
$data = openssl_encrypt($text, $cipher, $encryption_key, OPENSSL_RAW_DATA, $iv);
return base64_encode($iv . $data);
}
function decrypt($text) {
global $encryption_key, $cipher;
$data = base64_decode($text);
$iv_len = openssl_cipher_iv_length($cipher);
$iv = substr($data, 0, $iv_len);
$data = substr($data, $iv_len);
return openssl_decrypt($data, $cipher, $encryption_key, OPENSSL_RAW_DATA, $iv);
}
Last code tested in GO for decrypting data (ignore the block below and scroll for updated code)
package main
import (
"crypto/aes"
"crypto/cipher"
"crypto/md5"
"encoding/base64"
"fmt"
)
func main(){
result, _ := DecryptString(`password`, `U2FsdGVkX1+ywYxveBnekSnx6ZP25nyPsWHS3oqcuTo=`)
fmt.Printf("Decrypted string is: %s", result)
}
var openSSLSaltHeader string = "Salted_" // OpenSSL salt is always this string + 8 bytes of actual salt
type OpenSSLCreds struct {
key []byte
iv []byte
}
// Decrypt string that was encrypted using OpenSSL and AES-256-CBC
func DecryptString(passphrase, encryptedBase64String string) ([]byte, error) {
data, err := base64.StdEncoding.DecodeString(encryptedBase64String)
if err != nil {
return nil, err
}
saltHeader := data[:aes.BlockSize]
if string(saltHeader[:7]) != openSSLSaltHeader {
return nil, fmt.Errorf("Does not appear to have been encrypted with OpenSSL, salt header missing.")
}
salt := saltHeader[8:]
creds, err := extractOpenSSLCreds([]byte(passphrase), salt)
if err != nil {
return nil, err
}
return decrypt(creds.key, creds.iv, data)
}
func decrypt(key, iv, data []byte) ([]byte, error) {
if len(data) == 0 || len(data)%aes.BlockSize != 0 {
return nil, fmt.Errorf("bad blocksize(%v), aes.BlockSize = %v\n", len(data), aes.BlockSize)
}
c, err := aes.NewCipher(key)
if err != nil {
return nil, err
}
cbc := cipher.NewCBCDecrypter(c, iv)
cbc.CryptBlocks(data[aes.BlockSize:], data[aes.BlockSize:])
out, err := pkcs7Unpad(data[aes.BlockSize:], aes.BlockSize)
if out == nil {
return nil, err
}
return out, nil
}
// openSSLEvpBytesToKey follows the OpenSSL (undocumented?) convention for extracting the key and IV from passphrase.
// It uses the EVP_BytesToKey() method which is basically:
// D_i = HASH^count(D_(i-1) || password || salt) where || denotes concatentaion, until there are sufficient bytes available
// 48 bytes since we're expecting to handle AES-256, 32bytes for a key and 16bytes for the IV
func extractOpenSSLCreds(password, salt []byte) (OpenSSLCreds, error) {
m := make([]byte, 48)
prev := []byte{}
for i := 0; i < 3; i++ {
prev = hash(prev, password, salt)
copy(m[i*16:], prev)
}
return OpenSSLCreds{key: m[:32], iv: m[32:]}, nil
}
func hash(prev, password, salt []byte) []byte {
a := make([]byte, len(prev)+len(password)+len(salt))
copy(a, prev)
copy(a[len(prev):], password)
copy(a[len(prev)+len(password):], salt)
return md5sum(a)
}
func md5sum(data []byte) []byte {
h := md5.New()
h.Write(data)
return h.Sum(nil)
}
// pkcs7Unpad returns slice of the original data without padding.
func pkcs7Unpad(data []byte, blocklen int) ([]byte, error) {
if blocklen <= 0 {
return nil, fmt.Errorf("invalid blocklen %d", blocklen)
}
if len(data)%blocklen != 0 || len(data) == 0 {
return nil, fmt.Errorf("invalid data len %d", len(data))
}
padlen := int(data[len(data)-1])
if padlen > blocklen || padlen == 0 {
return nil, fmt.Errorf("invalid padding")
}
pad := data[len(data)-padlen:]
for i := 0; i < padlen; i++ {
if pad[i] != byte(padlen) {
return nil, fmt.Errorf("invalid padding")
}
}
return data[:len(data)-padlen], nil
}
The code written in GO should be able to decrypt data encrypted in PHP. The only result that I get is an error: Error: Does not appear to have been encrypted with OpenSSL, salt header missing.
UPDATE: Go code updated
The code below almost works. IV, key, cipher binary text are all the same as in PHP, but the final result is still encrypted (or wrongly decrypted)
package main
import (
"crypto/aes"
"crypto/cipher"
"encoding/base64"
"fmt"
)
func main() {
var stringToDecode string = "base64_encode(SOME_PHP_ENCRYPTED_USING_THE_PHP_CODE_ABOVE)"
var cipherKey = []byte("myprivatekey")
content, err := base64.StdEncoding.DecodeString(stringToDecode)
if err != nil {
fmt.Printf("Error: %s", err)
}
fmt.Println("Cipher key: ", string(cipherKey))
fmt.Println("Cipher key length: ", len(cipherKey))
cipherText := content
cipherBlock, err := aes.NewCipher(cipherKey)
if err != nil {
panic(err)
}
iv := cipherText[:aes.BlockSize]
fmt.Println("iv:", base64.StdEncoding.EncodeToString(iv))
fmt.Println("Cipher text:", string(cipherText[aes.BlockSize:]))
cipherText = cipherText[aes.BlockSize:]
fmt.Println("Cipher text binary: ", string(cipherText))
if len(cipherText)%aes.BlockSize != 0 {
panic(fmt.Sprintf("Cipher text (len=%d) is not a multiple of the block size (%d)", len(cipherText), aes.BlockSize))
}
mode := cipher.NewCBCDecrypter(cipherBlock, iv)
mode.CryptBlocks(cipherText, cipherText)
// The output is not decrypted as expected
fmt.Printf("The result: %s\n", string(cipherText))
}
I have been trying to figure out why one of my variables attaches some garbage value the second time I make a call in gdb but cannot figure it out. I have diagnosed the problem but don't know how to fix it.
On the first call of "curl http://localhost:8080/cat.html", here is what the variables return:
temp = 0x7fffffff9c74 "/cat.html HTTP/1.1\r\n"
request_target = 0x607080 "/cat.html"
abs_path = 0x7fffffffbdd0 "/cat.html"
query = 0x7fffffff9dd0 ""
This works fine and the terminal does show the html file. However, the second time I make the call is where the problem arises.
On the second call of the same address, the following variables are returned:
temp = 0x7fffffff9c74 "/cat.html HTTP/1.1\r\n"
request_target = 0x607080 "/cat.html\327\254\367\377\177"
abs_path = 0x7fffffffbdd0 "/cat.html\327\254\367\377\177"
query = 0x7fffffff9dd0 ""
And then I will receive the 404 file not found error.
Does anybody know why and where I am accumulating all these random characters ("\327\254\367\377\177")? I do believe that it is coming from the temp variable, but I have tried for hours to fix it but I still haven't been able to.
Below are my "parse" and "load" functions:
bool parse(const char* line, char* abs_path, char* query)
{
// GET /cat.html?name="Alice" HTTP/1.1
if (strncmp(line, "GET ", 4) != 0)
{
error(405);
return false;
}
else if (line[4] != '/')
{
error(501);
return false;
}
else if (strncmp(strrchr(line, ' '), " HTTP/1.1", 9) != 0)
{
error(505);
return false;
}
char* temp = strchr(line, '/');
int after_length = strlen(strrchr(line, ' '));
char* request_target = malloc(strlen(temp) - after_length);
strncpy(request_target, temp, strlen(temp) - after_length);
if ((strchr(request_target, '"') != NULL || strchr(request_target, ' ') != NULL))
{
error(400);
return false;
}
if (strchr(request_target, '?') == NULL)
{
strcpy(abs_path, request_target);
strcpy(query, "");
}
else
{
int q_length = strlen(strchr(request_target, '?'));
if (q_length != 2)
{
strncpy(abs_path, request_target, strlen(request_target) - q_length);
strcpy(query, &strchr(request_target, '?')[1]);
}
else
{
strncpy(abs_path, request_target, strlen(request_target) - 2);
strcpy(query, "");
}
}
free(request_target);
return true;
}
bool load(FILE* file, BYTE** content, size_t* length)
{
if (file == NULL)
{
error(500);
return false;
}
*content = NULL;
*length = 0;
BYTE buffer[BYTES];
ssize_t bytes = fread(buffer, 1, sizeof(buffer), file);
while (bytes != 0)
{
*content = realloc(*content, *length + bytes);
memcpy(*content + *length, buffer, bytes);
*length += bytes;
bytes = fread(buffer, 1, sizeof(buffer), file);
}
return true;
}
I am using AES encryption in Go and PHP. But both the languages does not encrypt/decrypt each other ciphertext. Following i have tried in php
class Crypto {
private $encryptKey = "keyforencryption";
private $iv = 'ivusedforencrypt';
private $blocksize = 16;
public function encrypt($toEncrypt){
$iv_size = mcrypt_get_iv_size(MCRYPT_RIJNDAEL_256, MCRYPT_MODE_CFB);
//$iv = mcrypt_create_iv($iv_size, MCRYPT_RAND);
return base64_encode($this->iv . mcrypt_encrypt(MCRYPT_RIJNDAEL_128, $this->encryptKey, $toEncrypt, MCRYPT_MODE_CFB, $this->iv));
}
public function decrypt($toDecrypt){
$iv_size = mcrypt_get_iv_size(MCRYPT_RIJNDAEL_128, MCRYPT_MODE_CFB);//$this->blocksize;
$toDecrypt = base64_decode($toDecrypt);
return rtrim(mcrypt_decrypt(MCRYPT_RIJNDAEL_128, $this->encryptKey, substr($toDecrypt, $iv_size), MCRYPT_MODE_CFB, substr($toDecrypt, 0, $iv_size)));
}
}
$c = new Crypto();
echo "Encrypted : ".$e = $c->encrypt("test");
echo "<br/>Decrypted : ".$c->decrypt($e);
output : aXZ1c2VkZm9yZW5jcnlwdDpdZEinU2rB
and this one in Go with AES
package main
import (
"crypto/aes"
"crypto/cipher"
"crypto/rand"
"encoding/base64"
"errors"
"fmt"
"io"
"log"
)
func main() {
key := []byte("keyforencryption")
plaintext := []byte("test")
fmt.Printf("%s\n", plaintext)
ciphertext, err := encrypt(key, plaintext)
if err != nil {
log.Fatal(err)
}
b := base64.StdEncoding.EncodeToString(ciphertext)
fmt.Printf("Encrypted text : %s\n", b)
result, err := decrypt(key, b)
if err != nil {
log.Fatal(err)
}
fmt.Printf("Decrypted Text : %s\n", result)
}
func encrypt(key, text []byte) ([]byte, error) {
block, err := aes.NewCipher(key)
if err != nil {
return nil, err
}
//b := base64.StdEncoding.EncodeToString(text)
ciphertext := make([]byte, aes.BlockSize+len(text))
iv := ciphertext[:aes.BlockSize]
if _, err := io.ReadFull(rand.Reader, iv); err != nil {
return nil, err
}
cfb := cipher.NewCFBEncrypter(block, iv)
cfb.XORKeyStream(ciphertext[aes.BlockSize:], []byte(text))
return ciphertext, nil
}
func decrypt(key []byte, text1 string) ([]byte, error) {
text, _ := base64.StdEncoding.DecodeString(string(text1))
block, err := aes.NewCipher(key)
if err != nil {
return nil, err
}
if len(text) < aes.BlockSize {
return nil, errors.New("ciphertext too short")
}
iv := text[:aes.BlockSize]
text = text[aes.BlockSize:]
cfb := cipher.NewCFBDecrypter(block, iv)
cfb.XORKeyStream(text, text)
b := base64.StdEncoding.EncodeToString(text)
data, err := base64.StdEncoding.DecodeString(string(b))
if err != nil {
return nil, err
}
return data, nil
}
output : ZVnhCXjIvtGKBdqvjwHRZKcVy34=
any help would be appreciable.
CFB mode has an issue, this will work in CBC mode
class Crypto {
private $encryptKey = "keyforencryption";
public function encrypt($toEncrypt){
$iv_size = mcrypt_get_iv_size(MCRYPT_RIJNDAEL_128, MCRYPT_MODE_CBC);
$iv = mcrypt_create_iv($iv_size, MCRYPT_RAND);
return base64_encode($iv . mcrypt_encrypt(MCRYPT_RIJNDAEL_128, $this->encryptKey, $toEncrypt, MCRYPT_MODE_CBC, $iv));
}
public function decrypt($toDecrypt){
$iv_size = mcrypt_get_iv_size(MCRYPT_RIJNDAEL_128, MCRYPT_MODE_CBC);
echo "<br/>".$toDecrypt = base64_decode($toDecrypt);
return rtrim(mcrypt_decrypt(MCRYPT_RIJNDAEL_128, $this->encryptKey, substr($toDecrypt, $iv_size), MCRYPT_MODE_CBC, substr($toDecrypt, 0, $iv_size)));
}
}
$c = new Crypto();
echo "Encrypted : ".$e = $c->encrypt("test123");
echo "<br/>Decrypted : ".$c->decrypt($e);
and this one in golang
package main
import (
"crypto/aes"
"crypto/cipher"
"crypto/rand"
"encoding/base64"
"fmt"
"io"
"bytes"
)
func main() {
e:= cbcEncrypt()
fmt.Printf("Encrypted String : %s\n", e)
d:= cbcDecrypt(e)
fmt.Printf("Decrypted String : %s\n", d)
}
func cbcDecrypt(text1 string) []byte{
key := []byte("keyforencryption")
ciphertext, _ := base64.StdEncoding.DecodeString(string(text1))
block, err := aes.NewCipher(key)
if err != nil {
panic(err)
}
// include it at the beginning of the ciphertext.
if len(ciphertext) < aes.BlockSize {
panic("ciphertext too short")
}
iv := ciphertext[:aes.BlockSize]
ciphertext = ciphertext[aes.BlockSize:]
// CBC mode always works in whole blocks.
if len(ciphertext)%aes.BlockSize != 0 {
panic("ciphertext is not a multiple of the block size")
}
mode := cipher.NewCBCDecrypter(block, iv)
// CryptBlocks can work in-place if the two arguments are the same.
mode.CryptBlocks(ciphertext, ciphertext)
ciphertext = PKCS5UnPadding(ciphertext)
return ciphertext
}
func cbcEncrypt() string{
key := []byte("keyforencryption")
plaintext := []byte("testssssss")
plaintext = PKCS5Padding(plaintext, 16)
// CBC mode works on blocks so plaintexts may need to be padded to the
// next whole block. For an example of such padding, see
// https://tools.ietf.org/html/rfc5246#section-6.2.3.2. Here we'll
// assume that the plaintext is already of the correct length.
if len(plaintext)%aes.BlockSize != 0 {
panic("plaintext is not a multiple of the block size")
}
block, err := aes.NewCipher(key)
if err != nil {
panic(err)
}
// The IV needs to be unique, but not secure. Therefore it's common to
// include it at the beginning of the ciphertext.
ciphertext := make([]byte, aes.BlockSize+len(plaintext))
iv := ciphertext[:aes.BlockSize]
if _, err := io.ReadFull(rand.Reader, iv); err != nil {
panic(err)
}
mode := cipher.NewCBCEncrypter(block, iv)
mode.CryptBlocks(ciphertext[aes.BlockSize:], plaintext)
// It's important to remember that ciphertexts must be authenticated
// (i.e. by using crypto/hmac) as well as being encrypted in order to
// be secure.
return base64.StdEncoding.EncodeToString(ciphertext)
}
func PKCS5Padding(src []byte, blockSize int) []byte {
padding := blockSize - len(src)%blockSize
padtext := bytes.Repeat([]byte{byte(padding)}, padding)
return append(src, padtext...)
}
func PKCS5UnPadding(src []byte) []byte {
length := len(src)
unpadding := int(src[length-1])
return src[:(length - unpadding)]
}
this should work
Also use padding for encoding and unpadding for decode in php.
function pkcs5_pad($text)
{
$blocksize = mcrypt_get_block_size(MCRYPT_RIJNDAEL_128, MCRYPT_MODE_CBC);
$pad = $blocksize - (strlen($text) % $blocksize);
return $text . str_repeat(chr($pad), $pad);
}
function pkcs5_unpad($text)
{
$block = mcrypt_get_block_size(MCRYPT_RIJNDAEL_128, MCRYPT_MODE_CBC);
$pad = ord($text[($len = strlen($text)) - 1]);
$len = strlen($text);
$pad = ord($text[$len-1]);
return substr($text, 0, strlen($text) - $pad);
}