Using jwt-go Library - Key is invalid or invalid type - parsing

I am trying to pass in a token to the "Parse(token String, keyFunc Keyfunc)" GO routine defined in this GO-library (http://godoc.org/github.com/dgrijalva/jwt-go) for JWT-token parsing/validation.
When I pass the token to this function -
token, err := jwt.Parse(getToken, func(token *jwt.Token) (interface{}, error) {
return config.Config.Key, nil
})
I get an error which says "Key is invalid or invalid type".
My config struct looks like this in config.go file -
config struct {
Key string
}
Any suggestions to solve this problem? The token I am passing is a JWT token.

config struct {
Key string
}
Key needs to be a []byte

I am not sure if this can be an issue for someone else.
My problem was I was using Signing Method "SigningMethodES256" but "SigningMethodHS256" or Any with SigningMethodHS* works fine.
If someone knows why this is an issue please answer.

Other way is to do something like this -
token, err := jwt.Parse(getToken, func(token *jwt.Token) (interface{}, error) {
return []byte(config.Config.Key), nil
})
The whole idea being that the Parse function returns a slice of bytes.

Taking a look at the function signatures in the GoDoc for github.com/dgrijalva/jwt-go we see:
func Parse(tokenString string, keyFunc Keyfunc) (*Token, error)
type Keyfunc func(*Token) (interface{}, error)
Keyfunc requires you to return (interface{}, error). Given the mysterious interface{} type, you might expect to be fine returning a string; however, a peek under the hood reveals that Parse() tries to Verify(), which attempts the following type assertion with your interface{} value as the key:
keyBytes, ok := key.([]byte)
That will succeed for []byte types, but will fail for string types. When that fails, the result is the error message you are getting. Read more about type assertions in the Effective Go documentation to learn why it fails.
Example: https://play.golang.org/p/9KKNFLLQrm
package main
import "fmt"
func main() {
var a interface{}
var b interface{}
a = []byte("hello")
b = "hello"
key, ok := a.([]byte)
if !ok {
fmt.Println("a is an invalid type")
} else {
fmt.Println(key)
}
key, ok = b.([]byte)
if !ok {
fmt.Println("b is an invalid type")
} else {
fmt.Println(key)
}
}
[104 101 108 108 111]
b is an invalid type

This is working for me.
token.SignedString([]byte("mysecretkey"))
func GenerateJWT(email string, username string) (tokenString string, err error) {
expirationTime := time.Now().Add(1 * time.Hour)
claims := &JWTClime{
Email: email,
Username: username,
StandardClaims: jwt.StandardClaims{
ExpiresAt: expirationTime.Unix(),
},
}
token := jwt.NewWithClaims(jwt.SigningMethodHS256, claims)
tokenString, err = token.SignedString([]byte("mysecretkey"))
return
}

Related

Go-Ethereum iOS cannot unmarshal results

So I'm playing around with go-ethereum in iOS and I'm having quite a bit of trouble trying to interact with a contract deployed to Rinkeby testnet, I'm very new to the whole blockchain technology so any help is appreciated.
All I'm trying to do is access a deployed contract and get the value of a string but the issue I'm having is I get this error when I try to make a call to a bound contract:
Thread 1: Fatal error: 'try!' expression unexpectedly raised an error: Error Domain=go Code=1 "abi: cannot unmarshal string in to []interface {}" UserInfo={NSLocalizedDescription=abi: cannot unmarshal string in to []interface {}}
this is the code I'm using to make the call.
// Declare the error variables
var clientError: NSErrorPointer;
var addressError: NSErrorPointer;
var contractError: NSErrorPointer;
// Get the bindContract from Rinkeby test network.
let client = GethNewEthereumClient("https://rinkeby.infura.io/v3/398ed56d211646faaf010ca183de11f2", clientError);
let contractAddress = GethNewAddressFromHex("0x7259667715d671Ee370d7788647f95Fe7C3B532d", addressError);
guard let contractABI = ReadJsonResourceAsString(fileName: "InboxContractInterface", fileType: "json") else {
print("[ViewController] failed to read the abi json as string.")
return;
}
let boundContract = GethBindContract(contractAddress, contractABI, client, contractError);
// Prepare the callOpts
let callOpts = GethNewCallOpts();
callOpts?.setGasLimit(300000);
callOpts?.setContext(GethNewContext());
// Prepare the results & params interfaces
let results = GethNewInterfaces(1);
let params = GethNewInterfaces(0);
let stringResult = GethNewInterface();
stringResult?.setDefaultString();
try! results?.set(0, object: stringResult);
// Make the call
let methodName = "message";
try! boundContract?.call(callOpts, out_: results, method: methodName, args: params);
// Show results.
print("[ViewController] message call result: " + (stringResult?.getString())!);
And this is my contract's code:
pragma solidity ^0.4.17;
contract Inbox {
string public message;
function Inbox (string initialMessage) public {
message = initialMessage;
}
function setMessage (string newMessage) public {
message = newMessage;
}
}
For anyone that might find the same issue after digging a bit more I found this issue for android: https://github.com/ethereum/go-ethereum/issues/14832
Luckily this is already fixed, so it was totally my fault for not using the latest version.
I was using Geth v1.5.9 so after updating to v1.8.2 it finally worked, not sure which version in-between got fixed tho.

Extract value string from URL

I want to retrieve a value from a URL. Provided I have a URL such as http://myurl.com/theValue1/iWantToRetrieveThis, I want to split this value and want to retrieve theValue1 and iWantToRetrieveThis. How can I do this?
I tried the code below but it seems that it's only retrieving the query string:
func decodeGetTokenRequest(_ context.Context, r *http.Request) (request interface{}, err error) {
fmt.Println("decoding here", path.Base(r.URL))
return getTokenRequest{
SellerID: r.URL.Query().Get("sellerid"), <<--- THis is empty
Scope: r.URL.Query().Get("scope"), <<-- This is also empty
Authorization: Validation{
credential: r.Header.Get("ETM-API-AUTH-KEY"),
},
}, nil
}
Ok I just had to go with #Rafal answer since what I'm trying to retrieve is not a query parameter but part of the url.

Encrypt RSA/ECB/OAEPWithSHA-256AndMGF1Padding Swift

I am going to say in advance i don't know too much about cryptography (Basics only). I am trying to Implement a Credential OpenHome Service and I want to encrypt a password to send it to the device.
The device provides a function written in C that returns a public key String that looks like that:
MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCzjFGuEKD0uWxzb47oRbiSP2uDwVJPeWU7m9VXi626V6lameTzdtwj2eYVZTIAsAW7yW4or2skn7oHqFG4GvhMzgMwoQjKFxeCPPFXRSotnt26AN1DhvFJp3V/d+MpmkzI07iWcD5eNe4EVNK9GSE4JOEHhJ/JYBVMiu04XE5aqwIDAQAB
The Android implementation has been already done and the specs given are
RSA/ECB/OAEPWithSHA-256AndMGF1Padding
also there is a web site that gives "instructions" when encrypting
http://wiki.openhome.org/wiki/Av:Developer:CredentialsService
I have tried so far these libraries:
SwiftyRSA, Heimdall, SwCrypt
I really thing that one of my main failures are I don't understand what I have, what do I need and finally how to achieve it using swift.
ideally at the end i will have a functions like
func encryptMessage(message:String, whithPublicKey key:String)->String
thank you very much.
After a long research i have just implemented my own solution rather than using libraries and not understanding what was going on. It is always good to know what happens and it this case it is not rocket science.
On iOS if you want to encrypt/decrypt you need to use a key stored on the keychain. If, in my case, i have been given the public key i can import it and also I can do the same with the private key. Please see my HelperClass Here.
Then, and from only from iOS 10, you can call this 2 methods for encrypting and decrypting
let error:UnsafeMutablePointer<Unmanaged<CFError>?>? = nil
let plainData = "A Plain text...".data(using: .utf8)
if let encryptedMessageData:Data = SecKeyCreateEncryptedData(publicSecKey, .rsaEncryptionOAEPSHA256, plainData! as CFData,error) as Data?{
print("We have an encrypted message")
let encryptedMessageSigned = encryptedMessageData.map { Int8(bitPattern: $0) }
print(encryptedMessageSigned)
if let decryptedMessage:Data = SecKeyCreateDecryptedData(privateSecKey, .rsaEncryptionOAEPSHA256, encryptedMessageData as CFData,error) as Data?{
print("We have an decrypted message \(String.init(data: decryptedMessage, encoding: .utf8)!)")
}
else{
print("Error decrypting")
}
}
else{
print("Error encrypting")
}
Also, if you want before iOS 10 you have the functions:
func SecKeyEncrypt(_ key: SecKey,
_ padding: SecPadding,
_ plainText: UnsafePointer<UInt8>,
_ plainTextLen: Int,
_ cipherText: UnsafeMutablePointer<UInt8>,
_ cipherTextLen: UnsafeMutablePointer<Int>) -> OSStatus
And
func SecKeyDecrypt(_ key: SecKey,
_ padding: SecPadding,
_ cipherText: UnsafePointer<UInt8>,
_ cipherTextLen: Int,
_ plainText: UnsafeMutablePointer<UInt8>,
_ plainTextLen: UnsafeMutablePointer<Int>) -> OSStatus
But these give less options and They are quite resticted.
Worth mentioning that my public and private key where generate on android using
public static String createStringFromPublicKey(Key key) throws Exception {
X509EncodedKeySpec x509EncodedKeySpec = new X509EncodedKeySpec(key.getEncoded());
return new String(Base64.encode(x509EncodedKeySpec.getEncoded(), Base64.NO_WRAP), "UTF-8");
}
and
public static String createStringFromPrivateKey(Key key) throws Exception {
PKCS8EncodedKeySpec pkcs8EncodedKeySpec = new PKCS8EncodedKeySpec(key.getEncoded());
return new String(Base64.encode(pkcs8EncodedKeySpec.getEncoded(), Base64.NO_WRAP), "UTF-8");
}

Decode JSON from stream of data Docker GO SDK

I want to use Client.ContainerStats(ctx context.Context, containerID string, stream bool) method to get streaming stats of a container.
From what I understand, if I pass true to stream parameter, Docker will not close connection and periodically sends JSON containing stats of a container.
However, I don't know how decode JSON because I don't know where JSON data start and end.
What I'm using right now is that I don't use stream option and just fetch data periodically then decode it like this.
stats, err := dockerClient.ContainerStats(ctx, container.ContainerID, false)
msgBytes, _ := ioutil.ReadAll(stats.Body)
var containerStats ContainerStats
err = json.Unmarshal(msgBytes, &containerStats)
What I'm looking for is a function that block when I call it, then when it receives JSON data (I mean complete JSON data that can be decoded) it will return struct containing data that was decoded from JSON and then I can call that function again to get next stat without having to make a new request to Docker.
In your case, you have multiple options:
Map the result on a custom struct
Map the result on a map[string]interface{}
If you want to map by using a custom struct you can do something like this:
type myStruct struct {
Id string `json:"id"`
Read string `json:"read"`
Preread string `json:"preread"`
}
// perform actions to retrieve logs in stats
//...
var containerStats myStruct
json.NewDecoder(stats.Body).Decode(&containerStats)
fmt.Println(containerStats.Id)
With this solution, you have to decide which fields you want to map.
However, if you do not want to specify fields, you can perform something like this:
//Perform actions to retrieve logs in stats
//...
var containerStats map[string]interface{}
json.NewDecoder(stats.Body).Decode(&containerStats)
fmt.Println(containerStats["id"])
To conclude, if you have to manipulate your data, I recommend you to use the first solution by using custom structure.
EDITED: handle stream
By passing stream parameter to true, the docker api will return an io.ReadCloser which will be updated. Then, it's up to the caller to close the io.ReadCloser returned.
What you have to do is to perdiodically read the buffer value.
type myStruct struct {
Id string `json:"id"`
Read string `json:"read"`
Preread string `json:"preread"`
CpuStats cpu `json:"cpu_stats"`
}
type cpu struct {
Usage cpuUsage `json:"cpu_usage"`
}
type cpuUsage struct {
Total float64 `json:"total_usage"`
}
func main() {
ctx, cancel := context.WithTimeout(context.Background(), 5 * time.Second)
cli, e := client.NewEnvClient()
if e != nil {
panic(e)
}
stats, e := cli.ContainerStats(ctx, "container_id", true)
if e != nil {
fmt.Errorf("%s", e.Error())
}
decoder := json.NewDecoder(stats.Body)
var containerStats myStruct
for {
select {
case <-ctx.Done():
stats.Body.Close()
fmt.Println("Stop logging")
return
default:
if err := decoder.Decode(&containerStats); err == io.EOF {
return
} else if err != nil {
cancel()
}
fmt.Println(containerStats.CpuStats.Usage.Total)
}
}
}
In this example, we are decoding the stats.Body ReadCloser when new data arrives, printing the total cpu usage, and closing the stream after 5 seconds.

Go Anaconda twitter media upload with tweet

I can tweet, and upload media, but I cannot figure out how to tweet with the media using anaconda("github.com/ChimeraCoder/anaconda"). The media_id in the example was from a sucessfull media upload call.
mediaResponse, err := api.UploadMedia("R0lGODlhEAALALMMAOXp8a2503CHtOrt9L3G2+Dl7vL0+J6sy4yew1Jvp/T2+e/y9v///wAAAAAAAAAAACH/C05FVFNDQVBFMi4wAwEAAAAh+QQFCwAMACwAAAAAEAALAAAEK5DJSau91KxlpObepinKIi2kyaAlq7pnCq9p3NZ0aW/47H4dBjAEwhiPlAgAIfkECQsADAAsAAAAAAQACwAABA9QpCQRmhbflPnu4HdJVAQAIfkECQsADAAsAAAAABAACwAABDKQySlSEnOGc4JMCJJk0kEQxxeOpImqIsm4KQPG7VnfbEbDvcnPtpINebJNByiTVS6yCAAh+QQJCwAMACwAAAAAEAALAAAEPpDJSaVISVQWzglSgiAJUBSAdBDEEY5JMQyFyrqMSMq03b67WY2x+uVgvGERp4sJfUyYCQUFJjadj3WzuWQiACH5BAkLAAwALAAAAAAQAAsAAAQ9kMlJq73hnGDWMhJQFIB0EMSxKMoiFcNQmKjKugws0+navrEZ49S7AXfDmg+nExIPnU9oVEqmLpXMBouNAAAh+QQFCwAMACwAAAAAEAALAAAEM5DJSau91KxlpOYSUBTAoiiLZKJSMQzFmjJy+8bnXDMuvO89HIuWs8E+HQYyNAJgntBKBAAh+QQFFAAMACwMAAIABAAHAAAEDNCsJZWaFt+V+ZVUBAA7")
if err != nil {
fmt.Println(err)
}
//v := url.Values{}
//v.Set("media_ids", string(mediaResponse.MediaID))
fmt.Println(mediaResponse)
tweet := `
"media_ids": 612877656984416256,
"status": "hello"
`
result, err := api.PostTweet(tweet, nil)
if err != nil {
fmt.Println(err)
} else {
fmt.Println(result)
}
Can someone assist in telling me how to parse the json or call the PostTweet with the media id? I've also tried adding the media to url.Values without sucess.
Thanks everyone. I see that the json was invalid but the issue was an error passing the media_ids parameter. The response was: "errors":[{"code":44,"message":"media_ids parameter is invalid."}] which i though erroring out on the formatting but it had to do with not converting the media_ids type int64 to a string correctly. Here is the fixed code:
data, err := ioutil.ReadFile(fileName)
if err != nil {
fmt.Println(err)
}
mediaResponse, err := api.UploadMedia(base64.StdEncoding.EncodeToString(data))
if err != nil {
fmt.Println(err)
}
v := url.Values{}
v.Set("media_ids", strconv.FormatInt(mediaResponse.MediaID, 10))
result, err := api.PostTweet(posttitle, v)
if err != nil {
fmt.Println(err)
} else {
fmt.Println(result)
}
This is not valid json:
tweet := `
"media_ids": 612877656984416256,
"status": "hello"
`
Try using this to generate your json:
type Tweet struct {
MediaIds uint64 `json:"media_ids"`
Status string `json:"status"`
}
tweet := Tweet{612877656984416256, "hello"}
b, err := json.Marshal(tweet)
This results in :
{"media_ids":612877656984416256,"status":"hello"}
This has a few benefits over using a raw string.
It is more go centric. The struct can be passed around with values set and read with proper type checking caught at compile time.
The generated json string is more likely to be semantically correct. e.g. Go will also escape certain characters to help ensure they will be parsed properly by the receiver.

Resources