...

Source file src/github.com/ProtonMail/go-crypto/openpgp/clearsign/clearsign_test.go

Documentation: github.com/ProtonMail/go-crypto/openpgp/clearsign

     1  // Copyright 2012 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  
     5  package clearsign
     6  
     7  import (
     8  	"bytes"
     9  	"fmt"
    10  	"github.com/ProtonMail/go-crypto/openpgp"
    11  	"github.com/ProtonMail/go-crypto/openpgp/packet"
    12  	"io"
    13  	"testing"
    14  )
    15  
    16  func testParse(t *testing.T, input []byte, expected, expectedPlaintext string) {
    17  	b, rest := Decode(input)
    18  	if b == nil {
    19  		t.Fatal("failed to decode clearsign message")
    20  	}
    21  	if !bytes.Equal(rest, []byte("trailing")) {
    22  		t.Errorf("unexpected remaining bytes returned: %s", string(rest))
    23  	}
    24  	if b.ArmoredSignature.Type != "PGP SIGNATURE" {
    25  		t.Errorf("bad armor type, got:%s, want:PGP SIGNATURE", b.ArmoredSignature.Type)
    26  	}
    27  	if !bytes.Equal(b.Bytes, []byte(expected)) {
    28  		t.Errorf("bad body, got:%x want:%x", b.Bytes, expected)
    29  	}
    30  
    31  	if !bytes.Equal(b.Plaintext, []byte(expectedPlaintext)) {
    32  		t.Errorf("bad plaintext, got:%x want:%x", b.Plaintext, expectedPlaintext)
    33  	}
    34  
    35  	keyring, err := openpgp.ReadArmoredKeyRing(bytes.NewBufferString(signingKey))
    36  	if err != nil {
    37  		t.Errorf("failed to parse public key: %s", err)
    38  	}
    39  
    40  	config := &packet.Config{}
    41  	if _, err := openpgp.CheckDetachedSignature(keyring, bytes.NewBuffer(b.Bytes), b.ArmoredSignature.Body, config); err != nil {
    42  		t.Errorf("failed to check signature: %s", err)
    43  	}
    44  
    45  	b, _ = Decode(input)
    46  	if _, err := b.VerifySignature(keyring, config); err != nil {
    47  		t.Errorf("failed to check signature: %s", err)
    48  	}
    49  }
    50  
    51  func TestParse(t *testing.T) {
    52  	testParse(t, clearsignInput, "Hello world\r\nline 2", "Hello world\nline 2\n")
    53  	testParse(t, clearsignInput2, "\r\n\r\n(This message has a couple of blank lines at the start and end.)\r\n\r\n", "\n\n(This message has a couple of blank lines at the start and end.)\n\n\n")
    54  }
    55  
    56  func TestParseWithNoNewlineAtEnd(t *testing.T) {
    57  	input := clearsignInput
    58  	input = input[:len(input)-len("trailing")-1]
    59  	b, rest := Decode(input)
    60  	if b == nil {
    61  		t.Fatal("failed to decode clearsign message")
    62  	}
    63  	if len(rest) > 0 {
    64  		t.Errorf("unexpected remaining bytes returned: %s", string(rest))
    65  	}
    66  }
    67  
    68  var signingTests = []struct {
    69  	in, signed, plaintext string
    70  }{
    71  	{"", "", ""},
    72  	{"a", "a", "a\n"},
    73  	{"a\n", "a", "a\n"},
    74  	{"-a\n", "-a", "-a\n"},
    75  	{"--a\nb", "--a\r\nb", "--a\nb\n"},
    76  	// leading whitespace
    77  	{" a\n", " a", " a\n"},
    78  	{"  a\n", "  a", "  a\n"},
    79  	// trailing whitespace (should be stripped)
    80  	{"a \n", "a", "a\n"},
    81  	{"a ", "a", "a\n"},
    82  	// whitespace-only lines (should be stripped)
    83  	{"  \n", "", "\n"},
    84  	{"  ", "", "\n"},
    85  	{"a\n  \n  \nb\n", "a\r\n\r\n\r\nb", "a\n\n\nb\n"},
    86  }
    87  
    88  func TestSigning(t *testing.T) {
    89  	keyring, err := openpgp.ReadArmoredKeyRing(bytes.NewBufferString(signingKey))
    90  	if err != nil {
    91  		t.Errorf("failed to parse public key: %s", err)
    92  	}
    93  
    94  	for i, test := range signingTests {
    95  		var buf bytes.Buffer
    96  
    97  		plaintext, err := Encode(&buf, keyring[0].PrivateKey, nil)
    98  		if err != nil {
    99  			t.Errorf("#%d: error from Encode: %s", i, err)
   100  			continue
   101  		}
   102  		if _, err := plaintext.Write([]byte(test.in)); err != nil {
   103  			t.Errorf("#%d: error from Write: %s", i, err)
   104  			continue
   105  		}
   106  		if err := plaintext.Close(); err != nil {
   107  			t.Fatalf("#%d: error from Close: %s", i, err)
   108  			continue
   109  		}
   110  
   111  		b, _ := Decode(buf.Bytes())
   112  		if b == nil {
   113  			t.Errorf("#%d: failed to decode clearsign message", i)
   114  			continue
   115  		}
   116  		if !bytes.Equal(b.Bytes, []byte(test.signed)) {
   117  			t.Errorf("#%d: bad result, got:%x, want:%x", i, b.Bytes, test.signed)
   118  			continue
   119  		}
   120  		if !bytes.Equal(b.Plaintext, []byte(test.plaintext)) {
   121  			t.Errorf("#%d: bad result, got:%x, want:%x", i, b.Plaintext, test.plaintext)
   122  			continue
   123  		}
   124  
   125  		config := &packet.Config{}
   126  		if _, err := openpgp.CheckDetachedSignature(keyring, bytes.NewBuffer(b.Bytes), b.ArmoredSignature.Body, config); err != nil {
   127  			t.Errorf("#%d: failed to check signature: %s", i, err)
   128  		}
   129  	}
   130  }
   131  
   132  // We use this to make test keys, so that they aren't all the same.
   133  type quickRand byte
   134  
   135  func (qr *quickRand) Read(p []byte) (int, error) {
   136  	for i := range p {
   137  		p[i] = byte(*qr)
   138  	}
   139  	*qr++
   140  	return len(p), nil
   141  }
   142  
   143  func TestMultiSign(t *testing.T) {
   144  	if testing.Short() {
   145  		t.Skip("skipping long test in -short mode")
   146  	}
   147  
   148  	zero := quickRand(0)
   149  	config := packet.Config{Rand: &zero}
   150  
   151  	for nKeys := 0; nKeys < 4; nKeys++ {
   152  	nextTest:
   153  		for nExtra := 0; nExtra < 4; nExtra++ {
   154  			var signKeys []*packet.PrivateKey
   155  			var verifyKeys openpgp.EntityList
   156  
   157  			desc := fmt.Sprintf("%d keys; %d of which will be used to verify", nKeys+nExtra, nKeys)
   158  			for i := 0; i < nKeys+nExtra; i++ {
   159  				e, err := openpgp.NewEntity("name", "comment", "email", &config)
   160  				if err != nil {
   161  					t.Errorf("cannot create key: %v", err)
   162  					continue nextTest
   163  				}
   164  				if i < nKeys {
   165  					verifyKeys = append(verifyKeys, e)
   166  				}
   167  				signKeys = append(signKeys, e.PrivateKey)
   168  			}
   169  
   170  			input := []byte("this is random text\r\n4 17")
   171  			var output bytes.Buffer
   172  			w, err := EncodeMulti(&output, signKeys, nil)
   173  			if err != nil {
   174  				t.Errorf("EncodeMulti (%s) failed: %v", desc, err)
   175  			}
   176  			if _, err := w.Write(input); err != nil {
   177  				t.Errorf("Write(%q) to signer (%s) failed: %v", string(input), desc, err)
   178  			}
   179  			if err := w.Close(); err != nil {
   180  				t.Errorf("Close() of signer (%s) failed: %v", desc, err)
   181  			}
   182  
   183  			block, _ := Decode(output.Bytes())
   184  			if string(block.Bytes) != string(input) {
   185  				t.Errorf("Inline data didn't match original; got %q want %q", string(block.Bytes), string(input))
   186  			}
   187  			config := &packet.Config{}
   188  			_, err = openpgp.CheckDetachedSignature(verifyKeys, bytes.NewReader(block.Bytes), block.ArmoredSignature.Body, config)
   189  			if nKeys == 0 {
   190  				if err == nil {
   191  					t.Errorf("verifying inline (%s) succeeded; want failure", desc)
   192  				}
   193  			} else {
   194  				if err != nil {
   195  					t.Errorf("verifying inline (%s) failed (%v); want success", desc, err)
   196  				}
   197  			}
   198  		}
   199  	}
   200  }
   201  
   202  func TestDecodeMissingCRC(t *testing.T) {
   203  	block, rest := Decode(clearsignInput3)
   204  	if block == nil {
   205  		t.Fatal("failed to decode PGP signature missing a CRC")
   206  	}
   207  	if len(rest) > 0 {
   208  		t.Fatalf("Decode should not have any remaining data left: %s", rest)
   209  	}
   210  	if _, err := packet.Read(block.ArmoredSignature.Body); err != nil {
   211  		t.Error(err)
   212  	}
   213  	if _, err := packet.Read(block.ArmoredSignature.Body); err != io.EOF {
   214  		t.Error(err)
   215  	}
   216  }
   217  
   218  const signatureBlock = `
   219  -----BEGIN PGP SIGNATURE-----
   220  Version: OpenPrivacy 0.99
   221  
   222  yDgBO22WxBHv7O8X7O/jygAEzol56iUKiXmV+XmpCtmpqQUKiQrFqclFqUDBovzS
   223  vBSFjNSiVHsuAA==
   224  =njUN
   225  -----END PGP SIGNATURE-----
   226  `
   227  
   228  var invalidInputs = []string{
   229  	`
   230  -----BEGIN PGP SIGNED MESSAGE-----
   231  Hash: SHA256
   232  
   233  (This message was truncated.)
   234  `,
   235  	`
   236  -----BEGIN PGP SIGNED MESSAGE-----garbage
   237  Hash: SHA256
   238  
   239  _o/
   240  ` + signatureBlock,
   241  	`
   242  garbage-----BEGIN PGP SIGNED MESSAGE-----
   243  Hash: SHA256
   244  
   245  _o/
   246  ` + signatureBlock,
   247  	`
   248  -----BEGIN PGP SIGNED MESSAGE-----
   249  Hash: SHA` + "\x0b\x0b" + `256
   250  
   251  _o/
   252  ` + signatureBlock,
   253  	`
   254  -----BEGIN PGP SIGNED MESSAGE-----
   255  NotHash: SHA256
   256  
   257  _o/
   258  ` + signatureBlock,
   259  }
   260  
   261  func TestParseInvalid(t *testing.T) {
   262  	for i, input := range invalidInputs {
   263  		if b, rest := Decode([]byte(input)); b != nil {
   264  			t.Errorf("#%d: decoded a bad clearsigned message without any error", i)
   265  		} else if string(rest) != input {
   266  			t.Errorf("#%d: did not return all data with a bad message", i)
   267  		}
   268  	}
   269  }
   270  
   271  var clearsignInput = []byte(`
   272  ;lasjlkfdsa
   273  
   274  -----BEGIN PGP SIGNED MESSAGE-----
   275  Hash: SHA1
   276  
   277  Hello world
   278  line 2
   279  -----BEGIN PGP SIGNATURE-----
   280  Version: GnuPG v1.4.10 (GNU/Linux)
   281  
   282  iJwEAQECAAYFAk8kMuEACgkQO9o98PRieSpMsAQAhmY/vwmNpflrPgmfWsYhk5O8
   283  pjnBUzZwqTDoDeINjZEoPDSpQAHGhjFjgaDx/Gj4fAl0dM4D0wuUEBb6QOrwflog
   284  2A2k9kfSOMOtk0IH/H5VuFN1Mie9L/erYXjTQIptv9t9J7NoRBMU0QOOaFU0JaO9
   285  MyTpno24AjIAGb+mH1U=
   286  =hIJ6
   287  -----END PGP SIGNATURE-----
   288  trailing`)
   289  
   290  var clearsignInput2 = []byte(`
   291  asdlfkjasdlkfjsadf
   292  
   293  -----BEGIN PGP SIGNED MESSAGE-----
   294  Hash: SHA256
   295  
   296  
   297  
   298  (This message has a couple of blank lines at the start and end.)
   299  
   300  
   301  -----BEGIN PGP SIGNATURE-----
   302  Version: GnuPG v1.4.11 (GNU/Linux)
   303  
   304  iJwEAQEIAAYFAlPpSREACgkQO9o98PRieSpZTAP+M8QUoCt/7Rf3YbXPcdzIL32v
   305  pt1I+cMNeopzfLy0u4ioEFi8s5VkwpL1AFmirvgViCwlf82inoRxzZRiW05JQ5LI
   306  ESEzeCoy2LIdRCQ2hcrG8pIUPzUO4TqO5D/dMbdHwNH4h5nNmGJUAEG6FpURlPm+
   307  qZg6BaTvOxepqOxnhVU=
   308  =e+C6
   309  -----END PGP SIGNATURE-----
   310  
   311  trailing`)
   312  
   313  var clearsignInput3 = []byte(`-----BEGIN PGP SIGNED MESSAGE-----
   314  Hash: SHA256
   315  
   316  Origin: vscode stable
   317  Label: vscode stable
   318  Suite: stable
   319  Codename: stable
   320  Date: Mon, 13 Jan 2020 08:41:45 UTC
   321  Architectures: amd64
   322  Components: main
   323  Description: Generated by aptly
   324  MD5Sum:
   325   66437152b3082616d8053e52c4bafafb  5821166 Contents-amd64
   326   8024662ed51109946a517754bbafdd33   286298 Contents-amd64.gz
   327   66437152b3082616d8053e52c4bafafb  5821166 main/Contents-amd64
   328   8024662ed51109946a517754bbafdd33   286298 main/Contents-amd64.gz
   329   3062a08b3eca94a65d6d17ba1dafcf3e  1088265 main/binary-amd64/Packages
   330   b8ee22200fba8fa3be56c1ff946cdd24   159344 main/binary-amd64/Packages.bz2
   331   f89c47c81ebd25caf287c8e6dda16c1a   169456 main/binary-amd64/Packages.gz
   332   4c9ca25b556f111a5536c78df885ad82       95 main/binary-amd64/Release
   333  SHA1:
   334   2b62d0e322746b7d094878278f49993ca4314bf7  5821166 Contents-amd64
   335   aafe35cce12e03d8b1939e403ddf5c0958c6e9bd   286298 Contents-amd64.gz
   336   2b62d0e322746b7d094878278f49993ca4314bf7  5821166 main/Contents-amd64
   337   aafe35cce12e03d8b1939e403ddf5c0958c6e9bd   286298 main/Contents-amd64.gz
   338   30316ac5d4ce3b472a96a797eeb0a2a82d43ed3e  1088265 main/binary-amd64/Packages
   339   6507e0b4da8194fd1048fcbb74c6e7433edaf3d6   159344 main/binary-amd64/Packages.bz2
   340   ec9d39c39567c74001221e4900fb5d11ec11b833   169456 main/binary-amd64/Packages.gz
   341   58bf20987a91d35936f18efce75ea233d43dbf8b       95 main/binary-amd64/Release
   342  SHA256:
   343   deff9ebfc44bf482e10a6ea10f608c6bb0fdc8373bf86b88cad9d99879ae3c39  5821166 Contents-amd64
   344   f163bc65c7666ef58e0be3336e8c846ae2b7b388fbb2d7db0bcdc3fd1abae462   286298 Contents-amd64.gz
   345   deff9ebfc44bf482e10a6ea10f608c6bb0fdc8373bf86b88cad9d99879ae3c39  5821166 main/Contents-amd64
   346   f163bc65c7666ef58e0be3336e8c846ae2b7b388fbb2d7db0bcdc3fd1abae462   286298 main/Contents-amd64.gz
   347   0fba50799ef72d0c2b354d0bcbbc8c623f6dae5a7fd7c218a54ea44dd8a49d5e  1088265 main/binary-amd64/Packages
   348   69382470a88b67acde80fe45ab223016adebc445713ff0aa3272902581d21f13   159344 main/binary-amd64/Packages.bz2
   349   1724b8ace5bd8882943e9463d8525006f33ca704480da0186fd47937451dc216   169456 main/binary-amd64/Packages.gz
   350   0f509a0cb07e0ab433176fa47a21dccccc6b519f25f640cc58561104c11de6c2       95 main/binary-amd64/Release
   351  SHA512:
   352   f69f09c6180ceb6625a84b5f7123ad27972983146979dcfd9c38b2990459b52b4975716f85374511486bb5ad5852ebb1ef8265176df7134fc15b17ada3ba596c  5821166 Contents-amd64
   353   46031bf89166188989368957d20cdcaac6eec72bab3f9839c9704bb08cbee3174ca6da11e290b0eab0e6b5754c1e7feb06d18ec9c5a0c955029cef53235e0a3a   286298 Contents-amd64.gz
   354   f69f09c6180ceb6625a84b5f7123ad27972983146979dcfd9c38b2990459b52b4975716f85374511486bb5ad5852ebb1ef8265176df7134fc15b17ada3ba596c  5821166 main/Contents-amd64
   355   46031bf89166188989368957d20cdcaac6eec72bab3f9839c9704bb08cbee3174ca6da11e290b0eab0e6b5754c1e7feb06d18ec9c5a0c955029cef53235e0a3a   286298 main/Contents-amd64.gz
   356   3f78baf5adbaf0100996555b154807c794622fd0b5879b568ae0b6560e988fbfabed8d97db5a703d1a58514b9690fc6b60f9ad2eeece473d86ab257becd0ae41  1088265 main/binary-amd64/Packages
   357   18f26df90beff29192662ca40525367c3c04f4581d59d2e9ab1cd0700a145b6a292a1609ca33ebe1c211f13718a8eee751f41fd8189cf93d52aa3e0851542dfc   159344 main/binary-amd64/Packages.bz2
   358   6a6d917229e0cf06c493e174a87d76e815717676f2c70bcbd3bc689a80bd3c5489ea97db83b8f74cba8e70f374f9d9974f22b1ed2687a4ba1dacd22fdef7e14d   169456 main/binary-amd64/Packages.gz
   359   e1a4378ad266c13c2edf8a0e590fa4d11973ab99ce79f15af005cb838f1600f66f3dc6da8976fa8b474da9073c118039c27623ab3360c6df115071497fe4f50c       95 main/binary-amd64/Release
   360  
   361  -----BEGIN PGP SIGNATURE-----
   362  Version: BSN Pgp v1.0.0.0
   363  
   364  iQEcBAEBCAAGBQJeHC1bAAoJEOs+lK2+EinPAg8H/1rrhcgfm1HYL+Vmr9Ns6ton
   365  LWQ8r13ADN66UTRa3XsO9V+q1fYowTqpXq6EZt2Gmlby/cpDf7mFPM5IteOXWLl7
   366  QcWxPKHcdPIUi+h5F7BkFW65imP9GyX+V5Pxx5X544op7hYKaI0gAQ1oYtWDb3HE
   367  4D27fju6icbj8w6E8TePcrDn82UvWAcaI5WSLboyhXCt2DxS3PNGFlyaP58zKJ8F
   368  9cbBzksuMgMaTPAAMrU0zrFGfGeQz0Yo6nV/gRGiQaL9pSeIJWSKLNCMG/nIGmv2
   369  xHVNFqTEetREY6UcQmuhwOn4HezyigH6XCBVp/Uez1izXiNdwBOet34SSvnkuJ4=
   370  -----END PGP SIGNATURE-----`)
   371  
   372  var signingKey = `-----BEGIN PGP PRIVATE KEY BLOCK-----
   373  Version: GnuPG v1.4.10 (GNU/Linux)
   374  
   375  lQHYBE2rFNoBBADFwqWQIW/DSqcB4yCQqnAFTJ27qS5AnB46ccAdw3u4Greeu3Bp
   376  idpoHdjULy7zSKlwR1EA873dO/k/e11Ml3dlAFUinWeejWaK2ugFP6JjiieSsrKn
   377  vWNicdCS4HTWn0X4sjl0ZiAygw6GNhqEQ3cpLeL0g8E9hnYzJKQ0LWJa0QARAQAB
   378  AAP/TB81EIo2VYNmTq0pK1ZXwUpxCrvAAIG3hwKjEzHcbQznsjNvPUihZ+NZQ6+X
   379  0HCfPAdPkGDCLCb6NavcSW+iNnLTrdDnSI6+3BbIONqWWdRDYJhqZCkqmG6zqSfL
   380  IdkJgCw94taUg5BWP/AAeQrhzjChvpMQTVKQL5mnuZbUCeMCAN5qrYMP2S9iKdnk
   381  VANIFj7656ARKt/nf4CBzxcpHTyB8+d2CtPDKCmlJP6vL8t58Jmih+kHJMvC0dzn
   382  gr5f5+sCAOOe5gt9e0am7AvQWhdbHVfJU0TQJx+m2OiCJAqGTB1nvtBLHdJnfdC9
   383  TnXXQ6ZXibqLyBies/xeY2sCKL5qtTMCAKnX9+9d/5yQxRyrQUHt1NYhaXZnJbHx
   384  q4ytu0eWz+5i68IYUSK69jJ1NWPM0T6SkqpB3KCAIv68VFm9PxqG1KmhSrQIVGVz
   385  dCBLZXmIuAQTAQIAIgUCTasU2gIbAwYLCQgHAwIGFQgCCQoLBBYCAwECHgECF4AA
   386  CgkQO9o98PRieSoLhgQAkLEZex02Qt7vGhZzMwuN0R22w3VwyYyjBx+fM3JFETy1
   387  ut4xcLJoJfIaF5ZS38UplgakHG0FQ+b49i8dMij0aZmDqGxrew1m4kBfjXw9B/v+
   388  eIqpODryb6cOSwyQFH0lQkXC040pjq9YqDsO5w0WYNXYKDnzRV0p4H1pweo2VDid
   389  AdgETasU2gEEAN46UPeWRqKHvA99arOxee38fBt2CI08iiWyI8T3J6ivtFGixSqV
   390  bRcPxYO/qLpVe5l84Nb3X71GfVXlc9hyv7CD6tcowL59hg1E/DC5ydI8K8iEpUmK
   391  /UnHdIY5h8/kqgGxkY/T/hgp5fRQgW1ZoZxLajVlMRZ8W4tFtT0DeA+JABEBAAEA
   392  A/0bE1jaaZKj6ndqcw86jd+QtD1SF+Cf21CWRNeLKnUds4FRRvclzTyUMuWPkUeX
   393  TaNNsUOFqBsf6QQ2oHUBBK4VCHffHCW4ZEX2cd6umz7mpHW6XzN4DECEzOVksXtc
   394  lUC1j4UB91DC/RNQqwX1IV2QLSwssVotPMPqhOi0ZLNY7wIA3n7DWKInxYZZ4K+6
   395  rQ+POsz6brEoRHwr8x6XlHenq1Oki855pSa1yXIARoTrSJkBtn5oI+f8AzrnN0BN
   396  oyeQAwIA/7E++3HDi5aweWrViiul9cd3rcsS0dEnksPhvS0ozCJiHsq/6GFmy7J8
   397  QSHZPteedBnZyNp5jR+H7cIfVN3KgwH/Skq4PsuPhDq5TKK6i8Pc1WW8MA6DXTdU
   398  nLkX7RGmMwjC0DBf7KWAlPjFaONAX3a8ndnz//fy1q7u2l9AZwrj1qa1iJ8EGAEC
   399  AAkFAk2rFNoCGwwACgkQO9o98PRieSo2/QP/WTzr4ioINVsvN1akKuekmEMI3LAp
   400  BfHwatufxxP1U+3Si/6YIk7kuPB9Hs+pRqCXzbvPRrI8NHZBmc8qIGthishdCYad
   401  AHcVnXjtxrULkQFGbGvhKURLvS9WnzD/m1K2zzwxzkPTzT9/Yf06O6Mal5AdugPL
   402  VrM0m72/jnpKo04=
   403  =zNCn
   404  -----END PGP PRIVATE KEY BLOCK-----
   405  `
   406  

View as plain text