25개 이상의 토픽을 선택하실 수 없습니다. Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 

147 lines
3.8 KiB

  1. // Copyright 2013 The Go Authors. All rights reserved.
  2. // Use of this source code is governed by a BSD-style
  3. // license that can be found in the LICENSE file.
  4. package packet
  5. import (
  6. "crypto"
  7. "encoding/binary"
  8. "fmt"
  9. "io"
  10. "strconv"
  11. "time"
  12. "golang.org/x/crypto/openpgp/errors"
  13. "golang.org/x/crypto/openpgp/s2k"
  14. )
  15. // SignatureV3 represents older version 3 signatures. These signatures are less secure
  16. // than version 4 and should not be used to create new signatures. They are included
  17. // here for backwards compatibility to read and validate with older key material.
  18. // See RFC 4880, section 5.2.2.
  19. type SignatureV3 struct {
  20. SigType SignatureType
  21. CreationTime time.Time
  22. IssuerKeyId uint64
  23. PubKeyAlgo PublicKeyAlgorithm
  24. Hash crypto.Hash
  25. HashTag [2]byte
  26. RSASignature parsedMPI
  27. DSASigR, DSASigS parsedMPI
  28. }
  29. func (sig *SignatureV3) parse(r io.Reader) (err error) {
  30. // RFC 4880, section 5.2.2
  31. var buf [8]byte
  32. if _, err = readFull(r, buf[:1]); err != nil {
  33. return
  34. }
  35. if buf[0] < 2 || buf[0] > 3 {
  36. err = errors.UnsupportedError("signature packet version " + strconv.Itoa(int(buf[0])))
  37. return
  38. }
  39. if _, err = readFull(r, buf[:1]); err != nil {
  40. return
  41. }
  42. if buf[0] != 5 {
  43. err = errors.UnsupportedError(
  44. "invalid hashed material length " + strconv.Itoa(int(buf[0])))
  45. return
  46. }
  47. // Read hashed material: signature type + creation time
  48. if _, err = readFull(r, buf[:5]); err != nil {
  49. return
  50. }
  51. sig.SigType = SignatureType(buf[0])
  52. t := binary.BigEndian.Uint32(buf[1:5])
  53. sig.CreationTime = time.Unix(int64(t), 0)
  54. // Eight-octet Key ID of signer.
  55. if _, err = readFull(r, buf[:8]); err != nil {
  56. return
  57. }
  58. sig.IssuerKeyId = binary.BigEndian.Uint64(buf[:])
  59. // Public-key and hash algorithm
  60. if _, err = readFull(r, buf[:2]); err != nil {
  61. return
  62. }
  63. sig.PubKeyAlgo = PublicKeyAlgorithm(buf[0])
  64. switch sig.PubKeyAlgo {
  65. case PubKeyAlgoRSA, PubKeyAlgoRSASignOnly, PubKeyAlgoDSA:
  66. default:
  67. err = errors.UnsupportedError("public key algorithm " + strconv.Itoa(int(sig.PubKeyAlgo)))
  68. return
  69. }
  70. var ok bool
  71. if sig.Hash, ok = s2k.HashIdToHash(buf[1]); !ok {
  72. return errors.UnsupportedError("hash function " + strconv.Itoa(int(buf[2])))
  73. }
  74. // Two-octet field holding left 16 bits of signed hash value.
  75. if _, err = readFull(r, sig.HashTag[:2]); err != nil {
  76. return
  77. }
  78. switch sig.PubKeyAlgo {
  79. case PubKeyAlgoRSA, PubKeyAlgoRSASignOnly:
  80. sig.RSASignature.bytes, sig.RSASignature.bitLength, err = readMPI(r)
  81. case PubKeyAlgoDSA:
  82. if sig.DSASigR.bytes, sig.DSASigR.bitLength, err = readMPI(r); err != nil {
  83. return
  84. }
  85. sig.DSASigS.bytes, sig.DSASigS.bitLength, err = readMPI(r)
  86. default:
  87. panic("unreachable")
  88. }
  89. return
  90. }
  91. // Serialize marshals sig to w. Sign, SignUserId or SignKey must have been
  92. // called first.
  93. func (sig *SignatureV3) Serialize(w io.Writer) (err error) {
  94. buf := make([]byte, 8)
  95. // Write the sig type and creation time
  96. buf[0] = byte(sig.SigType)
  97. binary.BigEndian.PutUint32(buf[1:5], uint32(sig.CreationTime.Unix()))
  98. if _, err = w.Write(buf[:5]); err != nil {
  99. return
  100. }
  101. // Write the issuer long key ID
  102. binary.BigEndian.PutUint64(buf[:8], sig.IssuerKeyId)
  103. if _, err = w.Write(buf[:8]); err != nil {
  104. return
  105. }
  106. // Write public key algorithm, hash ID, and hash value
  107. buf[0] = byte(sig.PubKeyAlgo)
  108. hashId, ok := s2k.HashToHashId(sig.Hash)
  109. if !ok {
  110. return errors.UnsupportedError(fmt.Sprintf("hash function %v", sig.Hash))
  111. }
  112. buf[1] = hashId
  113. copy(buf[2:4], sig.HashTag[:])
  114. if _, err = w.Write(buf[:4]); err != nil {
  115. return
  116. }
  117. if sig.RSASignature.bytes == nil && sig.DSASigR.bytes == nil {
  118. return errors.InvalidArgumentError("Signature: need to call Sign, SignUserId or SignKey before Serialize")
  119. }
  120. switch sig.PubKeyAlgo {
  121. case PubKeyAlgoRSA, PubKeyAlgoRSASignOnly:
  122. err = writeMPIs(w, sig.RSASignature)
  123. case PubKeyAlgoDSA:
  124. err = writeMPIs(w, sig.DSASigR, sig.DSASigS)
  125. default:
  126. panic("impossible")
  127. }
  128. return
  129. }