I am trying to write a service in Go that takes the parameters given by GameCenter in
//GKLocalPlayer
- (void)generateIdentityVerificationSignatureWithCompletionHandler:(void (^)(NSURL *publicKeyUrl, NSData *signature, NSData *salt, uint64_t timestamp, NSError *error))completionHandler
Inside the completionHandler of the method, I am sending the public key URL, base 64 encoded signature, base 64 encoded salt, timestamp and the user's game center ID to my Go service. Inside my Go (in Google App Engine), this is what I am doing:
Get the certificate from the public key URL
Decode signature and salt
Form the payload based on player ID, bundle ID, timestamp and
salt
Use X509.CheckSignature to verify that the payload matches the
signature when it's hased with the public key
*I know that I still need to verify with the certificate authority but I am skipping that for now (if you know how to do that in Go for this case, please please please share!)
Problem: CheckSignature is returning crypto/rsa: verification error and I really think that I am doing everything as instructed by Apple
https://developer.apple.com/library/ios/documentation/GameKit/Reference/GKLocalPlayer_Ref/Reference/Reference.html#//apple_ref/doc/uid/TP40009587-CH1-SW25
And the code that I have so far:
func (v *ValidationRequest) ValidateGameCenter(publicKeyUrl string, playerId string, bundleId string, signature string, salt string, timestamp uint64) error {
client := urlfetch.Client(v.Context)
resp, err := client.Get(publicKeyUrl)
if err != nil {
v.Context.Errorf("%v", err.Error())
return err
}
body, err := ioutil.ReadAll(resp.Body)
if err != nil {
v.Context.Errorf("%v", err.Error())
return err
}
cert, err := x509.ParseCertificate(body)
if err != nil {
v.Context.Errorf("%v", err.Error())
return err
}
signatureBytes, err := base64.StdEncoding.DecodeString(signature)
saltBytes, err:= base64.StdEncoding.DecodeString(salt)
payload, err := formPayload(v, playerId, bundleId, timestamp, saltBytes)
if err != nil {
v.Context.Errorf("%v", err.Error())
return err
}
err = cert.CheckSignature(cert.SignatureAlgorithm, payload, signatureBytes)
if err != nil {
v.Context.Errorf("%v", err.Error())
return err
}
return nil
}
func formPayload(v *ValidationRequest, playerId string, bundleId string, timestamp uint64, salt []byte) ([]byte, error) {
bundleIdBytes := []byte(bundleId)
playerIdBytes := []byte(playerId)
payloadBuffer := new(bytes.Buffer)
written, err := payloadBuffer.Write(playerIdBytes)
if err != nil {
return nil, err
}
written, err = payloadBuffer.Write(bundleIdBytes)
if err != nil {
return nil, err
}
var bigEndianTimestamp []byte = make([]byte, 8)
binary.BigEndian.PutUint64(bigEndianTimestamp, timestamp)
if written != len(bundleIdBytes) {
return nil, errors.New(fmt.Sprintf("Failed writing all bytes. Written: %d Length: %d", written, len(bundleIdBytes)))
}
written, err = payloadBuffer.Write(bigEndianTimestamp)
if err != nil {
return nil, err
}
if written != len(bigEndianTimestamp) {
return nil, errors.New(fmt.Sprintf("Failed writing all bytes. Written: %d Length: %d", written, len(bigEndianTimestamp)))
}
written, err = payloadBuffer.Write(salt)
if err != nil {
return nil, err
}
if written != len(salt) {
return nil, errors.New(fmt.Sprintf("Failed writing all bytes. Written: %d Length: %d", written, len(salt)))
}
return payloadBuffer.Bytes(), nil
}
Related
I have a problem. I want to write something similar to a turnstile, with face recognition. I use gocv and kagami/go-face for this. I have a stream from a webcam. The problem is that it recognizes the image too quickly and every time it recognizes a face, it opens a passage for it. That is, it pulls the opening function 10 times per second, for example. And I want him to open it once. So I have 2 functions readStream and opener. Maybe you can somehow not read the stream or stop the stream until another person appears in the frame? The goroutine go readStream() is called first, and then go opener()
func readStream(c chan int) {
recognizer, err := face.NewRecognizer(config.Recognizer.ModelsDir)
if err != nil {
log.Fatalf("Can't init face recognizer: %v", err)
}
webcam, err := gocv.OpenVideoCapture(videoSrc)
if err != nil {
log.Fatalf("Error opening capture device: %v", videoSrc)
}
img := gocv.NewMat()
defer img.Close()
window := gocv.NewWindow("videosourse")
defer window.Close()
for {
if ok := webcam.Read(&img); !ok || img.Empty() {
fmt.Printf("Device closed: %v\n", videoSrc)
return
}
jpgImageBuffer, err := gocv.IMEncode(gocv.JPEGFileExt, img)
if err != nil {
log.Errorf("ERROR: %s", err.Error())
}
f, err := recognizer.RecognizeSingle(jpgImageBuffer.GetBytes())
if err == nil && f != nil {
catID := recognizer.ClassifyThreshold(f.Descriptor, config.Recognizer.Tolerance)
if catID > 0 {
c <- catID
}
}
window.IMShow(img)
window.WaitKey(1)
}
}
func opener(c chan int) {
timeout := time.After(5 * time.Second)
for {
select {
case id := <-c:
fmt.Printf("####### OPENED for %d #######\n", id)
case <-timeout:
<-c
fmt.Println("Time's up! All data read in nothing")
break
}
}
}
i tried to use sync.once , but it stopped the webcam video stream after 1st recognition
I tried with this code but the result is not as expected, maybe I am wrong somewhere, please help.
gcrypt.vapi from: https://gitlab.gnome.org/GNOME/vala-extra-vapis
using GCrypt;
using Posix;
void main () {
GCrypt.Cipher.Cipher cipher;
GCrypt.Error err = GCrypt.Cipher.Cipher.open(out cipher, Cipher.Algorithm.AES128, Cipher.Mode.CBC, Cipher.Flag.SECURE);
if (err != 0) {
print("Error: %s\n", err.to_string());
Process.exit(EXIT_FAILURE);
}
string iv = "1111111111111111";
string key = "2222222222222222";
err = cipher.set_key(key.data);
if (err != 0) {
print("Error key: %s\n", err.to_string());
Process.exit(EXIT_FAILURE);
}
err = cipher.set_iv(iv.data);
if (err != 0) {
print("Error iv: %s\n", err.to_string());
Process.exit(EXIT_FAILURE);
}
string str = "Hello World!!!!!";
uchar[] ary = new uchar[str.length];
print("ary: %d\n", ary.length);
err = cipher.encrypt(ary, str.data);
if (err != 0) {
print("Error encrypt: %s\n", err.to_string());
Process.exit(EXIT_FAILURE);
}
string result = Base64.encode(ary);
print("ary: %d\n", ary.length);
print("result: %s\n", result); // tus0150r+OSFg63kxluXpg==
// expect result: tus0150r+OSFg63kxluXpmlrUQOsLMbbgx51GhLZats=
cipher.close();
Process.exit(EXIT_SUCCESS);
}
Your output buffer ary is sized too small so you're losing data. You can't assume that the encrypted output will be the same size as the input data:
uchar[] ary = new uchar[str.length]
Edit: I was incorrect, since AES is a block cipher the size will be the same, however the padding scheme must be considered
Here's an example of creating an output buffer of the correct size (granted it's for AES256, not AES128, so you'll need to make some adjustment): https://github.com/JCWasmx86/LFinance/blob/e6057b38a594ecbef728b212d9aa7df8cd8e869b/src/crypto/encryption.vala
That code has a link out to another Stack Overflow post about determining the correct size: Size of data after AES/CBC and AES/ECB encryption
Unfortunately I don't know enough about AES to provide the exact size that you'll need, but hopefully this gets you going in the right direction!
I'am learning to use sqlx,but now I have a problem.
[signal SIGSEGV: segmentation violation code=0x1 addr=0x0 pc=0x7006c8]
goroutine 1 [running]:
github.com/jmoiron/sqlx.(*DB).QueryRowx(0x0, {0x75cb6a, 0x22}, {0xc000090c70, 0x1, 0x1})
This is my code and I don't know why this error occurring.
import (
"fmt"
_ "github.com/go-sql-driver/mysql"
"github.com/jmoiron/sqlx"
)
var DB *sqlx.DB
func initializeDatabases() (err error) {
dsn := "user:password#tcp(127.0.0.1:3306)/test?charset=utf8mb4&parseTime=True"
DB, err := sqlx.Connect("mysql", dsn)
if err != nil {
fmt.Printf("connect 2 dtatbase failed,err:%v\n", err)
return
}
DB.SetMaxOpenConns(10)
DB.SetMaxIdleConns(10)
return err
}
func sqlxQuerySingleRow() {
sqlStr := "select * from student where id = ?"
var u User
if err := DB.Get(&u, sqlStr, 1); err != nil {
return
}
fmt.Println("id:%d,name:%s,age:%d", u.Id, u.Name, u.Age)
}
func main() {
if err := initializeDatabases(); err != nil {
panic(err)
}
fmt.Println("connect success")
sqlxQuerySingleRow()
//sqlxMultiRow()
}
I know why,because I defined the DB as a global variable,but in the initializeDatabases() function,I declared the DB by:= which causes the returned Client connection to only take effect in the initializeDatabases()function,so I should change:= to =
I’m trying to figure out how I can use the Go client (http://godoc.org/github.com/moby/moby/client) to pull a file from a docker image at a specific version (tag)
I want to download the image and then copy a file from the image onto the local file system. I see a lot of commands for dealing with an image, but not how to access its contents. I do see ways to access a container’s contents.
I’m suspecting I would need to download the image, create a container with the image and finally copy the contents out of the container. Though if I could avoid creating a container, that would be preferred.
Does anyone know exactly how to do this? Code snippet would be appreciated.
Thanks!
You must start the container, copy the file and then remove the container... It's not really an expensive operation since the container isn't started anyway.
Here's a working example that copies a file from the specified image to standard output. The API is straightforward to follow:
https://docs.docker.com/engine/api/get-started/
https://godoc.org/github.com/moby/moby/client
https://gist.github.com/ricardobranco777/a3be772935dfb1a183e0831496925585
package main
import (
"archive/tar"
"fmt"
"io"
"io/ioutil"
"os"
"github.com/docker/docker/api/types"
"github.com/docker/docker/api/types/container"
"github.com/docker/docker/client"
"golang.org/x/net/context"
)
func main() {
if len(os.Args) != 3 {
fmt.Fprintf(os.Stderr, "Usage: %s IMAGE FILE\n", os.Args[0])
os.Exit(1)
}
imageName := os.Args[1]
filePath := os.Args[2]
ctx := context.Background()
cli, err := client.NewEnvClient()
if err != nil {
panic(err)
}
out, err := cli.ImagePull(ctx, imageName, types.ImagePullOptions{})
if err != nil {
panic(err)
}
defer out.Close()
if _, err := ioutil.ReadAll(out); err != nil {
panic(err)
}
info, err := cli.ContainerCreate(ctx, &container.Config{
Image: imageName,
}, nil, nil, "")
if err != nil {
panic(err)
}
tarStream, _, err := cli.CopyFromContainer(ctx, info.ID, filePath)
if err != nil {
panic(err)
}
tr := tar.NewReader(tarStream)
if _, err := tr.Next(); err != nil {
panic(err)
}
io.Copy(os.Stdout, tr)
if err := cli.ContainerRemove(ctx, info.ID, types.ContainerRemoveOptions{}); err != nil {
panic(err)
}
}
For example, having basic packet protocol, like:
[packetType int][packetId int][data []byte]
And making a client and server doing simple things with it (egx, chatting.)
Here's a client and server with sloppy panic error-handling. They have some limitations:
The server only handles one client connection at a time. You could fix this by using goroutines.
Packets always contain 100-byte payloads. You could fix this by putting a length in the packet somewhere and not using encoding/binary for the entire struct, but I've kept it simple.
Here's the server:
package main
import (
"encoding/binary"
"fmt"
"net"
)
type packet struct {
// Field names must be capitalized for encoding/binary.
// It's also important to use explicitly sized types.
// int32 rather than int, etc.
Type int32
Id int32
// This must be an array rather than a slice.
Data [100]byte
}
func main() {
// set up a listener on port 2000
l, err := net.Listen("tcp", ":2000")
if err != nil {
panic(err.String())
}
for {
// start listening for a connection
conn, err := l.Accept()
if err != nil {
panic(err.String())
}
handleClient(conn)
}
}
func handleClient(conn net.Conn) {
defer conn.Close()
// a client has connected; now wait for a packet
var msg packet
binary.Read(conn, binary.BigEndian, &msg)
fmt.Printf("Received a packet: %s\n", msg.Data)
// send the response
response := packet{Type: 1, Id: 1}
copy(response.Data[:], "Hello, client")
binary.Write(conn, binary.BigEndian, &response)
}
Here's the client. It sends one packet with packet type 0, id 0, and the contents "Hello, server". Then it waits for a response, prints it, and exits.
package main
import (
"encoding/binary"
"fmt"
"net"
)
type packet struct {
Type int32
Id int32
Data [100]byte
}
func main() {
// connect to localhost on port 2000
conn, err := net.Dial("tcp", ":2000")
if err != nil {
panic(err.String())
}
defer conn.Close()
// send a packet
msg := packet{}
copy(msg.Data[:], "Hello, server")
err = binary.Write(conn, binary.BigEndian, &msg)
if err != nil {
panic(err.String())
}
// receive the response
var response packet
err = binary.Read(conn, binary.BigEndian, &response)
if err != nil {
panic(err.String())
}
fmt.Printf("Response: %s\n", response.Data)
}
Check out Jan Newmarch's "Network programming with Go".