PHP Code:
$str = chr(164);
$resualt = sha1($str);
echo $resualt;
PHP resualt:
f5efcd994fca895f644b0ccc362aba5d6f4ae0c6
Golang code:
str := string(164)
//fmt.Println(str)
passSha1 := sha1.New()
passSha1.Write([]byte(str))
getSha1 := passSha1.Sum(nil)
fmt.Printf("%x\n",getSha1)
Golang resualt:
fe33a6b4de93e363cf1620f7228df4164d913fbf
In Go, how can I get the same result like PHP.
Your php code is encoding a 1-byte input, but your Go code is doing the same on a utf-8 encoded string. If you print len(string(164)) you'll see that it is 2-bytes. Use this:
str := []byte{164}
passSha1 := sha1.New()
passSha1.Write([]byte(str))
getSha1 := passSha1.Sum(nil)
fmt.Printf("%x\n",getSha1)
Related
I was hoping someone had already implemented this in golang as I am far from even good at cryptography. However in porting a project from php to golang I have run into an issue with porting the openssl_encrypt method found here. I have also dug into the source code a little with no avail.
Here is the method I have implemented in golang. which gives me the output
lvb7JwaI4OCYUrdJMm8Q9uDd9rIILnvbZKJb/ozFbwCmLKkxoJN5Zf/ODOJ/RGq5
Here is the output I need when using php.
lvb7JwaI4OCYUrdJMm8Q9uDd9rIILnvbZKJb/ozFbwDV98XaJjvzEjBQp7jc+2DH
And here is the function I used to generate it with php.
$data = "This is some text I want to encrypt";
$method = "aes-256-cbc";
$password = "This is a really long key and su";
$options = 0;
$iv = "MMMMMMMMMMMMMMMM";
echo openssl_encrypt($data, $method, $password, $options, $iv);
To me it looks like it is very close and I must be missing something obvious.
You were very close, but you had the padding wrong. According to this answer (and the PHP docs), PHP uses the default OpenSSL padding behavior, which is to use the required number of padding bytes as the padding byte value.
The only change I made was:
copy(plaintextblock[length:], bytes.Repeat([]byte{uint8(extendBlock)}, extendBlock))
You can see the full updated code here.
Others beat me to the answer while I was playing with it, but I have a "better" fixed version of your example code that also takes into account that padding is always required (at least to emulate what the php code does).
It also shows the openssl command line that you'd use to do the same thing, and if available runs it (of course the playground won't).
package main
import (
"crypto/aes"
"crypto/cipher"
"encoding/base64"
"fmt"
"log"
"os/exec"
"strings"
)
func main() {
const input = "This is some text I want to encrypt"
fmt.Println(opensslCommand(input))
fmt.Println(aesCBCenctypt(input))
}
func aesCBCenctypt(input string) string {
// Of course real IVs should be from crypto/rand
iv := []byte("MMMMMMMMMMMMMMMM")
// And real keys should be from something like PBKDF2, RFC 2898.
// E.g. use golang.org/x/crypto/pbkdf2 to turn a
// "passphrase" into a key.
key := []byte("This is a really long key and su")
// Make sure the block size is a multiple of aes.BlockSize
// Pad to aes.BlockSize using the pad length as the padding
// byte. If we would otherwise need no padding we instead
// pad an entire extra block.
pad := (aes.BlockSize - len(input)%aes.BlockSize)
if pad == 0 {
pad = aes.BlockSize
}
data := make([]byte, len(input)+pad)
copy(data, input)
for i := len(input); i < len(input)+pad; i++ {
data[i] = byte(pad)
}
cb, err := aes.NewCipher(key)
if err != nil {
log.Fatalln("error NewCipher():", err)
}
mode := cipher.NewCBCEncrypter(cb, iv)
mode.CryptBlocks(data, data)
return base64.StdEncoding.EncodeToString(data)
}
// Just for comparison, don't do this for real!
func opensslCommand(input string) string {
iv := []byte("MMMMMMMMMMMMMMMM")
key := []byte("This is a really long key and su")
args := []string{"enc", "-aes-256-cbc", "-base64"}
// "-nosalt", "-nopad"
args = append(args, "-iv", fmt.Sprintf("%X", iv))
args = append(args, "-K", fmt.Sprintf("%X", key))
cmd := exec.Command("openssl", args...)
// Show how you could do this via the command line:
fmt.Println("Command:", strings.Join(cmd.Args, " "))
cmd.Stdin = strings.NewReader(input)
result, err := cmd.CombinedOutput()
if err != nil {
if e, ok := err.(*exec.Error); ok && e.Err == exec.ErrNotFound {
// openssl not available
return err.Error() // XXX
}
// some other error, show it and the (error?) output and die
fmt.Println("cmd error:", err)
log.Fatalf("result %q", result)
}
// Strip trailing '\n' and return it.
if n := len(result) - 1; result[n] == '\n' {
result = result[:n]
}
return string(result)
}
Playground
I'm making a Delphi application and I'm trying to encode with base64 encoding stream and I made two functions:
function EncodedInputParams(input: TStringStream): string;
var
output: TStringStream;
encoder: TIdEncoderMIME;
begin
input.Encoding.UTF8;
input.Position := 0;
output := TStringStream.Create;
try
encoder := TIdEncoderMIME.Create(nil);
encoder.Encode(input, output);
output.Seek(0, soFromBeginning);
Result := output.DataString;
finally
output.Free;
end;
end;
function SecondEncoding(input: TStringStream): string;
var
output: TStringStream;
midRes: string;
begin
input.Encoding.UTF8;
input.Position := 0;
output := TStringStream.Create;
try
EncodeStream(input, output);
output.Seek(0, soFromBeginning);
midRes := output.DataString;
midRes := StringReplace(midRes, #13#10, EmptyStr, [rfReplaceAll]);
result := midRes;
finally
output.Free;
end;
end;
Functions are working fine but the problem is that these solutions return different string than a string encoded same way in PHP: http://www.tools4noobs.com/online_php_functions/base64_encode/ .
Any ideas how to rewrite one of the function to return string like one written in PHP.
Anybody getting JSON to work with TIdHttp ?
The PHP always return NULL in the $_POST, am I doing anything wrong ?
Delphi source:
http := TIdHttp.Create(nil);
http.HandleRedirects := True;
http.ReadTimeout := 5000;
http.Request.ContentType := 'application/json';
jsonToSend := TStringStream.Create('{"name":"Peter Pan"}');
jsonToSend.Position := 0;
Memo1.Lines.Text := http.Post('http://www.website.com/test.php', jsonToSend);
jsonToSend.free;
http.free;
PHP source:
<?php
$value = json_decode($_POST);
var_dump($value);
?>
You can't use a TStringList to post JSON data. TIdHTTP.Post() will encode the TStringList contents in a way that breaks the JSON data. You need to put the JSON data into a TStream instead. TIdHTTP.Post() will transmit its contents as-is. Also, don't forget to set the TIdHTTP.Request.ContentType property so the server knows you are posting JSON data.
You need to define a post variable, try this code (I have added "json" var to your code):
Delphi code:
http := TIdHttp.Create(nil);
http.HandleRedirects := true;
http.ReadTimeout := 5000;
jsonToSend := TStringList.create;
jsonToSend.Text := 'json={"name":"Peter Pan"}';
Memo1.Lines.Text := http.Post('http://www.website.com/test.php', jsonToSend);
jsonToSend.free;
http.free;
PHP source:
<?php
$value = json_decode($_POST['json']);
var_dump($value);
?>
Hoi!
I trying to make a webservice in Windows.
The client is Delphi 6, with MSXML2.XMLHTTP call, and other side is PHP.
First I tested: can I receive hungarian XML?
The PHP source was UTF-8 encoded file (PSPAD).
$s = 'alma árvíztűrő tükörfúrógép beta';
$doc = new DOMDocument('1.0', 'utf-8');
$doc->formatOutput = true;
$m = $doc->createElement('package');
$doc->appendChild($m);
$n = $doc->createElement('Msg');
$m->appendChild($n);
$n->nodeValue = $s;
$xs = $doc->saveXML();
header('Content-Type: text/xml');
echo($xs);
This package I fully got in Delphi side, the accents are ok.
So then I tried to inject data from xml (post xml to php with accents).
global $HTTP_RAW_POST_DATA;
$xmlstr = $HTTP_RAW_POST_DATA;
$xml = new SimpleXMLElement($xmlstr);
$msg = $xml->msg;
#$msg = 'ÁRVÍZTŰRŐ TÜKÖRFÚRÓGÉP';
Ok, I got the "msg" field, but nevertheless I trying to convert it, everytime I got some convert notice, and the result is not same as when I set the variable directly...
The debug is:
echo(utfCharToNumber($sinput).'<br>');
echo(utfCharToNumber($sdefined).'<br>');
Input: 195[ ]8286195141908419717682197[ ]328419
Defined: 195[129]8286195141908419717682197[144]328419
Input: 5156751951508270195154821951477119513780<br>
Defined: 5156751951508270195154821951477119513780<br>
As you see that two holes I have in the variable when I converted the input from MSXML2.
I really don't understand this.
I cannot reproduce same XML output from get the data from input XML as when I set directly in PHP code...
Why?
Thanks for your every help, idea, link, document, little example!
dd
Since you haven't included Delphi source, I suspect you're posting data straight from a string as content body of the request, which is encoded in the current ANSI encoding by default in Delphi 6. I advise you either use Utf8Encode on the string before you add this as the request's body data, or add a 'Content-encoding' request header with the name of the ANSI encoding (if I remember correctly GetLocaleInfo could give you this).
The source of the problem was the Delphi code.
Priorly I used AnsiToUTF8 to encode the XML text.
But the COM object is uses UTF16 as I think.
The working code is this:
procedure TForm1.Button4Click(Sender: TObject);
var
mhttp : variant;
ws : WideString;
tosend : OleVariant;
xml : TXMLDocument;
n : IXMLNode;
begin
mhttp := CreateOleObject('MSXML2.XMLHTTP');
mhttp.Open('POST', 'http://127.0.0.1/test_xmlgen.php', False);
xml := CreateANewDocument(Self, '', 'a');
n := xml.DocumentElement.AddChild('msg');
n.NodeValue := 'ÁRVÍZTŰRŐ TÜKÖRFÚRÓGÉP';
xml.SaveToXML(ws);
tosend := ws;
mhttp.send(tosend);
Memo1.Lines.Text :=
IntToStr(mhttp.Status) + #13 +
mhttp.responseText + #13;
end;
This can resend the XML I sent - with good accents.
Thanks for your help:
dd
Is there any way with, say Perl or PHP, that I can grab output from another process that outputs to the Windows cmd shell? I have a game server that outputs certain information, for example say 'player finished track in 43s' and I want to grab that line and use Perl or PHP to send a request to a webserver to update ranks on a web page. Is there a way to grab that output pipe in Perl or PHP? Or could I achieve this using C++ Windows API maybe?
Let me clarify here: I want to execute a seperate Perl or PHP script that grabs output from the Windows cmd shell, and the output that is being displayed to the Windows cmd shell is coming from a different process.
You could use IPC::Open3 to read from the other process' standard output. Note that inter-process communication assumes a parent/child relationship between the processes. If that's not the case... I'm not aware of a mechanism for attaching to the output of a pre-existing process. In that case you may need to alter the producer to write data to a log file (or database) that your application can read from.
If all you care about is STDOUT, you can just use open2 from IPC::Open2:
#!/usr/bin/perl
use strict;
use warnings;
use IPC::Open2;
#if there are arguments pretend to be the server
#for this example
if (#ARGV) {
local $| = 1;
for my $i (1 .. 100) {
print "pid $$ iter $i\n";
sleep 1;
}
exit;
}
#run perl with the current script as its argument,
#pass in an arg so that we trigger the behaviour
#above
open2 my $out, my $in, $^X, $0, 1
or die "could not run '$^X $0 1': $!\n";
while (<$out>) {
s/[\r\n]//g;
print "pid $$ saw [$_]\n";
}
You need to start your server within Perl:
my $server_out = `server.exe`; # Note the backticks.
Now $server_out contains the output of server.exe. But the trick here is that you have to wait until server.exe exits to get the out put.
Try IPC::Run (which is not a core module)
use English;
use IPC::Run;
my ($stdout, $stderr);
IPC::Run::run([$cmd, $arg1, $arg2, $argN], \undef, \$stdout, $stderr);
while(<$stdout>) {
print "Cmd said $_\n";
}
Note: Code not tested.
Found the info here.
Capturing the output in Perl is as simple as:
$output = qx(command);
or
$output = `command`; # backticks
Refer: perldoc perlop
This code redirects the STDOUT of a console application to a stringlist, which you can use on a memo for example. It's Delphi code, but in C++ the basic idea is exactly the same.
I use it to run console applications hidden, while redirecting the output to my own application, to show in a pane. It adds a new line to AStrings as soon as data comes in, so you'll have access to the output of the other application before it finishes.
procedure RunConsoleApp(const CommandLine: string; AStrings: TStrings);
type
TCharBuffer = array[0..MaxInt div SizeOf(Char) - 1] of Char;
const
MaxBufSize = 1024;
var
I: Longword;
SI: TStartupInfo;
PI: TProcessInformation;
SA: PSecurityAttributes;
SD: PSECURITY_DESCRIPTOR;
NewStdIn: THandle;
NewStdOut: THandle;
ReadStdOut: THandle;
WriteStdIn: THandle;
Buffer: ^TCharBuffer;
BufferSize: Cardinal;
Last: WideString;
Str: WideString;
ExitCode_: DWORD;
Bread: DWORD;
Avail: DWORD;
begin
GetMem(SA, SizeOf(TSecurityAttributes));
case Win32Platform of
VER_PLATFORM_WIN32_NT:
begin
GetMem(SD, SizeOf(SECURITY_DESCRIPTOR));
SysUtils.Win32Check(InitializeSecurityDescriptor(SD, SECURITY_DESCRIPTOR_REVISION));
SysUtils.Win32Check(SetSecurityDescriptorDacl(SD, True, nil, False));
SA.lpSecurityDescriptor := SD;
end; {end VER_PLATFORM_WIN32_NT}
else
SA.lpSecurityDescriptor := nil;
end; {end case}
SA.nLength := SizeOf(SECURITY_ATTRIBUTES);
SA.bInheritHandle := True;
SysUtils.Win32Check(CreatePipe(NewStdIn, WriteStdIn, SA, 0));
if not CreatePipe(ReadStdOut, NewStdOut, SA, 0) then
begin
CloseHandle(NewStdIn);
CloseHandle(WriteStdIn);
SysUtils.RaiseLastWin32Error;
end; {end if}
GetStartupInfo(SI);
SI.dwFlags := STARTF_USESTDHANDLES or STARTF_USESHOWWINDOW;
SI.wShowWindow := {SW_SHOWNORMAL} SW_HIDE;
SI.hStdOutput := NewStdOut;
SI.hStdError := NewStdOut;
SI.hStdInput := NewStdIn;
if not CreateProcess(nil, PChar(CommandLine), nil, nil, True, CREATE_NEW_CONSOLE, nil, nil, SI, PI) then
begin
CloseHandle(NewStdIn);
CloseHandle(NewStdOut);
CloseHandle(ReadStdOut);
CloseHandle(WriteStdIn);
SysUtils.RaiseLastWin32Error;
end; {end if}
Last := '';
BufferSize := MaxBufSize;
Buffer := AllocMem(BufferSize);
try
repeat
SysUtils.Win32Check(GetExitCodeProcess(PI.hProcess, ExitCode_));
PeekNamedPipe(ReadStdOut, Buffer, BufferSize, #Bread, #Avail, nil);
if (Bread <> 0) then
begin
if (BufferSize < Avail) then
begin
BufferSize := Avail;
ReallocMem(Buffer, BufferSize);
end; {end if}
FillChar(Buffer^, BufferSize, #0);
Windows.ReadFile(ReadStdOut, Buffer^, BufferSize, Bread, nil);
Str := Last;
I := 0;
while (I < Bread) do
begin
case Buffer^[I] of
#0: inc(I);
#7: begin
inc(I);
Windows.Beep(800, 50);
Str := Str + '^';
end;
#10:
begin
inc(I);
AStrings.Add(Str);
Str := '';
end; {end #10}
#13:
begin
inc(I);
if (I < Bread) and (Buffer^[I] = #10) then
inc(I);
AStrings.Add(Str);
Str := '';
end; {end #13}
else
begin
Str := Str + Buffer^[I];
inc(I);
end; {end else}
end; {end case}
end; {end while}
Last := Str;
end; {end if}
Sleep(1);
Application.ProcessMessages;
until (ExitCode_ <> STILL_ACTIVE);
if Last <> '' then
AStrings.Add(Last);
finally
FreeMem(Buffer);
end; {end try/finally}
CloseHandle(PI.hThread);
CloseHandle(PI.hProcess);
CloseHandle(NewStdIn);
CloseHandle(NewStdOut);
CloseHandle(ReadStdOut);
CloseHandle(WriteStdIn);
end; {end procedure}
Here is a PHP specific solution, the project allows PHP to obtain and interact dynamically with a real cmd terminal. Get it here: https://github.com/merlinthemagic/MTS
After downloading you would simply use the following code:
//if you prefer Powershell, replace 'cmd' with 'powershell'
$shellObj = \MTS\Factories::getDevices()->getLocalHost()->getShell('cmd');
$strCmd1 = 'some_app.exe -param "test"';
$return1 = $shellObj->exeCmd($strCmd1);
The return will give you the command return OR error from cmd, just as if you sat at the console.
Furthermore, you can issue any command you like against the $shellObj, the environment is maintained throughout the life of the PHP script. So instead of bundling commands in a script file, just issue them one by one using the exeCmd() method, that way you can also handle the return and any exceptions.