从PEM文件中加载(由openssl生成的)DSA私钥。

huangapple go评论92阅读模式
英文:

Load (openssl generated) DSA private key from PEM file

问题

我正在尝试在我的程序中加载一个 DSA 私钥,以下是我的方法:

  1. 使用 OpenSSL 创建一个 DSA 密钥对:

     openssl dsaparam -genkey 2048 -out dsakey.pem
    
  2. 使用以下函数解析 PEM 文件:

     func getDSAPrivateKeyFromPemFile(pemfilepath string) (recoveredprivateKey *dsa.PrivateKey, err error) {
     pemfile, err := os.Open(pemfilepath)
     if err != nil {
     	return nil, err
     }
     recoveredbytes, err := ioutil.ReadAll(pemfile)
     if err != nil {
     	return nil, err
     }
    
     recoveredpemdsaparameteres, rest := pem.Decode(recoveredbytes)
     if recoveredpemdsaparameteres == nil {
     	return nil, errors.New("No pem recovered")
     }
    
     _, err = asn1.Unmarshal(append(recoveredpemdsaparameteres.Bytes, recoveredpemdsaprivatekey.Bytes...), recoveredprivateKey)
     if err != nil {
         return nil, err
      }
      fmt.Printf("PEM:%v\n", recoveredpemdsaparameteres)
    
      recoveredpemdsaprivatekey, _ := pem.Decode(rest)
      fmt.Printf("PEM:%v\n", recoveredpemdsaprivatekey)
      pemfile.Close()
     }
    

当我调用这个函数时,它失败了:

panic: reflect: call of reflect.Value.Type on zero Value

goroutine 1 [running]:
reflect.Value.Type(0x0, 0x0, 0x0, 0x0, 0x0)
	/usr/local/go/src/reflect/value.go:1664 +0x7b
encoding/asn1.parseField(0x0, 0x0, 0x0, 0xc8200b0600, 0x58b, 0x600, 0x0, 0x0, 0x0, 0x0, ...)
	/usr/local/go/src/encoding/asn1/asn1.go:558 +0xbd
encoding/asn1.UnmarshalWithParams(0xc8200b0600, 0x58b, 0x600, 0x1383e0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, ...)
	/usr/local/go/src/encoding/asn1/asn1.go:957 +0x16e
encoding/asn1.Unmarshal(0xc8200b0600, 0x58b, 0x600, 0x1383e0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0)
	/usr/local/go/src/encoding/asn1/asn1.go:950 +0x8f
main.getDSAPrivateKeyFromPemFile(0x1e7fa0, 0x26, 0x0, 0x0, 0x0)

然而,我可以完全看到我的 DSA 密钥的输出:

PEM:&{DSA PARAMETERS map[] [48 130 2 45 2 130...]}
PEM:&{DSA PRIVATE KEY map[] [48 130 3 86 2 1 0 ...]}

问题实际上在于如何将 PEM 字节解组为 dsa.PrivateKey。
有什么想法吗?

附注:我在互联网上找不到任何加载 DSA 私钥 PEM 文件的示例。

英文:

I'm trying to load a dsa private key in my program, Here is how I approached it:

  1. I create a dsa key pair using openssl:

     openssl dsaparam -genkey 2048 -out dsakey.pem
    
  2. I use the following function to parse the pem file

     func getDSAPrivateKeyFromPemFile(pemfilepath string) (recoveredprivateKey *dsa.PrivateKey, err error) {
     pemfile, err := os.Open(pemfilepath)
     if err != nil {
     	return nil, err
     }
     recoveredbytes, err := ioutil.ReadAll(pemfile)
     if err != nil {
     	return nil, err
     }
    
     recoveredpemdsaparameteres, rest := pem.Decode(recoveredbytes)
     if recoveredpemdsaparameteres == nil {
     	return nil, errors.New("No pem recovered")
     }
    
     _, err = asn1.Unmarshal(append(recoveredpemdsaparameteres.Bytes, recoveredpemdsaprivatekey.Bytes...), recoveredprivateKey)
     if err != nil {
         return nil, err
      }
      fmt.Printf("PEM:%v\n", recoveredpemdsaparameteres)
    
      recoveredpemdsaprivatekey, _ := pem.Decode(rest)
      fmt.Printf("PEM:%v\n", recoveredpemdsaprivatekey)
      pemfile.Close()
     }
    

When I call this function if fails:

panic: reflect: call of reflect.Value.Type on zero Value

goroutine 1 [running]:
reflect.Value.Type(0x0, 0x0, 0x0, 0x0, 0x0)
	/usr/local/go/src/reflect/value.go:1664 +0x7b
encoding/asn1.parseField(0x0, 0x0, 0x0, 0xc8200b0600, 0x58b, 0x600, 0x0, 0x0, 0x0, 0x0, ...)
	/usr/local/go/src/encoding/asn1/asn1.go:558 +0xbd
encoding/asn1.UnmarshalWithParams(0xc8200b0600, 0x58b, 0x600, 0x1383e0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, ...)
	/usr/local/go/src/encoding/asn1/asn1.go:957 +0x16e
encoding/asn1.Unmarshal(0xc8200b0600, 0x58b, 0x600, 0x1383e0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0)
	/usr/local/go/src/encoding/asn1/asn1.go:950 +0x8f
main.getDSAPrivateKeyFromPemFile(0x1e7fa0, 0x26, 0x0, 0x0, 0x0)

However, I can perfectly see my dsa key in output:

PEM:&{DSA PARAMETERS map[] [48 130 2 45 2 130...]}
PEM:&{DSA PRIVATE KEY map[] [48 130 3 86 2 1 0 ...]}

The problem is in fact how to unmarshal pem bytes to dsa.PrivateKey.
Any ideas?

P.S: I was not able to find any example of loading DSA private key pem file over the internet.

答案1

得分: 1

在花费了几个小时后,我成功解决了我的问题。我将我的发现发布出来,以便能够节省其他人的时间:

首先,我使用这个很棒的在线工具 http://lapo.it/asn1js/ 来查看我的pem文件编码。只有在那之后,我才意识到go期望pem文件具有不同的结构...不太好!
然后,将文件中的每个值与相应的dsa.PrivateKey结构关联起来并不难。
因此,我创建了一个新的结构体,并将其命名为MyPrivateKey,与pem文件中的顺序相同:

type MyPrivateKey struct {
    E1, P, Q, G, Y, X *big.Int
}

然后,我不再尝试直接解组到dsa.PrivateKey,而是将asn1编码的值解组到我自己创建的结构体中。神奇的是,它起作用了。这是修改后的函数:

func getDSAPrivateKeyFromPemFile(pemFilePath string) (privateKey *dsa.PrivateKey, err error) {
    pemfile, err := os.Open(pemFilePath)

    if err != nil {
        return nil, err
    }
    recoveredBytes, err := ioutil.ReadAll(pemfile)
    if err != nil {
        return nil, err
    }
    pemfile.Close()

    pemDSAParameters, rest := pem.Decode(recoveredBytes)
    if pemDSAParameters == nil {
        return nil, errors.New("No pem recovered")
    }
    pemDSAPrivateKey, _ := pem.Decode(rest)
    keyParameters := dsa.Parameters{G: big.NewInt(0), P: big.NewInt(0), Q: big.NewInt(0)}
    _, err = asn1.Unmarshal(pemDSAParameters.Bytes, &keyParameters)
    if err != nil {
        return nil, err
    }
    //fmt.Printf("\n\n\n\n\n\nP:%x\n\nG:%x\n\nQ:%x\n\n\n\n\n\n", keyParameters.P, keyParameters.G, keyParameters.Q)
    myPrivateKey := MyPrivateKey{}
    _, err = asn1.Unmarshal(pemDSAPrivateKey.Bytes, &myPrivateKey)
    if err != nil {
        return nil, err
    }
    //fmt.Printf("\nprivate\nE1:%x\n\nP:%x\n\nQ:%x\n\nG:%x\n\nY:%x\nX:%x\n\n\n\n", myPrivateKey.E1, myPrivateKey.P, myPrivateKey.Q, myPrivateKey.G, myPrivateKey.Y, myPrivateKey.X)
    privateKey = &dsa.PrivateKey{}
    privateKey.Parameters = keyParameters
    privateKey.X = myPrivateKey.X

    return privateKey, nil
}

也许有更简单的方法来解决这个问题,我可能只是忽略了!如果你知道更好的方法,请不吝赐教!否则,我认为go应该在标准库中处理这种问题。

英文:

After spending couple of hours, I managed to fix my problem
I post my finding so it may save someone's time:

First I reviewed my pem file encoding using this great online tool: http://lapo.it/asn1js/. Only then I realized go is expecting the pem file to have different structure... Not nice!
Aftwerwards, it was not hard to relate each value within the file to the corresponding dsa.PrivateKey struct.
So, I made a new struct and named it MyPrivateKey with the same order as the pem file:

type MyPrivateKey struct {
    E1, P, Q, G, Y, X *big.Int
}

Then, instead of trying to unmarshal directly to dsa.PrivateKey, I unmarshaled the asn1 encoded value to my self made struct. And magically it worked. Here is the modified func:

func getDSAPrivateKeyFromPemFile(pemFilePath string) (privateKey *dsa.PrivateKey, err error) {
	pemfile, err := os.Open(pemFilePath)

	if err != nil {
		return nil, err
	}
	recoveredBytes, err := ioutil.ReadAll(pemfile)
	if err != nil {
		return nil, err
	}
	pemfile.Close()

	pemDSAParameters, rest := pem.Decode(recoveredBytes)
	if pemDSAParameters == nil {
		return nil, errors.New("No pem recovered")
	}
	pemDSAPrivateKey, _ := pem.Decode(rest)
	keyParameters := dsa.Parameters{G: big.NewInt(0), P: big.NewInt(0), Q: big.NewInt(0)}
	_, err = asn1.Unmarshal(pemDSAParameters.Bytes, &keyParameters)
	if err != nil {
		return nil, err
	}
	//fmt.Printf("\n\n\n\n\n\nP:%x\n\nG:%x\n\nQ:%x\n\n\n\n\n\n", keyParameters.P, keyParameters.G, keyParameters.Q)
	myPrivateKey := MyPrivateKey{}
	_, err = asn1.Unmarshal(pemDSAPrivateKey.Bytes, &myPrivateKey)
	if err != nil {
		return nil, err
	}
	//fmt.Printf("\nprivate\nE1:%x\n\nP:%x\n\nQ:%x\n\nG:%x\n\nY:%x\nX:%x\n\n\n\n", myPrivateKey.E1, myPrivateKey.P, myPrivateKey.Q, myPrivateKey.G, myPrivateKey.Y, myPrivateKey.X)
	privateKey = &dsa.PrivateKey{}
	privateKey.Parameters = keyParameters
	privateKey.X = myPrivateKey.X

	return privateKey, nil
}

Maybe there was a much easier way to this all and I simply overlooked! If you know a better way please be my guest! Otherwise, I believe go should handle this kind of issues in the standard libraries.

huangapple
  • 本文由 发表于 2015年10月23日 19:33:24
  • 转载请务必保留本文链接:https://go.coder-hub.com/33301318.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定