signatures.go 3.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113
  1. // Copyright 2015 Google Inc. All Rights Reserved.
  2. //
  3. // Licensed under the Apache License, Version 2.0 (the "License");
  4. // you may not use this file except in compliance with the License.
  5. // You may obtain a copy of the License at
  6. //
  7. // http://www.apache.org/licenses/LICENSE-2.0
  8. //
  9. // Unless required by applicable law or agreed to in writing, software
  10. // distributed under the License is distributed on an "AS IS" BASIS,
  11. // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  12. // See the License for the specific language governing permissions and
  13. // limitations under the License.
  14. package ct
  15. import (
  16. "crypto"
  17. "crypto/ecdsa"
  18. "crypto/elliptic"
  19. "crypto/rsa"
  20. "crypto/sha256"
  21. "encoding/base64"
  22. "encoding/pem"
  23. "fmt"
  24. "log"
  25. "github.com/google/certificate-transparency-go/tls"
  26. "github.com/google/certificate-transparency-go/x509"
  27. )
  28. // AllowVerificationWithNonCompliantKeys may be set to true in order to allow
  29. // SignatureVerifier to use keys which are technically non-compliant with
  30. // RFC6962.
  31. var AllowVerificationWithNonCompliantKeys = false
  32. // PublicKeyFromPEM parses a PEM formatted block and returns the public key contained within and any remaining unread bytes, or an error.
  33. func PublicKeyFromPEM(b []byte) (crypto.PublicKey, SHA256Hash, []byte, error) {
  34. p, rest := pem.Decode(b)
  35. if p == nil {
  36. return nil, [sha256.Size]byte{}, rest, fmt.Errorf("no PEM block found in %s", string(b))
  37. }
  38. k, err := x509.ParsePKIXPublicKey(p.Bytes)
  39. return k, sha256.Sum256(p.Bytes), rest, err
  40. }
  41. // PublicKeyFromB64 parses a base64-encoded public key.
  42. func PublicKeyFromB64(b64PubKey string) (crypto.PublicKey, error) {
  43. der, err := base64.StdEncoding.DecodeString(b64PubKey)
  44. if err != nil {
  45. return nil, fmt.Errorf("error decoding public key: %s", err)
  46. }
  47. return x509.ParsePKIXPublicKey(der)
  48. }
  49. // SignatureVerifier can verify signatures on SCTs and STHs
  50. type SignatureVerifier struct {
  51. pubKey crypto.PublicKey
  52. }
  53. // NewSignatureVerifier creates a new SignatureVerifier using the passed in PublicKey.
  54. func NewSignatureVerifier(pk crypto.PublicKey) (*SignatureVerifier, error) {
  55. switch pkType := pk.(type) {
  56. case *rsa.PublicKey:
  57. if pkType.N.BitLen() < 2048 {
  58. e := fmt.Errorf("public key is RSA with < 2048 bits (size:%d)", pkType.N.BitLen())
  59. if !AllowVerificationWithNonCompliantKeys {
  60. return nil, e
  61. }
  62. log.Printf("WARNING: %v", e)
  63. }
  64. case *ecdsa.PublicKey:
  65. params := *(pkType.Params())
  66. if params != *elliptic.P256().Params() {
  67. e := fmt.Errorf("public is ECDSA, but not on the P256 curve")
  68. if !AllowVerificationWithNonCompliantKeys {
  69. return nil, e
  70. }
  71. log.Printf("WARNING: %v", e)
  72. }
  73. default:
  74. return nil, fmt.Errorf("Unsupported public key type %v", pkType)
  75. }
  76. return &SignatureVerifier{
  77. pubKey: pk,
  78. }, nil
  79. }
  80. // VerifySignature verifies the given signature sig matches the data.
  81. func (s SignatureVerifier) VerifySignature(data []byte, sig tls.DigitallySigned) error {
  82. return tls.VerifySignature(s.pubKey, data, sig)
  83. }
  84. // VerifySCTSignature verifies that the SCT's signature is valid for the given LogEntry.
  85. func (s SignatureVerifier) VerifySCTSignature(sct SignedCertificateTimestamp, entry LogEntry) error {
  86. sctData, err := SerializeSCTSignatureInput(sct, entry)
  87. if err != nil {
  88. return err
  89. }
  90. return s.VerifySignature(sctData, tls.DigitallySigned(sct.Signature))
  91. }
  92. // VerifySTHSignature verifies that the STH's signature is valid.
  93. func (s SignatureVerifier) VerifySTHSignature(sth SignedTreeHead) error {
  94. sthData, err := SerializeSTHSignatureInput(sth)
  95. if err != nil {
  96. return err
  97. }
  98. return s.VerifySignature(sthData, tls.DigitallySigned(sth.TreeHeadSignature))
  99. }