[
  {
    "path": ".github/FUNDING.yml",
    "content": "# These are supported funding model platforms\n\ngithub: # Replace with up to 4 GitHub Sponsors-enabled usernames e.g., [user1, user2]\npatreon: # Replace with a single Patreon username\nopen_collective: # Replace with a single Open Collective username\nko_fi: # Replace with a single Ko-fi username\ntidelift: # Replace with a single Tidelift platform-name/package-name e.g., npm/babel\ncommunity_bridge: # Replace with a single Community Bridge project-name e.g., cloud-foundry\nliberapay: # Replace with a single Liberapay username\nissuehunt: # Replace with a single IssueHunt username\notechie: # Replace with a single Otechie username\ncustom: https://weibo.com/5978668016/KDzUy5mOq\n"
  },
  {
    "path": ".gitignore",
    "content": "# Binaries for programs and plugins\n*.exe\n*.exe~\n*.dll\n*.so\n*.dylib\n\n# Test binary, build with `go test -c`\n*.test\n\n# Output of the go coverage tool, specifically when used with LiteIDE\n*.out\n"
  },
  {
    "path": "LICENSE",
    "content": "                                 Apache License\n                           Version 2.0, January 2004\n                        http://www.apache.org/licenses/\n\n   TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION\n\n   1. Definitions.\n\n      \"License\" shall mean the terms and conditions for use, reproduction,\n      and distribution as defined by Sections 1 through 9 of this document.\n\n      \"Licensor\" shall mean the copyright owner or entity authorized by\n      the copyright owner that is granting the License.\n\n      \"Legal Entity\" shall mean the union of the acting entity and all\n      other entities that control, are controlled by, or are under common\n      control with that entity. For the purposes of this definition,\n      \"control\" means (i) the power, direct or indirect, to cause the\n      direction or management of such entity, whether by contract or\n      otherwise, or (ii) ownership of fifty percent (50%) or more of the\n      outstanding shares, or (iii) beneficial ownership of such entity.\n\n      \"You\" (or \"Your\") shall mean an individual or Legal Entity\n      exercising permissions granted by this License.\n\n      \"Source\" form shall mean the preferred form for making modifications,\n      including but not limited to software source code, documentation\n      source, and configuration files.\n\n      \"Object\" form shall mean any form resulting from mechanical\n      transformation or translation of a Source form, including but\n      not limited to compiled object code, generated documentation,\n      and conversions to other media types.\n\n      \"Work\" shall mean the work of authorship, whether in Source or\n      Object form, made available under the License, as indicated by a\n      copyright notice that is included in or attached to the work\n      (an example is provided in the Appendix below).\n\n      \"Derivative Works\" shall mean any work, whether in Source or Object\n      form, that is based on (or derived from) the Work and for which the\n      editorial revisions, annotations, elaborations, or other modifications\n      represent, as a whole, an original work of authorship. For the purposes\n      of this License, Derivative Works shall not include works that remain\n      separable from, or merely link (or bind by name) to the interfaces of,\n      the Work and Derivative Works thereof.\n\n      \"Contribution\" shall mean any work of authorship, including\n      the original version of the Work and any modifications or additions\n      to that Work or Derivative Works thereof, that is intentionally\n      submitted to Licensor for inclusion in the Work by the copyright owner\n      or by an individual or Legal Entity authorized to submit on behalf of\n      the copyright owner. For the purposes of this definition, \"submitted\"\n      means any form of electronic, verbal, or written communication sent\n      to the Licensor or its representatives, including but not limited to\n      communication on electronic mailing lists, source code control systems,\n      and issue tracking systems that are managed by, or on behalf of, the\n      Licensor for the purpose of discussing and improving the Work, but\n      excluding communication that is conspicuously marked or otherwise\n      designated in writing by the copyright owner as \"Not a Contribution.\"\n\n      \"Contributor\" shall mean Licensor and any individual or Legal Entity\n      on behalf of whom a Contribution has been received by Licensor and\n      subsequently incorporated within the Work.\n\n   2. Grant of Copyright License. Subject to the terms and conditions of\n      this License, each Contributor hereby grants to You a perpetual,\n      worldwide, non-exclusive, no-charge, royalty-free, irrevocable\n      copyright license to reproduce, prepare Derivative Works of,\n      publicly display, publicly perform, sublicense, and distribute the\n      Work and such Derivative Works in Source or Object form.\n\n   3. Grant of Patent License. Subject to the terms and conditions of\n      this License, each Contributor hereby grants to You a perpetual,\n      worldwide, non-exclusive, no-charge, royalty-free, irrevocable\n      (except as stated in this section) patent license to make, have made,\n      use, offer to sell, sell, import, and otherwise transfer the Work,\n      where such license applies only to those patent claims licensable\n      by such Contributor that are necessarily infringed by their\n      Contribution(s) alone or by combination of their Contribution(s)\n      with the Work to which such Contribution(s) was submitted. If You\n      institute patent litigation against any entity (including a\n      cross-claim or counterclaim in a lawsuit) alleging that the Work\n      or a Contribution incorporated within the Work constitutes direct\n      or contributory patent infringement, then any patent licenses\n      granted to You under this License for that Work shall terminate\n      as of the date such litigation is filed.\n\n   4. Redistribution. You may reproduce and distribute copies of the\n      Work or Derivative Works thereof in any medium, with or without\n      modifications, and in Source or Object form, provided that You\n      meet the following conditions:\n\n      (a) You must give any other recipients of the Work or\n          Derivative Works a copy of this License; and\n\n      (b) You must cause any modified files to carry prominent notices\n          stating that You changed the files; and\n\n      (c) You must retain, in the Source form of any Derivative Works\n          that You distribute, all copyright, patent, trademark, and\n          attribution notices from the Source form of the Work,\n          excluding those notices that do not pertain to any part of\n          the Derivative Works; and\n\n      (d) If the Work includes a \"NOTICE\" text file as part of its\n          distribution, then any Derivative Works that You distribute must\n          include a readable copy of the attribution notices contained\n          within such NOTICE file, excluding those notices that do not\n          pertain to any part of the Derivative Works, in at least one\n          of the following places: within a NOTICE text file distributed\n          as part of the Derivative Works; within the Source form or\n          documentation, if provided along with the Derivative Works; or,\n          within a display generated by the Derivative Works, if and\n          wherever such third-party notices normally appear. The contents\n          of the NOTICE file are for informational purposes only and\n          do not modify the License. You may add Your own attribution\n          notices within Derivative Works that You distribute, alongside\n          or as an addendum to the NOTICE text from the Work, provided\n          that such additional attribution notices cannot be construed\n          as modifying the License.\n\n      You may add Your own copyright statement to Your modifications and\n      may provide additional or different license terms and conditions\n      for use, reproduction, or distribution of Your modifications, or\n      for any such Derivative Works as a whole, provided Your use,\n      reproduction, and distribution of the Work otherwise complies with\n      the conditions stated in this License.\n\n   5. Submission of Contributions. Unless You explicitly state otherwise,\n      any Contribution intentionally submitted for inclusion in the Work\n      by You to the Licensor shall be under the terms and conditions of\n      this License, without any additional terms or conditions.\n      Notwithstanding the above, nothing herein shall supersede or modify\n      the terms of any separate license agreement you may have executed\n      with Licensor regarding such Contributions.\n\n   6. Trademarks. This License does not grant permission to use the trade\n      names, trademarks, service marks, or product names of the Licensor,\n      except as required for reasonable and customary use in describing the\n      origin of the Work and reproducing the content of the NOTICE file.\n\n   7. Disclaimer of Warranty. Unless required by applicable law or\n      agreed to in writing, Licensor provides the Work (and each\n      Contributor provides its Contributions) on an \"AS IS\" BASIS,\n      WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or\n      implied, including, without limitation, any warranties or conditions\n      of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A\n      PARTICULAR PURPOSE. You are solely responsible for determining the\n      appropriateness of using or redistributing the Work and assume any\n      risks associated with Your exercise of permissions under this License.\n\n   8. Limitation of Liability. In no event and under no legal theory,\n      whether in tort (including negligence), contract, or otherwise,\n      unless required by applicable law (such as deliberate and grossly\n      negligent acts) or agreed to in writing, shall any Contributor be\n      liable to You for damages, including any direct, indirect, special,\n      incidental, or consequential damages of any character arising as a\n      result of this License or out of the use or inability to use the\n      Work (including but not limited to damages for loss of goodwill,\n      work stoppage, computer failure or malfunction, or any and all\n      other commercial damages or losses), even if such Contributor\n      has been advised of the possibility of such damages.\n\n   9. Accepting Warranty or Additional Liability. While redistributing\n      the Work or Derivative Works thereof, You may choose to offer,\n      and charge a fee for, acceptance of support, warranty, indemnity,\n      or other liability obligations and/or rights consistent with this\n      License. However, in accepting such obligations, You may act only\n      on Your own behalf and on Your sole responsibility, not on behalf\n      of any other Contributor, and only if You agree to indemnify,\n      defend, and hold each Contributor harmless for any liability\n      incurred by, or claims asserted against, such Contributor by reason\n      of your accepting any such warranty or additional liability.\n\n   END OF TERMS AND CONDITIONS\n\n   APPENDIX: How to apply the Apache License to your work.\n\n      To apply the Apache License to your work, attach the following\n      boilerplate notice, with the fields enclosed by brackets \"[]\"\n      replaced with your own identifying information. (Don't include\n      the brackets!)  The text should be enclosed in the appropriate\n      comment syntax for the file format. We also recommend that a\n      file or class name and description of purpose be included on the\n      same \"printed page\" as the copyright notice for easier\n      identification within third-party archives.\n\n   Copyright [yyyy] [name of copyright owner]\n\n   Licensed under the Apache License, Version 2.0 (the \"License\");\n   you may not use this file except in compliance with the License.\n   You may obtain a copy of the License at\n\n       http://www.apache.org/licenses/LICENSE-2.0\n\n   Unless required by applicable law or agreed to in writing, software\n   distributed under the License is distributed on an \"AS IS\" BASIS,\n   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n   See the License for the specific language governing permissions and\n   limitations under the License.\n"
  },
  {
    "path": "README.md",
    "content": "# gm\n"
  },
  {
    "path": "cryptobyte/README",
    "content": "这个包下的代码全部copy自SDK中的golang_org/x/crypto/cryptobyte包，这个包不对应用开放，所以只好全部copy过来\n"
  },
  {
    "path": "cryptobyte/asn1/asn1.go",
    "content": "// Copyright 2017 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\n// Package asn1 contains supporting types for parsing and building ASN.1\n// messages with the cryptobyte package.\npackage asn1\n\n// Tag represents an ASN.1 identifier octet, consisting of a tag number\n// (indicating a type) and class (such as context-specific or constructed).\n//\n// Methods in the cryptobyte package only support the low-tag-number form, i.e.\n// a single identifier octet with bits 7-8 encoding the class and bits 1-6\n// encoding the tag number.\ntype Tag uint8\n\nconst (\n\tclassConstructed     = 0x20\n\tclassContextSpecific = 0x80\n)\n\n// Constructed returns t with the constructed class bit set.\nfunc (t Tag) Constructed() Tag { return t | classConstructed }\n\n// ContextSpecific returns t with the context-specific class bit set.\nfunc (t Tag) ContextSpecific() Tag { return t | classContextSpecific }\n\n// The following is a list of standard tag and class combinations.\nconst (\n\tBOOLEAN           = Tag(1)\n\tINTEGER           = Tag(2)\n\tBIT_STRING        = Tag(3)\n\tOCTET_STRING      = Tag(4)\n\tNULL              = Tag(5)\n\tOBJECT_IDENTIFIER = Tag(6)\n\tENUM              = Tag(10)\n\tUTF8String        = Tag(12)\n\tSEQUENCE          = Tag(16 | classConstructed)\n\tSET               = Tag(17 | classConstructed)\n\tPrintableString   = Tag(19)\n\tT61String         = Tag(20)\n\tIA5String         = Tag(22)\n\tUTCTime           = Tag(23)\n\tGeneralizedTime   = Tag(24)\n\tGeneralString     = Tag(27)\n)\n"
  },
  {
    "path": "cryptobyte/asn1.go",
    "content": "// Copyright 2017 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\npackage cryptobyte\n\nimport (\n\tencoding_asn1 \"encoding/asn1\"\n\t\"fmt\"\n\t\"math/big\"\n\t\"reflect\"\n\t\"time\"\n\n\t\"github.com/ZZMarquis/gm/cryptobyte/asn1\"\n)\n\n// This file contains ASN.1-related methods for String and Builder.\n\n// Builder\n\n// AddASN1Int64 appends a DER-encoded ASN.1 INTEGER.\nfunc (b *Builder) AddASN1Int64(v int64) {\n\tb.addASN1Signed(asn1.INTEGER, v)\n}\n\n// AddASN1Enum appends a DER-encoded ASN.1 ENUMERATION.\nfunc (b *Builder) AddASN1Enum(v int64) {\n\tb.addASN1Signed(asn1.ENUM, v)\n}\n\nfunc (b *Builder) addASN1Signed(tag asn1.Tag, v int64) {\n\tb.AddASN1(tag, func(c *Builder) {\n\t\tlength := 1\n\t\tfor i := v; i >= 0x80 || i < -0x80; i >>= 8 {\n\t\t\tlength++\n\t\t}\n\n\t\tfor ; length > 0; length-- {\n\t\t\ti := v >> uint((length-1)*8) & 0xff\n\t\t\tc.AddUint8(uint8(i))\n\t\t}\n\t})\n}\n\n// AddASN1Uint64 appends a DER-encoded ASN.1 INTEGER.\nfunc (b *Builder) AddASN1Uint64(v uint64) {\n\tb.AddASN1(asn1.INTEGER, func(c *Builder) {\n\t\tlength := 1\n\t\tfor i := v; i >= 0x80; i >>= 8 {\n\t\t\tlength++\n\t\t}\n\n\t\tfor ; length > 0; length-- {\n\t\t\ti := v >> uint((length-1)*8) & 0xff\n\t\t\tc.AddUint8(uint8(i))\n\t\t}\n\t})\n}\n\n// AddASN1BigInt appends a DER-encoded ASN.1 INTEGER.\nfunc (b *Builder) AddASN1BigInt(n *big.Int) {\n\tif b.err != nil {\n\t\treturn\n\t}\n\n\tb.AddASN1(asn1.INTEGER, func(c *Builder) {\n\t\tif n.Sign() < 0 {\n\t\t\t// A negative number has to be converted to two's-complement form. So we\n\t\t\t// invert and subtract 1. If the most-significant-bit isn't set then\n\t\t\t// we'll need to pad the beginning with 0xff in order to keep the number\n\t\t\t// negative.\n\t\t\tnMinus1 := new(big.Int).Neg(n)\n\t\t\tnMinus1.Sub(nMinus1, bigOne)\n\t\t\tbytes := nMinus1.Bytes()\n\t\t\tfor i := range bytes {\n\t\t\t\tbytes[i] ^= 0xff\n\t\t\t}\n\t\t\tif bytes[0]&0x80 == 0 {\n\t\t\t\tc.add(0xff)\n\t\t\t}\n\t\t\tc.add(bytes...)\n\t\t} else if n.Sign() == 0 {\n\t\t\tc.add(0)\n\t\t} else {\n\t\t\tbytes := n.Bytes()\n\t\t\tif bytes[0]&0x80 != 0 {\n\t\t\t\tc.add(0)\n\t\t\t}\n\t\t\tc.add(bytes...)\n\t\t}\n\t})\n}\n\n// AddASN1OctetString appends a DER-encoded ASN.1 OCTET STRING.\nfunc (b *Builder) AddASN1OctetString(bytes []byte) {\n\tb.AddASN1(asn1.OCTET_STRING, func(c *Builder) {\n\t\tc.AddBytes(bytes)\n\t})\n}\n\nconst generalizedTimeFormatStr = \"20060102150405Z0700\"\n\n// AddASN1GeneralizedTime appends a DER-encoded ASN.1 GENERALIZEDTIME.\nfunc (b *Builder) AddASN1GeneralizedTime(t time.Time) {\n\tif t.Year() < 0 || t.Year() > 9999 {\n\t\tb.err = fmt.Errorf(\"cryptobyte: cannot represent %v as a GeneralizedTime\", t)\n\t\treturn\n\t}\n\tb.AddASN1(asn1.GeneralizedTime, func(c *Builder) {\n\t\tc.AddBytes([]byte(t.Format(generalizedTimeFormatStr)))\n\t})\n}\n\n// AddASN1BitString appends a DER-encoded ASN.1 BIT STRING. This does not\n// support BIT STRINGs that are not a whole number of bytes.\nfunc (b *Builder) AddASN1BitString(data []byte) {\n\tb.AddASN1(asn1.BIT_STRING, func(b *Builder) {\n\t\tb.AddUint8(0)\n\t\tb.AddBytes(data)\n\t})\n}\n\nfunc (b *Builder) addBase128Int(n int64) {\n\tvar length int\n\tif n == 0 {\n\t\tlength = 1\n\t} else {\n\t\tfor i := n; i > 0; i >>= 7 {\n\t\t\tlength++\n\t\t}\n\t}\n\n\tfor i := length - 1; i >= 0; i-- {\n\t\to := byte(n >> uint(i*7))\n\t\to &= 0x7f\n\t\tif i != 0 {\n\t\t\to |= 0x80\n\t\t}\n\n\t\tb.add(o)\n\t}\n}\n\nfunc isValidOID(oid encoding_asn1.ObjectIdentifier) bool {\n\tif len(oid) < 2 {\n\t\treturn false\n\t}\n\n\tif oid[0] > 2 || (oid[0] <= 1 && oid[1] >= 40) {\n\t\treturn false\n\t}\n\n\tfor _, v := range oid {\n\t\tif v < 0 {\n\t\t\treturn false\n\t\t}\n\t}\n\n\treturn true\n}\n\nfunc (b *Builder) AddASN1ObjectIdentifier(oid encoding_asn1.ObjectIdentifier) {\n\tb.AddASN1(asn1.OBJECT_IDENTIFIER, func(b *Builder) {\n\t\tif !isValidOID(oid) {\n\t\t\tb.err = fmt.Errorf(\"cryptobyte: invalid OID: %v\", oid)\n\t\t\treturn\n\t\t}\n\n\t\tb.addBase128Int(int64(oid[0])*40 + int64(oid[1]))\n\t\tfor _, v := range oid[2:] {\n\t\t\tb.addBase128Int(int64(v))\n\t\t}\n\t})\n}\n\nfunc (b *Builder) AddASN1Boolean(v bool) {\n\tb.AddASN1(asn1.BOOLEAN, func(b *Builder) {\n\t\tif v {\n\t\t\tb.AddUint8(0xff)\n\t\t} else {\n\t\t\tb.AddUint8(0)\n\t\t}\n\t})\n}\n\nfunc (b *Builder) AddASN1NULL() {\n\tb.add(uint8(asn1.NULL), 0)\n}\n\n// MarshalASN1 calls encoding_asn1.Marshal on its input and appends the result if\n// successful or records an error if one occurred.\nfunc (b *Builder) MarshalASN1(v interface{}) {\n\t// NOTE(martinkr): This is somewhat of a hack to allow propagation of\n\t// encoding_asn1.Marshal errors into Builder.err. N.B. if you call MarshalASN1 with a\n\t// value embedded into a struct, its tag information is lost.\n\tif b.err != nil {\n\t\treturn\n\t}\n\tbytes, err := encoding_asn1.Marshal(v)\n\tif err != nil {\n\t\tb.err = err\n\t\treturn\n\t}\n\tb.AddBytes(bytes)\n}\n\n// AddASN1 appends an ASN.1 object. The object is prefixed with the given tag.\n// Tags greater than 30 are not supported and result in an error (i.e.\n// low-tag-number form only). The child builder passed to the\n// BuilderContinuation can be used to build the content of the ASN.1 object.\nfunc (b *Builder) AddASN1(tag asn1.Tag, f BuilderContinuation) {\n\tif b.err != nil {\n\t\treturn\n\t}\n\t// Identifiers with the low five bits set indicate high-tag-number format\n\t// (two or more octets), which we don't support.\n\tif tag&0x1f == 0x1f {\n\t\tb.err = fmt.Errorf(\"cryptobyte: high-tag number identifier octects not supported: 0x%x\", tag)\n\t\treturn\n\t}\n\tb.AddUint8(uint8(tag))\n\tb.addLengthPrefixed(1, true, f)\n}\n\n// String\n\nfunc (s *String) ReadASN1Boolean(out *bool) bool {\n\tvar bytes String\n\tif !s.ReadASN1(&bytes, asn1.INTEGER) || len(bytes) != 1 {\n\t\treturn false\n\t}\n\n\tswitch bytes[0] {\n\tcase 0:\n\t\t*out = false\n\tcase 0xff:\n\t\t*out = true\n\tdefault:\n\t\treturn false\n\t}\n\n\treturn true\n}\n\nvar bigIntType = reflect.TypeOf((*big.Int)(nil)).Elem()\n\n// ReadASN1Integer decodes an ASN.1 INTEGER into out and advances. If out does\n// not point to an integer or to a big.Int, it panics. It returns true on\n// success and false on error.\nfunc (s *String) ReadASN1Integer(out interface{}) bool {\n\tif reflect.TypeOf(out).Kind() != reflect.Ptr {\n\t\tpanic(\"out is not a pointer\")\n\t}\n\tswitch reflect.ValueOf(out).Elem().Kind() {\n\tcase reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:\n\t\tvar i int64\n\t\tif !s.readASN1Int64(&i) || reflect.ValueOf(out).Elem().OverflowInt(i) {\n\t\t\treturn false\n\t\t}\n\t\treflect.ValueOf(out).Elem().SetInt(i)\n\t\treturn true\n\tcase reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64:\n\t\tvar u uint64\n\t\tif !s.readASN1Uint64(&u) || reflect.ValueOf(out).Elem().OverflowUint(u) {\n\t\t\treturn false\n\t\t}\n\t\treflect.ValueOf(out).Elem().SetUint(u)\n\t\treturn true\n\tcase reflect.Struct:\n\t\tif reflect.TypeOf(out).Elem() == bigIntType {\n\t\t\treturn s.readASN1BigInt(out.(*big.Int))\n\t\t}\n\t}\n\tpanic(\"out does not point to an integer type\")\n}\n\nfunc checkASN1Integer(bytes []byte) bool {\n\tif len(bytes) == 0 {\n\t\t// An INTEGER is encoded with at least one octet.\n\t\treturn false\n\t}\n\tif len(bytes) == 1 {\n\t\treturn true\n\t}\n\tif bytes[0] == 0 && bytes[1]&0x80 == 0 || bytes[0] == 0xff && bytes[1]&0x80 == 0x80 {\n\t\t// Value is not minimally encoded.\n\t\treturn false\n\t}\n\treturn true\n}\n\nvar bigOne = big.NewInt(1)\n\nfunc (s *String) readASN1BigInt(out *big.Int) bool {\n\tvar bytes String\n\tif !s.ReadASN1(&bytes, asn1.INTEGER) || !checkASN1Integer(bytes) {\n\t\treturn false\n\t}\n\tif bytes[0]&0x80 == 0x80 {\n\t\t// Negative number.\n\t\tneg := make([]byte, len(bytes))\n\t\tfor i, b := range bytes {\n\t\t\tneg[i] = ^b\n\t\t}\n\t\tout.SetBytes(neg)\n\t\tout.Add(out, bigOne)\n\t\tout.Neg(out)\n\t} else {\n\t\tout.SetBytes(bytes)\n\t}\n\treturn true\n}\n\nfunc (s *String) readASN1Int64(out *int64) bool {\n\tvar bytes String\n\tif !s.ReadASN1(&bytes, asn1.INTEGER) || !checkASN1Integer(bytes) || !asn1Signed(out, bytes) {\n\t\treturn false\n\t}\n\treturn true\n}\n\nfunc asn1Signed(out *int64, n []byte) bool {\n\tlength := len(n)\n\tif length > 8 {\n\t\treturn false\n\t}\n\tfor i := 0; i < length; i++ {\n\t\t*out <<= 8\n\t\t*out |= int64(n[i])\n\t}\n\t// Shift up and down in order to sign extend the result.\n\t*out <<= 64 - uint8(length)*8\n\t*out >>= 64 - uint8(length)*8\n\treturn true\n}\n\nfunc (s *String) readASN1Uint64(out *uint64) bool {\n\tvar bytes String\n\tif !s.ReadASN1(&bytes, asn1.INTEGER) || !checkASN1Integer(bytes) || !asn1Unsigned(out, bytes) {\n\t\treturn false\n\t}\n\treturn true\n}\n\nfunc asn1Unsigned(out *uint64, n []byte) bool {\n\tlength := len(n)\n\tif length > 9 || length == 9 && n[0] != 0 {\n\t\t// Too large for uint64.\n\t\treturn false\n\t}\n\tif n[0]&0x80 != 0 {\n\t\t// Negative number.\n\t\treturn false\n\t}\n\tfor i := 0; i < length; i++ {\n\t\t*out <<= 8\n\t\t*out |= uint64(n[i])\n\t}\n\treturn true\n}\n\n// ReadASN1Enum decodes an ASN.1 ENUMERATION into out and advances. It returns\n// true on success and false on error.\nfunc (s *String) ReadASN1Enum(out *int) bool {\n\tvar bytes String\n\tvar i int64\n\tif !s.ReadASN1(&bytes, asn1.ENUM) || !checkASN1Integer(bytes) || !asn1Signed(&i, bytes) {\n\t\treturn false\n\t}\n\tif int64(int(i)) != i {\n\t\treturn false\n\t}\n\t*out = int(i)\n\treturn true\n}\n\nfunc (s *String) readBase128Int(out *int) bool {\n\tret := 0\n\tfor i := 0; len(*s) > 0; i++ {\n\t\tif i == 4 {\n\t\t\treturn false\n\t\t}\n\t\tret <<= 7\n\t\tb := s.read(1)[0]\n\t\tret |= int(b & 0x7f)\n\t\tif b&0x80 == 0 {\n\t\t\t*out = ret\n\t\t\treturn true\n\t\t}\n\t}\n\treturn false // truncated\n}\n\n// ReadASN1ObjectIdentifier decodes an ASN.1 OBJECT IDENTIFIER into out and\n// advances. It returns true on success and false on error.\nfunc (s *String) ReadASN1ObjectIdentifier(out *encoding_asn1.ObjectIdentifier) bool {\n\tvar bytes String\n\tif !s.ReadASN1(&bytes, asn1.OBJECT_IDENTIFIER) || len(bytes) == 0 {\n\t\treturn false\n\t}\n\n\t// In the worst case, we get two elements from the first byte (which is\n\t// encoded differently) and then every varint is a single byte long.\n\tcomponents := make([]int, len(bytes)+1)\n\n\t// The first varint is 40*value1 + value2:\n\t// According to this packing, value1 can take the values 0, 1 and 2 only.\n\t// When value1 = 0 or value1 = 1, then value2 is <= 39. When value1 = 2,\n\t// then there are no restrictions on value2.\n\tvar v int\n\tif !bytes.readBase128Int(&v) {\n\t\treturn false\n\t}\n\tif v < 80 {\n\t\tcomponents[0] = v / 40\n\t\tcomponents[1] = v % 40\n\t} else {\n\t\tcomponents[0] = 2\n\t\tcomponents[1] = v - 80\n\t}\n\n\ti := 2\n\tfor ; len(bytes) > 0; i++ {\n\t\tif !bytes.readBase128Int(&v) {\n\t\t\treturn false\n\t\t}\n\t\tcomponents[i] = v\n\t}\n\t*out = components[:i]\n\treturn true\n}\n\n// ReadASN1GeneralizedTime decodes an ASN.1 GENERALIZEDTIME into out and\n// advances. It returns true on success and false on error.\nfunc (s *String) ReadASN1GeneralizedTime(out *time.Time) bool {\n\tvar bytes String\n\tif !s.ReadASN1(&bytes, asn1.GeneralizedTime) {\n\t\treturn false\n\t}\n\tt := string(bytes)\n\tres, err := time.Parse(generalizedTimeFormatStr, t)\n\tif err != nil {\n\t\treturn false\n\t}\n\tif serialized := res.Format(generalizedTimeFormatStr); serialized != t {\n\t\treturn false\n\t}\n\t*out = res\n\treturn true\n}\n\n// ReadASN1BitString decodes an ASN.1 BIT STRING into out and advances. It\n// returns true on success and false on error.\nfunc (s *String) ReadASN1BitString(out *encoding_asn1.BitString) bool {\n\tvar bytes String\n\tif !s.ReadASN1(&bytes, asn1.BIT_STRING) || len(bytes) == 0 {\n\t\treturn false\n\t}\n\n\tpaddingBits := uint8(bytes[0])\n\tbytes = bytes[1:]\n\tif paddingBits > 7 ||\n\t\tlen(bytes) == 0 && paddingBits != 0 ||\n\t\tlen(bytes) > 0 && bytes[len(bytes)-1]&(1<<paddingBits-1) != 0 {\n\t\treturn false\n\t}\n\n\tout.BitLength = len(bytes)*8 - int(paddingBits)\n\tout.Bytes = bytes\n\treturn true\n}\n\n// ReadASN1BitString decodes an ASN.1 BIT STRING into out and advances. It is\n// an error if the BIT STRING is not a whole number of bytes. This function\n// returns true on success and false on error.\nfunc (s *String) ReadASN1BitStringAsBytes(out *[]byte) bool {\n\tvar bytes String\n\tif !s.ReadASN1(&bytes, asn1.BIT_STRING) || len(bytes) == 0 {\n\t\treturn false\n\t}\n\n\tpaddingBits := uint8(bytes[0])\n\tif paddingBits != 0 {\n\t\treturn false\n\t}\n\t*out = bytes[1:]\n\treturn true\n}\n\n// ReadASN1Bytes reads the contents of a DER-encoded ASN.1 element (not including\n// tag and length bytes) into out, and advances. The element must match the\n// given tag. It returns true on success and false on error.\nfunc (s *String) ReadASN1Bytes(out *[]byte, tag asn1.Tag) bool {\n\treturn s.ReadASN1((*String)(out), tag)\n}\n\n// ReadASN1 reads the contents of a DER-encoded ASN.1 element (not including\n// tag and length bytes) into out, and advances. The element must match the\n// given tag. It returns true on success and false on error.\n//\n// Tags greater than 30 are not supported (i.e. low-tag-number format only).\nfunc (s *String) ReadASN1(out *String, tag asn1.Tag) bool {\n\tvar t asn1.Tag\n\tif !s.ReadAnyASN1(out, &t) || t != tag {\n\t\treturn false\n\t}\n\treturn true\n}\n\n// ReadASN1Element reads the contents of a DER-encoded ASN.1 element (including\n// tag and length bytes) into out, and advances. The element must match the\n// given tag. It returns true on success and false on error.\n//\n// Tags greater than 30 are not supported (i.e. low-tag-number format only).\nfunc (s *String) ReadASN1Element(out *String, tag asn1.Tag) bool {\n\tvar t asn1.Tag\n\tif !s.ReadAnyASN1Element(out, &t) || t != tag {\n\t\treturn false\n\t}\n\treturn true\n}\n\n// ReadAnyASN1 reads the contents of a DER-encoded ASN.1 element (not including\n// tag and length bytes) into out, sets outTag to its tag, and advances. It\n// returns true on success and false on error.\n//\n// Tags greater than 30 are not supported (i.e. low-tag-number format only).\nfunc (s *String) ReadAnyASN1(out *String, outTag *asn1.Tag) bool {\n\treturn s.readASN1(out, outTag, true /* skip header */)\n}\n\n// ReadAnyASN1Element reads the contents of a DER-encoded ASN.1 element\n// (including tag and length bytes) into out, sets outTag to is tag, and\n// advances. It returns true on success and false on error.\n//\n// Tags greater than 30 are not supported (i.e. low-tag-number format only).\nfunc (s *String) ReadAnyASN1Element(out *String, outTag *asn1.Tag) bool {\n\treturn s.readASN1(out, outTag, false /* include header */)\n}\n\n// PeekASN1Tag returns true if the next ASN.1 value on the string starts with\n// the given tag.\nfunc (s String) PeekASN1Tag(tag asn1.Tag) bool {\n\tif len(s) == 0 {\n\t\treturn false\n\t}\n\treturn asn1.Tag(s[0]) == tag\n}\n\n// SkipASN1 reads and discards an ASN.1 element with the given tag.\nfunc (s *String) SkipASN1(tag asn1.Tag) bool {\n\tvar unused String\n\treturn s.ReadASN1(&unused, tag)\n}\n\n// ReadOptionalASN1 attempts to read the contents of a DER-encoded ASN.1\n// element (not including tag and length bytes) tagged with the given tag into\n// out. It stores whether an element with the tag was found in outPresent,\n// unless outPresent is nil. It returns true on success and false on error.\nfunc (s *String) ReadOptionalASN1(out *String, outPresent *bool, tag asn1.Tag) bool {\n\tpresent := s.PeekASN1Tag(tag)\n\tif outPresent != nil {\n\t\t*outPresent = present\n\t}\n\tif present && !s.ReadASN1(out, tag) {\n\t\treturn false\n\t}\n\treturn true\n}\n\n// SkipOptionalASN1 advances s over an ASN.1 element with the given tag, or\n// else leaves s unchanged.\nfunc (s *String) SkipOptionalASN1(tag asn1.Tag) bool {\n\tif !s.PeekASN1Tag(tag) {\n\t\treturn true\n\t}\n\tvar unused String\n\treturn s.ReadASN1(&unused, tag)\n}\n\n// ReadOptionalASN1Integer attempts to read an optional ASN.1 INTEGER\n// explicitly tagged with tag into out and advances. If no element with a\n// matching tag is present, it writes defaultValue into out instead. If out\n// does not point to an integer or to a big.Int, it panics. It returns true on\n// success and false on error.\nfunc (s *String) ReadOptionalASN1Integer(out interface{}, tag asn1.Tag, defaultValue interface{}) bool {\n\tif reflect.TypeOf(out).Kind() != reflect.Ptr {\n\t\tpanic(\"out is not a pointer\")\n\t}\n\tvar present bool\n\tvar i String\n\tif !s.ReadOptionalASN1(&i, &present, tag) {\n\t\treturn false\n\t}\n\tif !present {\n\t\tswitch reflect.ValueOf(out).Elem().Kind() {\n\t\tcase reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64,\n\t\t\treflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64:\n\t\t\treflect.ValueOf(out).Elem().Set(reflect.ValueOf(defaultValue))\n\t\tcase reflect.Struct:\n\t\t\tif reflect.TypeOf(out).Elem() != bigIntType {\n\t\t\t\tpanic(\"invalid integer type\")\n\t\t\t}\n\t\t\tif reflect.TypeOf(defaultValue).Kind() != reflect.Ptr ||\n\t\t\t\treflect.TypeOf(defaultValue).Elem() != bigIntType {\n\t\t\t\tpanic(\"out points to big.Int, but defaultValue does not\")\n\t\t\t}\n\t\t\tout.(*big.Int).Set(defaultValue.(*big.Int))\n\t\tdefault:\n\t\t\tpanic(\"invalid integer type\")\n\t\t}\n\t\treturn true\n\t}\n\tif !i.ReadASN1Integer(out) || !i.Empty() {\n\t\treturn false\n\t}\n\treturn true\n}\n\n// ReadOptionalASN1OctetString attempts to read an optional ASN.1 OCTET STRING\n// explicitly tagged with tag into out and advances. If no element with a\n// matching tag is present, it writes defaultValue into out instead. It returns\n// true on success and false on error.\nfunc (s *String) ReadOptionalASN1OctetString(out *[]byte, outPresent *bool, tag asn1.Tag) bool {\n\tvar present bool\n\tvar child String\n\tif !s.ReadOptionalASN1(&child, &present, tag) {\n\t\treturn false\n\t}\n\tif outPresent != nil {\n\t\t*outPresent = present\n\t}\n\tif present {\n\t\tvar oct String\n\t\tif !child.ReadASN1(&oct, asn1.OCTET_STRING) || !child.Empty() {\n\t\t\treturn false\n\t\t}\n\t\t*out = oct\n\t} else {\n\t\t*out = nil\n\t}\n\treturn true\n}\n\n// ReadOptionalASN1Boolean sets *out to the value of the next ASN.1 BOOLEAN or,\n// if the next bytes are not an ASN.1 BOOLEAN, to the value of defaultValue.\nfunc (s *String) ReadOptionalASN1Boolean(out *bool, defaultValue bool) bool {\n\tvar present bool\n\tvar child String\n\tif !s.ReadOptionalASN1(&child, &present, asn1.BOOLEAN) {\n\t\treturn false\n\t}\n\n\tif !present {\n\t\t*out = defaultValue\n\t\treturn true\n\t}\n\n\treturn s.ReadASN1Boolean(out)\n}\n\nfunc (s *String) readASN1(out *String, outTag *asn1.Tag, skipHeader bool) bool {\n\tif len(*s) < 2 {\n\t\treturn false\n\t}\n\ttag, lenByte := (*s)[0], (*s)[1]\n\n\tif tag&0x1f == 0x1f {\n\t\t// ITU-T X.690 section 8.1.2\n\t\t//\n\t\t// An identifier octet with a tag part of 0x1f indicates a high-tag-number\n\t\t// form identifier with two or more octets. We only support tags less than\n\t\t// 31 (i.e. low-tag-number form, single octet identifier).\n\t\treturn false\n\t}\n\n\tif outTag != nil {\n\t\t*outTag = asn1.Tag(tag)\n\t}\n\n\t// ITU-T X.690 section 8.1.3\n\t//\n\t// Bit 8 of the first length byte indicates whether the length is short- or\n\t// long-form.\n\tvar length, headerLen uint32 // length includes headerLen\n\tif lenByte&0x80 == 0 {\n\t\t// Short-form length (section 8.1.3.4), encoded in bits 1-7.\n\t\tlength = uint32(lenByte) + 2\n\t\theaderLen = 2\n\t} else {\n\t\t// Long-form length (section 8.1.3.5). Bits 1-7 encode the number of octets\n\t\t// used to encode the length.\n\t\tlenLen := lenByte & 0x7f\n\t\tvar len32 uint32\n\n\t\tif lenLen == 0 || lenLen > 4 || len(*s) < int(2+lenLen) {\n\t\t\treturn false\n\t\t}\n\n\t\tlenBytes := String((*s)[2 : 2+lenLen])\n\t\tif !lenBytes.readUnsigned(&len32, int(lenLen)) {\n\t\t\treturn false\n\t\t}\n\n\t\t// ITU-T X.690 section 10.1 (DER length forms) requires encoding the length\n\t\t// with the minimum number of octets.\n\t\tif len32 < 128 {\n\t\t\t// Length should have used short-form encoding.\n\t\t\treturn false\n\t\t}\n\t\tif len32>>((lenLen-1)*8) == 0 {\n\t\t\t// Leading octet is 0. Length should have been at least one byte shorter.\n\t\t\treturn false\n\t\t}\n\n\t\theaderLen = 2 + uint32(lenLen)\n\t\tif headerLen+len32 < len32 {\n\t\t\t// Overflow.\n\t\t\treturn false\n\t\t}\n\t\tlength = headerLen + len32\n\t}\n\n\tif uint32(int(length)) != length || !s.ReadBytes((*[]byte)(out), int(length)) {\n\t\treturn false\n\t}\n\tif skipHeader && !out.Skip(int(headerLen)) {\n\t\tpanic(\"cryptobyte: internal error\")\n\t}\n\n\treturn true\n}\n"
  },
  {
    "path": "cryptobyte/builder.go",
    "content": "// Copyright 2017 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\npackage cryptobyte\n\nimport (\n\t\"errors\"\n\t\"fmt\"\n)\n\n// A Builder builds byte strings from fixed-length and length-prefixed values.\n// Builders either allocate space as needed, or are ‘fixed’, which means that\n// they write into a given buffer and produce an error if it's exhausted.\n//\n// The zero value is a usable Builder that allocates space as needed.\n//\n// Simple values are marshaled and appended to a Builder using methods on the\n// Builder. Length-prefixed values are marshaled by providing a\n// BuilderContinuation, which is a function that writes the inner contents of\n// the value to a given Builder. See the documentation for BuilderContinuation\n// for details.\ntype Builder struct {\n\terr            error\n\tresult         []byte\n\tfixedSize      bool\n\tchild          *Builder\n\toffset         int\n\tpendingLenLen  int\n\tpendingIsASN1  bool\n\tinContinuation *bool\n}\n\n// NewBuilder creates a Builder that appends its output to the given buffer.\n// Like append(), the slice will be reallocated if its capacity is exceeded.\n// Use Bytes to get the final buffer.\nfunc NewBuilder(buffer []byte) *Builder {\n\treturn &Builder{\n\t\tresult: buffer,\n\t}\n}\n\n// NewFixedBuilder creates a Builder that appends its output into the given\n// buffer. This builder does not reallocate the output buffer. Writes that\n// would exceed the buffer's capacity are treated as an error.\nfunc NewFixedBuilder(buffer []byte) *Builder {\n\treturn &Builder{\n\t\tresult:    buffer,\n\t\tfixedSize: true,\n\t}\n}\n\n// Bytes returns the bytes written by the builder or an error if one has\n// occurred during during building.\nfunc (b *Builder) Bytes() ([]byte, error) {\n\tif b.err != nil {\n\t\treturn nil, b.err\n\t}\n\treturn b.result[b.offset:], nil\n}\n\n// BytesOrPanic returns the bytes written by the builder or panics if an error\n// has occurred during building.\nfunc (b *Builder) BytesOrPanic() []byte {\n\tif b.err != nil {\n\t\tpanic(b.err)\n\t}\n\treturn b.result[b.offset:]\n}\n\n// AddUint8 appends an 8-bit value to the byte string.\nfunc (b *Builder) AddUint8(v uint8) {\n\tb.add(byte(v))\n}\n\n// AddUint16 appends a big-endian, 16-bit value to the byte string.\nfunc (b *Builder) AddUint16(v uint16) {\n\tb.add(byte(v>>8), byte(v))\n}\n\n// AddUint24 appends a big-endian, 24-bit value to the byte string. The highest\n// byte of the 32-bit input value is silently truncated.\nfunc (b *Builder) AddUint24(v uint32) {\n\tb.add(byte(v>>16), byte(v>>8), byte(v))\n}\n\n// AddUint32 appends a big-endian, 32-bit value to the byte string.\nfunc (b *Builder) AddUint32(v uint32) {\n\tb.add(byte(v>>24), byte(v>>16), byte(v>>8), byte(v))\n}\n\n// AddBytes appends a sequence of bytes to the byte string.\nfunc (b *Builder) AddBytes(v []byte) {\n\tb.add(v...)\n}\n\n// BuilderContinuation is continuation-passing interface for building\n// length-prefixed byte sequences. Builder methods for length-prefixed\n// sequences (AddUint8LengthPrefixed etc) will invoke the BuilderContinuation\n// supplied to them. The child builder passed to the continuation can be used\n// to build the content of the length-prefixed sequence. For example:\n//\n//   parent := cryptobyte.NewBuilder()\n//   parent.AddUint8LengthPrefixed(func (child *Builder) {\n//     child.AddUint8(42)\n//     child.AddUint8LengthPrefixed(func (grandchild *Builder) {\n//       grandchild.AddUint8(5)\n//     })\n//   })\n//\n// It is an error to write more bytes to the child than allowed by the reserved\n// length prefix. After the continuation returns, the child must be considered\n// invalid, i.e. users must not store any copies or references of the child\n// that outlive the continuation.\n//\n// If the continuation panics with a value of type BuildError then the inner\n// error will be returned as the error from Bytes. If the child panics\n// otherwise then Bytes will repanic with the same value.\ntype BuilderContinuation func(child *Builder)\n\n// BuildError wraps an error. If a BuilderContinuation panics with this value,\n// the panic will be recovered and the inner error will be returned from\n// Builder.Bytes.\ntype BuildError struct {\n\tErr error\n}\n\n// AddUint8LengthPrefixed adds a 8-bit length-prefixed byte sequence.\nfunc (b *Builder) AddUint8LengthPrefixed(f BuilderContinuation) {\n\tb.addLengthPrefixed(1, false, f)\n}\n\n// AddUint16LengthPrefixed adds a big-endian, 16-bit length-prefixed byte sequence.\nfunc (b *Builder) AddUint16LengthPrefixed(f BuilderContinuation) {\n\tb.addLengthPrefixed(2, false, f)\n}\n\n// AddUint24LengthPrefixed adds a big-endian, 24-bit length-prefixed byte sequence.\nfunc (b *Builder) AddUint24LengthPrefixed(f BuilderContinuation) {\n\tb.addLengthPrefixed(3, false, f)\n}\n\n// AddUint32LengthPrefixed adds a big-endian, 32-bit length-prefixed byte sequence.\nfunc (b *Builder) AddUint32LengthPrefixed(f BuilderContinuation) {\n\tb.addLengthPrefixed(4, false, f)\n}\n\nfunc (b *Builder) callContinuation(f BuilderContinuation, arg *Builder) {\n\tif !*b.inContinuation {\n\t\t*b.inContinuation = true\n\n\t\tdefer func() {\n\t\t\t*b.inContinuation = false\n\n\t\t\tr := recover()\n\t\t\tif r == nil {\n\t\t\t\treturn\n\t\t\t}\n\n\t\t\tif buildError, ok := r.(BuildError); ok {\n\t\t\t\tb.err = buildError.Err\n\t\t\t} else {\n\t\t\t\tpanic(r)\n\t\t\t}\n\t\t}()\n\t}\n\n\tf(arg)\n}\n\nfunc (b *Builder) addLengthPrefixed(lenLen int, isASN1 bool, f BuilderContinuation) {\n\t// Subsequent writes can be ignored if the builder has encountered an error.\n\tif b.err != nil {\n\t\treturn\n\t}\n\n\toffset := len(b.result)\n\tb.add(make([]byte, lenLen)...)\n\n\tif b.inContinuation == nil {\n\t\tb.inContinuation = new(bool)\n\t}\n\n\tb.child = &Builder{\n\t\tresult:         b.result,\n\t\tfixedSize:      b.fixedSize,\n\t\toffset:         offset,\n\t\tpendingLenLen:  lenLen,\n\t\tpendingIsASN1:  isASN1,\n\t\tinContinuation: b.inContinuation,\n\t}\n\n\tb.callContinuation(f, b.child)\n\tb.flushChild()\n\tif b.child != nil {\n\t\tpanic(\"cryptobyte: internal error\")\n\t}\n}\n\nfunc (b *Builder) flushChild() {\n\tif b.child == nil {\n\t\treturn\n\t}\n\tb.child.flushChild()\n\tchild := b.child\n\tb.child = nil\n\n\tif child.err != nil {\n\t\tb.err = child.err\n\t\treturn\n\t}\n\n\tlength := len(child.result) - child.pendingLenLen - child.offset\n\n\tif length < 0 {\n\t\tpanic(\"cryptobyte: internal error\") // result unexpectedly shrunk\n\t}\n\n\tif child.pendingIsASN1 {\n\t\t// For ASN.1, we reserved a single byte for the length. If that turned out\n\t\t// to be incorrect, we have to move the contents along in order to make\n\t\t// space.\n\t\tif child.pendingLenLen != 1 {\n\t\t\tpanic(\"cryptobyte: internal error\")\n\t\t}\n\t\tvar lenLen, lenByte uint8\n\t\tif int64(length) > 0xfffffffe {\n\t\t\tb.err = errors.New(\"pending ASN.1 child too long\")\n\t\t\treturn\n\t\t} else if length > 0xffffff {\n\t\t\tlenLen = 5\n\t\t\tlenByte = 0x80 | 4\n\t\t} else if length > 0xffff {\n\t\t\tlenLen = 4\n\t\t\tlenByte = 0x80 | 3\n\t\t} else if length > 0xff {\n\t\t\tlenLen = 3\n\t\t\tlenByte = 0x80 | 2\n\t\t} else if length > 0x7f {\n\t\t\tlenLen = 2\n\t\t\tlenByte = 0x80 | 1\n\t\t} else {\n\t\t\tlenLen = 1\n\t\t\tlenByte = uint8(length)\n\t\t\tlength = 0\n\t\t}\n\n\t\t// Insert the initial length byte, make space for successive length bytes,\n\t\t// and adjust the offset.\n\t\tchild.result[child.offset] = lenByte\n\t\textraBytes := int(lenLen - 1)\n\t\tif extraBytes != 0 {\n\t\t\tchild.add(make([]byte, extraBytes)...)\n\t\t\tchildStart := child.offset + child.pendingLenLen\n\t\t\tcopy(child.result[childStart+extraBytes:], child.result[childStart:])\n\t\t}\n\t\tchild.offset++\n\t\tchild.pendingLenLen = extraBytes\n\t}\n\n\tl := length\n\tfor i := child.pendingLenLen - 1; i >= 0; i-- {\n\t\tchild.result[child.offset+i] = uint8(l)\n\t\tl >>= 8\n\t}\n\tif l != 0 {\n\t\tb.err = fmt.Errorf(\"cryptobyte: pending child length %d exceeds %d-byte length prefix\", length, child.pendingLenLen)\n\t\treturn\n\t}\n\n\tif !b.fixedSize {\n\t\tb.result = child.result // In case child reallocated result.\n\t}\n}\n\nfunc (b *Builder) add(bytes ...byte) {\n\tif b.err != nil {\n\t\treturn\n\t}\n\tif b.child != nil {\n\t\tpanic(\"attempted write while child is pending\")\n\t}\n\tif len(b.result)+len(bytes) < len(bytes) {\n\t\tb.err = errors.New(\"cryptobyte: length overflow\")\n\t}\n\tif b.fixedSize && len(b.result)+len(bytes) > cap(b.result) {\n\t\tb.err = errors.New(\"cryptobyte: Builder is exceeding its fixed-size buffer\")\n\t\treturn\n\t}\n\tb.result = append(b.result, bytes...)\n}\n\n// A MarshalingValue marshals itself into a Builder.\ntype MarshalingValue interface {\n\t// Marshal is called by Builder.AddValue. It receives a pointer to a builder\n\t// to marshal itself into. It may return an error that occurred during\n\t// marshaling, such as unset or invalid values.\n\tMarshal(b *Builder) error\n}\n\n// AddValue calls Marshal on v, passing a pointer to the builder to append to.\n// If Marshal returns an error, it is set on the Builder so that subsequent\n// appends don't have an effect.\nfunc (b *Builder) AddValue(v MarshalingValue) {\n\terr := v.Marshal(b)\n\tif err != nil {\n\t\tb.err = err\n\t}\n}\n"
  },
  {
    "path": "cryptobyte/string.go",
    "content": "// Copyright 2017 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\n// Package cryptobyte contains types that help with parsing and constructing\n// length-prefixed, binary messages, including ASN.1 DER. (The asn1 subpackage\n// contains useful ASN.1 constants.)\n//\n// The String type is for parsing. It wraps a []byte slice and provides helper\n// functions for consuming structures, value by value.\n//\n// The Builder type is for constructing messages. It providers helper functions\n// for appending values and also for appending length-prefixed submessages –\n// without having to worry about calculating the length prefix ahead of time.\n//\n// See the documentation and examples for the Builder and String types to get\n// started.\npackage cryptobyte\n\n// String represents a string of bytes. It provides methods for parsing\n// fixed-length and length-prefixed values from it.\ntype String []byte\n\n// read advances a String by n bytes and returns them. If less than n bytes\n// remain, it returns nil.\nfunc (s *String) read(n int) []byte {\n\tif len(*s) < n {\n\t\treturn nil\n\t}\n\tv := (*s)[:n]\n\t*s = (*s)[n:]\n\treturn v\n}\n\n// Skip advances the String by n byte and reports whether it was successful.\nfunc (s *String) Skip(n int) bool {\n\treturn s.read(n) != nil\n}\n\n// ReadUint8 decodes an 8-bit value into out and advances over it. It\n// returns true on success and false on error.\nfunc (s *String) ReadUint8(out *uint8) bool {\n\tv := s.read(1)\n\tif v == nil {\n\t\treturn false\n\t}\n\t*out = uint8(v[0])\n\treturn true\n}\n\n// ReadUint16 decodes a big-endian, 16-bit value into out and advances over it.\n// It returns true on success and false on error.\nfunc (s *String) ReadUint16(out *uint16) bool {\n\tv := s.read(2)\n\tif v == nil {\n\t\treturn false\n\t}\n\t*out = uint16(v[0])<<8 | uint16(v[1])\n\treturn true\n}\n\n// ReadUint24 decodes a big-endian, 24-bit value into out and advances over it.\n// It returns true on success and false on error.\nfunc (s *String) ReadUint24(out *uint32) bool {\n\tv := s.read(3)\n\tif v == nil {\n\t\treturn false\n\t}\n\t*out = uint32(v[0])<<16 | uint32(v[1])<<8 | uint32(v[2])\n\treturn true\n}\n\n// ReadUint32 decodes a big-endian, 32-bit value into out and advances over it.\n// It returns true on success and false on error.\nfunc (s *String) ReadUint32(out *uint32) bool {\n\tv := s.read(4)\n\tif v == nil {\n\t\treturn false\n\t}\n\t*out = uint32(v[0])<<24 | uint32(v[1])<<16 | uint32(v[2])<<8 | uint32(v[3])\n\treturn true\n}\n\nfunc (s *String) readUnsigned(out *uint32, length int) bool {\n\tv := s.read(length)\n\tif v == nil {\n\t\treturn false\n\t}\n\tvar result uint32\n\tfor i := 0; i < length; i++ {\n\t\tresult <<= 8\n\t\tresult |= uint32(v[i])\n\t}\n\t*out = result\n\treturn true\n}\n\nfunc (s *String) readLengthPrefixed(lenLen int, outChild *String) bool {\n\tlenBytes := s.read(lenLen)\n\tif lenBytes == nil {\n\t\treturn false\n\t}\n\tvar length uint32\n\tfor _, b := range lenBytes {\n\t\tlength = length << 8\n\t\tlength = length | uint32(b)\n\t}\n\tif int(length) < 0 {\n\t\t// This currently cannot overflow because we read uint24 at most, but check\n\t\t// anyway in case that changes in the future.\n\t\treturn false\n\t}\n\tv := s.read(int(length))\n\tif v == nil {\n\t\treturn false\n\t}\n\t*outChild = v\n\treturn true\n}\n\n// ReadUint8LengthPrefixed reads the content of an 8-bit length-prefixed value\n// into out and advances over it. It returns true on success and false on\n// error.\nfunc (s *String) ReadUint8LengthPrefixed(out *String) bool {\n\treturn s.readLengthPrefixed(1, out)\n}\n\n// ReadUint16LengthPrefixed reads the content of a big-endian, 16-bit\n// length-prefixed value into out and advances over it. It returns true on\n// success and false on error.\nfunc (s *String) ReadUint16LengthPrefixed(out *String) bool {\n\treturn s.readLengthPrefixed(2, out)\n}\n\n// ReadUint24LengthPrefixed reads the content of a big-endian, 24-bit\n// length-prefixed value into out and advances over it. It returns true on\n// success and false on error.\nfunc (s *String) ReadUint24LengthPrefixed(out *String) bool {\n\treturn s.readLengthPrefixed(3, out)\n}\n\n// ReadBytes reads n bytes into out and advances over them. It returns true on\n// success and false and error.\nfunc (s *String) ReadBytes(out *[]byte, n int) bool {\n\tv := s.read(n)\n\tif v == nil {\n\t\treturn false\n\t}\n\t*out = v\n\treturn true\n}\n\n// CopyBytes copies len(out) bytes into out and advances over them. It returns\n// true on success and false on error.\nfunc (s *String) CopyBytes(out []byte) bool {\n\tn := len(out)\n\tv := s.read(n)\n\tif v == nil {\n\t\treturn false\n\t}\n\treturn copy(out, v) == n\n}\n\n// Empty reports whether the string does not contain any bytes.\nfunc (s String) Empty() bool {\n\treturn len(s) == 0\n}\n"
  },
  {
    "path": "go.mod",
    "content": "module github.com/ZZMarquis/gm\n\ngo 1.12\n"
  },
  {
    "path": "sm2/cert/gmx509.go",
    "content": "package cert\n\nimport (\n\t\"bytes\"\n\t\"crypto/elliptic\"\n\t\"crypto/x509\"\n\t\"crypto/x509/pkix\"\n\t\"encoding/asn1\"\n\t\"errors\"\n\t\"fmt\"\n\t\"math/big\"\n\t\"net\"\n\t\"net/url\"\n\t\"strconv\"\n\t\"strings\"\n\t\"time\"\n\t\"unicode/utf8\"\n\n\t\"github.com/ZZMarquis/gm/cryptobyte\"\n\tcryptobyte_asn1 \"github.com/ZZMarquis/gm/cryptobyte/asn1\"\n\t\"github.com/ZZMarquis/gm/sm2\"\n)\n\nvar (\n\toidSM2P256V1           = asn1.ObjectIdentifier{1, 2, 156, 10197, 1, 301}\n\toidSignatureSM3WithSM2 = asn1.ObjectIdentifier{1, 2, 156, 10197, 1, 501}\n\n\toidPublicKeyECDSA = asn1.ObjectIdentifier{1, 2, 840, 10045, 2, 1}\n\n\toidExtensionRequest = asn1.ObjectIdentifier{1, 2, 840, 113549, 1, 9, 14}\n\n\toidExtensionSubjectKeyId          = []int{2, 5, 29, 14}\n\toidExtensionKeyUsage              = []int{2, 5, 29, 15}\n\toidExtensionExtendedKeyUsage      = []int{2, 5, 29, 37}\n\toidExtensionAuthorityKeyId        = []int{2, 5, 29, 35}\n\toidExtensionBasicConstraints      = []int{2, 5, 29, 19}\n\toidExtensionSubjectAltName        = []int{2, 5, 29, 17}\n\toidExtensionCertificatePolicies   = []int{2, 5, 29, 32}\n\toidExtensionNameConstraints       = []int{2, 5, 29, 30}\n\toidExtensionCRLDistributionPoints = []int{2, 5, 29, 31}\n\toidExtensionAuthorityInfoAccess   = []int{1, 3, 6, 1, 5, 5, 7, 1, 1}\n\n\toidAuthorityInfoAccessOcsp    = asn1.ObjectIdentifier{1, 3, 6, 1, 5, 5, 7, 48, 1}\n\toidAuthorityInfoAccessIssuers = asn1.ObjectIdentifier{1, 3, 6, 1, 5, 5, 7, 48, 2}\n)\n\nconst (\n\tnameTypeEmail = 1\n\tnameTypeDNS   = 2\n\tnameTypeURI   = 6\n\tnameTypeIP    = 7\n)\n\ntype publicKeyInfo struct {\n\tRaw       asn1.RawContent\n\tAlgorithm pkix.AlgorithmIdentifier\n\tPublicKey asn1.BitString\n}\n\ntype tbsCertificateRequest struct {\n\tRaw           asn1.RawContent\n\tVersion       int\n\tSubject       asn1.RawValue\n\tPublicKey     publicKeyInfo\n\tRawAttributes []asn1.RawValue `asn1:\"tag:0\"`\n}\n\ntype certificateRequest struct {\n\tRaw                asn1.RawContent\n\tTBSCSR             tbsCertificateRequest\n\tSignatureAlgorithm pkix.AlgorithmIdentifier\n\tSignatureValue     asn1.BitString\n}\n\nfunc CreateCertificateRequest(template *x509.CertificateRequest, pub *sm2.PublicKey,\n\tpri *sm2.PrivateKey, userId []byte) (csr []byte, err error) {\n\tvar publicKeyBytes []byte\n\tvar publicKeyAlgorithm pkix.AlgorithmIdentifier\n\tpublicKeyBytes, publicKeyAlgorithm, err = marshalPublicKey(pub)\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\n\tvar extensions []pkix.Extension\n\tif (len(template.DNSNames) > 0 || len(template.EmailAddresses) > 0 || len(template.IPAddresses) > 0 || len(template.URIs) > 0) &&\n\t\t!oidInExtensions(oidExtensionSubjectAltName, template.ExtraExtensions) {\n\t\tsanBytes, err := marshalSANs(template.DNSNames, template.EmailAddresses, template.IPAddresses, template.URIs)\n\t\tif err != nil {\n\t\t\treturn nil, err\n\t\t}\n\n\t\textensions = append(extensions, pkix.Extension{\n\t\t\tId:    oidExtensionSubjectAltName,\n\t\t\tValue: sanBytes,\n\t\t})\n\t}\n\textensions = append(extensions, template.ExtraExtensions...)\n\n\tvar attributes []pkix.AttributeTypeAndValueSET\n\tattributes = append(attributes, template.Attributes...)\n\n\tif len(extensions) > 0 {\n\t\t// specifiedExtensions contains all the extensions that we\n\t\t// found specified via template.Attributes.\n\t\tspecifiedExtensions := make(map[string]bool)\n\n\t\tfor _, atvSet := range template.Attributes {\n\t\t\tif !atvSet.Type.Equal(oidExtensionRequest) {\n\t\t\t\tcontinue\n\t\t\t}\n\n\t\t\tfor _, atvs := range atvSet.Value {\n\t\t\t\tfor _, atv := range atvs {\n\t\t\t\t\tspecifiedExtensions[atv.Type.String()] = true\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\tatvs := make([]pkix.AttributeTypeAndValue, 0, len(extensions))\n\t\tfor _, e := range extensions {\n\t\t\tif specifiedExtensions[e.Id.String()] {\n\t\t\t\t// Attributes already contained a value for\n\t\t\t\t// this extension and it takes priority.\n\t\t\t\tcontinue\n\t\t\t}\n\n\t\t\tatvs = append(atvs, pkix.AttributeTypeAndValue{\n\t\t\t\t// There is no place for the critical flag in a CSR.\n\t\t\t\tType:  e.Id,\n\t\t\t\tValue: e.Value,\n\t\t\t})\n\t\t}\n\n\t\t// Append the extensions to an existing attribute if possible.\n\t\tappended := false\n\t\tfor _, atvSet := range attributes {\n\t\t\tif !atvSet.Type.Equal(oidExtensionRequest) || len(atvSet.Value) == 0 {\n\t\t\t\tcontinue\n\t\t\t}\n\n\t\t\tatvSet.Value[0] = append(atvSet.Value[0], atvs...)\n\t\t\tappended = true\n\t\t\tbreak\n\t\t}\n\n\t\t// Otherwise, add a new attribute for the extensions.\n\t\tif !appended {\n\t\t\tattributes = append(attributes, pkix.AttributeTypeAndValueSET{\n\t\t\t\tType: oidExtensionRequest,\n\t\t\t\tValue: [][]pkix.AttributeTypeAndValue{\n\t\t\t\t\tatvs,\n\t\t\t\t},\n\t\t\t})\n\t\t}\n\t}\n\n\tasn1Subject := template.RawSubject\n\tif len(asn1Subject) == 0 {\n\t\tasn1Subject, err = asn1.Marshal(template.Subject.ToRDNSequence())\n\t\tif err != nil {\n\t\t\treturn\n\t\t}\n\t}\n\n\trawAttributes, err := newRawAttributes(attributes)\n\tif err != nil {\n\t\treturn\n\t}\n\n\ttbsCSR := tbsCertificateRequest{\n\t\tVersion: 0, // PKCS #10, RFC 2986\n\t\tSubject: asn1.RawValue{FullBytes: asn1Subject},\n\t\tPublicKey: publicKeyInfo{\n\t\t\tAlgorithm: publicKeyAlgorithm,\n\t\t\tPublicKey: asn1.BitString{\n\t\t\t\tBytes:     publicKeyBytes,\n\t\t\t\tBitLength: len(publicKeyBytes) * 8,\n\t\t\t},\n\t\t},\n\t\tRawAttributes: rawAttributes,\n\t}\n\n\ttbsCSRContents, err := asn1.Marshal(tbsCSR)\n\tif err != nil {\n\t\treturn\n\t}\n\ttbsCSR.Raw = tbsCSRContents\n\n\tvar signature []byte\n\tsignature, err = sm2.Sign(pri, userId, tbsCSRContents)\n\tif err != nil {\n\t\treturn\n\t}\n\n\tvar sigAlgo pkix.AlgorithmIdentifier\n\tsigAlgo.Algorithm = oidSignatureSM3WithSM2\n\n\treturn asn1.Marshal(certificateRequest{\n\t\tTBSCSR:             tbsCSR,\n\t\tSignatureAlgorithm: sigAlgo,\n\t\tSignatureValue: asn1.BitString{\n\t\t\tBytes:     signature,\n\t\t\tBitLength: len(signature) * 8,\n\t\t},\n\t})\n}\n\n// marshalSANs marshals a list of addresses into a the contents of an X.509\n// SubjectAlternativeName extension.\nfunc marshalSANs(dnsNames, emailAddresses []string, ipAddresses []net.IP, uris []*url.URL) (derBytes []byte, err error) {\n\tvar rawValues []asn1.RawValue\n\tfor _, name := range dnsNames {\n\t\trawValues = append(rawValues, asn1.RawValue{Tag: nameTypeDNS, Class: 2, Bytes: []byte(name)})\n\t}\n\tfor _, email := range emailAddresses {\n\t\trawValues = append(rawValues, asn1.RawValue{Tag: nameTypeEmail, Class: 2, Bytes: []byte(email)})\n\t}\n\tfor _, rawIP := range ipAddresses {\n\t\t// If possible, we always want to encode IPv4 addresses in 4 bytes.\n\t\tip := rawIP.To4()\n\t\tif ip == nil {\n\t\t\tip = rawIP\n\t\t}\n\t\trawValues = append(rawValues, asn1.RawValue{Tag: nameTypeIP, Class: 2, Bytes: ip})\n\t}\n\tfor _, uri := range uris {\n\t\trawValues = append(rawValues, asn1.RawValue{Tag: nameTypeURI, Class: 2, Bytes: []byte(uri.String())})\n\t}\n\treturn asn1.Marshal(rawValues)\n}\n\n// oidNotInExtensions returns whether an extension with the given oid exists in\n// extensions.\nfunc oidInExtensions(oid asn1.ObjectIdentifier, extensions []pkix.Extension) bool {\n\tfor _, e := range extensions {\n\t\tif e.Id.Equal(oid) {\n\t\t\treturn true\n\t\t}\n\t}\n\treturn false\n}\n\nfunc marshalPublicKey(pub *sm2.PublicKey) (publicKeyBytes []byte, publicKeyAlgorithm pkix.AlgorithmIdentifier, err error) {\n\tpublicKeyBytes = pub.GetUnCompressBytes()\n\n\tpublicKeyAlgorithm.Algorithm = oidPublicKeyECDSA\n\tvar paramBytes []byte\n\tparamBytes, err = asn1.Marshal(oidSM2P256V1)\n\tpublicKeyAlgorithm.Parameters.FullBytes = paramBytes\n\n\terr = nil\n\treturn\n}\n\n// newRawAttributes converts AttributeTypeAndValueSETs from a template\n// CertificateRequest's Attributes into tbsCertificateRequest RawAttributes.\nfunc newRawAttributes(attributes []pkix.AttributeTypeAndValueSET) ([]asn1.RawValue, error) {\n\tvar rawAttributes []asn1.RawValue\n\tb, err := asn1.Marshal(attributes)\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\trest, err := asn1.Unmarshal(b, &rawAttributes)\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\tif len(rest) != 0 {\n\t\treturn nil, errors.New(\"x509: failed to unmarshal raw CSR Attributes\")\n\t}\n\treturn rawAttributes, nil\n}\n\n// ParseCertificateRequest parses a single certificate request from the\n// given ASN.1 DER data.\nfunc ParseCertificateRequest(asn1Data []byte) (*x509.CertificateRequest, error) {\n\tvar csr certificateRequest\n\n\trest, err := asn1.Unmarshal(asn1Data, &csr)\n\tif err != nil {\n\t\treturn nil, err\n\t} else if len(rest) != 0 {\n\t\treturn nil, asn1.SyntaxError{Msg: \"trailing data\"}\n\t}\n\n\treturn parseCertificateRequest(&csr)\n}\n\nfunc parseCertificateRequest(in *certificateRequest) (*x509.CertificateRequest, error) {\n\tout := &x509.CertificateRequest{\n\t\tRaw:                      in.Raw,\n\t\tRawTBSCertificateRequest: in.TBSCSR.Raw,\n\t\tRawSubjectPublicKeyInfo:  in.TBSCSR.PublicKey.Raw,\n\t\tRawSubject:               in.TBSCSR.Subject.FullBytes,\n\n\t\tSignature:          in.SignatureValue.RightAlign(),\n\t\tSignatureAlgorithm: 0, //与x509.go里的实现不一样，因为这里都是固定了使用SM3WithSM2\n\n\t\tPublicKeyAlgorithm: 0, //与x509.go里的实现不一样，因为这里都是固定了使用EC公钥\n\n\t\tVersion:    in.TBSCSR.Version,\n\t\tAttributes: parseRawAttributes(in.TBSCSR.RawAttributes),\n\t}\n\n\tif !oidSignatureSM3WithSM2.Equal(in.SignatureAlgorithm.Algorithm) {\n\t\treturn nil, errors.New(\"x509: illegal signature algorithm OID\")\n\t}\n\tif !oidPublicKeyECDSA.Equal(in.TBSCSR.PublicKey.Algorithm.Algorithm) {\n\t\treturn nil, errors.New(\"x509: illegal publick key algorithm OID\")\n\t}\n\n\tvar err error\n\tout.PublicKey, err = parsePublicKey(&in.TBSCSR.PublicKey)\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\n\tvar subject pkix.RDNSequence\n\tif rest, err := asn1.Unmarshal(in.TBSCSR.Subject.FullBytes, &subject); err != nil {\n\t\treturn nil, err\n\t} else if len(rest) != 0 {\n\t\treturn nil, errors.New(\"x509: trailing data after X.509 Subject\")\n\t}\n\n\tout.Subject.FillFromRDNSequence(&subject)\n\n\tif out.Extensions, err = parseCSRExtensions(in.TBSCSR.RawAttributes); err != nil {\n\t\treturn nil, err\n\t}\n\n\tfor _, extension := range out.Extensions {\n\t\tif extension.Id.Equal(oidExtensionSubjectAltName) {\n\t\t\tout.DNSNames, out.EmailAddresses, out.IPAddresses, out.URIs, err = parseSANExtension(extension.Value)\n\t\t\tif err != nil {\n\t\t\t\treturn nil, err\n\t\t\t}\n\t\t}\n\t}\n\n\treturn out, nil\n}\n\nfunc parsePublicKey(keyData *publicKeyInfo) (interface{}, error) {\n\tparamsData := keyData.Algorithm.Parameters.FullBytes\n\tnamedCurveOID := new(asn1.ObjectIdentifier)\n\trest, err := asn1.Unmarshal(paramsData, namedCurveOID)\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\tif len(rest) != 0 {\n\t\treturn nil, errors.New(\"x509: trailing data after SM2 parameters\")\n\t}\n\tif !oidSM2P256V1.Equal(*namedCurveOID) {\n\t\treturn nil, errors.New(\"x509: CurveOID is not the OID of SM2P256V1\")\n\t}\n\n\tcurve := sm2.GetSm2P256V1()\n\tx, y := elliptic.Unmarshal(curve, keyData.PublicKey.RightAlign())\n\tif x == nil || y == nil {\n\t\treturn nil, errors.New(\"x509: Unmarshal PublicKey failed\")\n\t}\n\tpub := &sm2.PublicKey{\n\t\tCurve: curve,\n\t\tX:     x,\n\t\tY:     y,\n\t}\n\treturn pub, nil\n}\n\n// parseRawAttributes Unmarshals RawAttributes intos AttributeTypeAndValueSETs.\nfunc parseRawAttributes(rawAttributes []asn1.RawValue) []pkix.AttributeTypeAndValueSET {\n\tvar attributes []pkix.AttributeTypeAndValueSET\n\tfor _, rawAttr := range rawAttributes {\n\t\tvar attr pkix.AttributeTypeAndValueSET\n\t\trest, err := asn1.Unmarshal(rawAttr.FullBytes, &attr)\n\t\t// Ignore attributes that don't parse into pkix.AttributeTypeAndValueSET\n\t\t// (i.e.: challengePassword or unstructuredName).\n\t\tif err == nil && len(rest) == 0 {\n\t\t\tattributes = append(attributes, attr)\n\t\t}\n\t}\n\treturn attributes\n}\n\n// parseCSRExtensions parses the attributes from a CSR and extracts any\n// requested extensions.\nfunc parseCSRExtensions(rawAttributes []asn1.RawValue) ([]pkix.Extension, error) {\n\t// pkcs10Attribute reflects the Attribute structure from section 4.1 of\n\t// https://tools.ietf.org/html/rfc2986.\n\ttype pkcs10Attribute struct {\n\t\tId     asn1.ObjectIdentifier\n\t\tValues []asn1.RawValue `asn1:\"set\"`\n\t}\n\n\tvar ret []pkix.Extension\n\tfor _, rawAttr := range rawAttributes {\n\t\tvar attr pkcs10Attribute\n\t\tif rest, err := asn1.Unmarshal(rawAttr.FullBytes, &attr); err != nil || len(rest) != 0 || len(attr.Values) == 0 {\n\t\t\t// Ignore attributes that don't parse.\n\t\t\tcontinue\n\t\t}\n\n\t\tif !attr.Id.Equal(oidExtensionRequest) {\n\t\t\tcontinue\n\t\t}\n\n\t\tvar extensions []pkix.Extension\n\t\tif _, err := asn1.Unmarshal(attr.Values[0].FullBytes, &extensions); err != nil {\n\t\t\treturn nil, err\n\t\t}\n\t\tret = append(ret, extensions...)\n\t}\n\n\treturn ret, nil\n}\n\nfunc forEachSAN(extension []byte, callback func(tag int, data []byte) error) error {\n\t// RFC 5280, 4.2.1.6\n\n\t// SubjectAltName ::= GeneralNames\n\t//\n\t// GeneralNames ::= SEQUENCE SIZE (1..MAX) OF GeneralName\n\t//\n\t// GeneralName ::= CHOICE {\n\t//      otherName                       [0]     OtherName,\n\t//      rfc822Name                      [1]     IA5String,\n\t//      dNSName                         [2]     IA5String,\n\t//      x400Address                     [3]     ORAddress,\n\t//      directoryName                   [4]     Name,\n\t//      ediPartyName                    [5]     EDIPartyName,\n\t//      uniformResourceIdentifier       [6]     IA5String,\n\t//      iPAddress                       [7]     OCTET STRING,\n\t//      registeredID                    [8]     OBJECT IDENTIFIER }\n\tvar seq asn1.RawValue\n\trest, err := asn1.Unmarshal(extension, &seq)\n\tif err != nil {\n\t\treturn err\n\t} else if len(rest) != 0 {\n\t\treturn errors.New(\"x509: trailing data after X.509 extension\")\n\t}\n\tif !seq.IsCompound || seq.Tag != 16 || seq.Class != 0 {\n\t\treturn asn1.StructuralError{Msg: \"bad SAN sequence\"}\n\t}\n\n\trest = seq.Bytes\n\tfor len(rest) > 0 {\n\t\tvar v asn1.RawValue\n\t\trest, err = asn1.Unmarshal(rest, &v)\n\t\tif err != nil {\n\t\t\treturn err\n\t\t}\n\n\t\tif err := callback(v.Tag, v.Bytes); err != nil {\n\t\t\treturn err\n\t\t}\n\t}\n\n\treturn nil\n}\n\n// domainToReverseLabels converts a textual domain name like foo.example.com to\n// the list of labels in reverse order, e.g. [\"com\", \"example\", \"foo\"].\nfunc domainToReverseLabels(domain string) (reverseLabels []string, ok bool) {\n\tfor len(domain) > 0 {\n\t\tif i := strings.LastIndexByte(domain, '.'); i == -1 {\n\t\t\treverseLabels = append(reverseLabels, domain)\n\t\t\tdomain = \"\"\n\t\t} else {\n\t\t\treverseLabels = append(reverseLabels, domain[i+1:])\n\t\t\tdomain = domain[:i]\n\t\t}\n\t}\n\n\tif len(reverseLabels) > 0 && len(reverseLabels[0]) == 0 {\n\t\t// An empty label at the end indicates an absolute value.\n\t\treturn nil, false\n\t}\n\n\tfor _, label := range reverseLabels {\n\t\tif len(label) == 0 {\n\t\t\t// Empty labels are otherwise invalid.\n\t\t\treturn nil, false\n\t\t}\n\n\t\tfor _, c := range label {\n\t\t\tif c < 33 || c > 126 {\n\t\t\t\t// Invalid character.\n\t\t\t\treturn nil, false\n\t\t\t}\n\t\t}\n\t}\n\n\treturn reverseLabels, true\n}\n\nfunc parseSANExtension(value []byte) (dnsNames, emailAddresses []string, ipAddresses []net.IP, uris []*url.URL, err error) {\n\terr = forEachSAN(value, func(tag int, data []byte) error {\n\t\tswitch tag {\n\t\tcase nameTypeEmail:\n\t\t\temailAddresses = append(emailAddresses, string(data))\n\t\tcase nameTypeDNS:\n\t\t\tdnsNames = append(dnsNames, string(data))\n\t\tcase nameTypeURI:\n\t\t\turi, err := url.Parse(string(data))\n\t\t\tif err != nil {\n\t\t\t\treturn fmt.Errorf(\"x509: cannot parse URI %q: %s\", string(data), err)\n\t\t\t}\n\t\t\tif len(uri.Host) > 0 {\n\t\t\t\tif _, ok := domainToReverseLabels(uri.Host); !ok {\n\t\t\t\t\treturn fmt.Errorf(\"x509: cannot parse URI %q: invalid domain\", string(data))\n\t\t\t\t}\n\t\t\t}\n\t\t\turis = append(uris, uri)\n\t\tcase nameTypeIP:\n\t\t\tswitch len(data) {\n\t\t\tcase net.IPv4len, net.IPv6len:\n\t\t\t\tipAddresses = append(ipAddresses, data)\n\t\t\tdefault:\n\t\t\t\treturn errors.New(\"x509: cannot parse IP address of length \" + strconv.Itoa(len(data)))\n\t\t\t}\n\t\t}\n\n\t\treturn nil\n\t})\n\n\treturn\n}\n\nfunc VerifyDERCSRSign(asn1Data []byte, userId []byte) (bool, error) {\n\tcsr, err := ParseCertificateRequest(asn1Data)\n\tif err != nil {\n\t\treturn false, err\n\t}\n\treturn VerifyCSRSign(csr, userId), nil\n}\n\nfunc VerifyCSRSign(csr *x509.CertificateRequest, userId []byte) bool {\n\tpub := csr.PublicKey.(*sm2.PublicKey)\n\treturn sm2.Verify(pub, userId, csr.RawTBSCertificateRequest, csr.Signature)\n}\n\nfunc FillCertificateTemplateByCSR(template *x509.Certificate, csr *x509.CertificateRequest) {\n\ttemplate.Subject = csr.Subject\n\ttemplate.PublicKeyAlgorithm = csr.PublicKeyAlgorithm\n\ttemplate.PublicKey = csr.PublicKey\n\ttemplate.Extensions = csr.Extensions\n\ttemplate.ExtraExtensions = csr.ExtraExtensions\n\ttemplate.DNSNames = csr.DNSNames\n\ttemplate.EmailAddresses = csr.EmailAddresses\n\ttemplate.IPAddresses = csr.IPAddresses\n\ttemplate.URIs = csr.URIs\n}\n\nfunc subjectBytes(cert *x509.Certificate) ([]byte, error) {\n\tif len(cert.RawSubject) > 0 {\n\t\treturn cert.RawSubject, nil\n\t}\n\n\treturn asn1.Marshal(cert.Subject.ToRDNSequence())\n}\n\nfunc reverseBitsInAByte(in byte) byte {\n\tb1 := in>>4 | in<<4\n\tb2 := b1>>2&0x33 | b1<<2&0xcc\n\tb3 := b2>>1&0x55 | b2<<1&0xaa\n\treturn b3\n}\n\n// asn1BitLength returns the bit-length of bitString by considering the\n// most-significant bit in a byte to be the \"first\" bit. This convention\n// matches ASN.1, but differs from almost everything else.\nfunc asn1BitLength(bitString []byte) int {\n\tbitLen := len(bitString) * 8\n\n\tfor i := range bitString {\n\t\tb := bitString[len(bitString)-i-1]\n\n\t\tfor bit := uint(0); bit < 8; bit++ {\n\t\t\tif (b>>bit)&1 == 1 {\n\t\t\t\treturn bitLen\n\t\t\t}\n\t\t\tbitLen--\n\t\t}\n\t}\n\n\treturn 0\n}\n\n// RFC 5280, 4.2.1.12  Extended Key Usage\n//\n// anyExtendedKeyUsage OBJECT IDENTIFIER ::= { id-ce-extKeyUsage 0 }\n//\n// id-kp OBJECT IDENTIFIER ::= { id-pkix 3 }\n//\n// id-kp-serverAuth             OBJECT IDENTIFIER ::= { id-kp 1 }\n// id-kp-clientAuth             OBJECT IDENTIFIER ::= { id-kp 2 }\n// id-kp-codeSigning            OBJECT IDENTIFIER ::= { id-kp 3 }\n// id-kp-emailProtection        OBJECT IDENTIFIER ::= { id-kp 4 }\n// id-kp-timeStamping           OBJECT IDENTIFIER ::= { id-kp 8 }\n// id-kp-OCSPSigning            OBJECT IDENTIFIER ::= { id-kp 9 }\nvar (\n\toidExtKeyUsageAny                            = asn1.ObjectIdentifier{2, 5, 29, 37, 0}\n\toidExtKeyUsageServerAuth                     = asn1.ObjectIdentifier{1, 3, 6, 1, 5, 5, 7, 3, 1}\n\toidExtKeyUsageClientAuth                     = asn1.ObjectIdentifier{1, 3, 6, 1, 5, 5, 7, 3, 2}\n\toidExtKeyUsageCodeSigning                    = asn1.ObjectIdentifier{1, 3, 6, 1, 5, 5, 7, 3, 3}\n\toidExtKeyUsageEmailProtection                = asn1.ObjectIdentifier{1, 3, 6, 1, 5, 5, 7, 3, 4}\n\toidExtKeyUsageIPSECEndSystem                 = asn1.ObjectIdentifier{1, 3, 6, 1, 5, 5, 7, 3, 5}\n\toidExtKeyUsageIPSECTunnel                    = asn1.ObjectIdentifier{1, 3, 6, 1, 5, 5, 7, 3, 6}\n\toidExtKeyUsageIPSECUser                      = asn1.ObjectIdentifier{1, 3, 6, 1, 5, 5, 7, 3, 7}\n\toidExtKeyUsageTimeStamping                   = asn1.ObjectIdentifier{1, 3, 6, 1, 5, 5, 7, 3, 8}\n\toidExtKeyUsageOCSPSigning                    = asn1.ObjectIdentifier{1, 3, 6, 1, 5, 5, 7, 3, 9}\n\toidExtKeyUsageMicrosoftServerGatedCrypto     = asn1.ObjectIdentifier{1, 3, 6, 1, 4, 1, 311, 10, 3, 3}\n\toidExtKeyUsageNetscapeServerGatedCrypto      = asn1.ObjectIdentifier{2, 16, 840, 1, 113730, 4, 1}\n\toidExtKeyUsageMicrosoftCommercialCodeSigning = asn1.ObjectIdentifier{1, 3, 6, 1, 4, 1, 311, 2, 1, 22}\n\toidExtKeyUsageMicrosoftKernelCodeSigning     = asn1.ObjectIdentifier{1, 3, 6, 1, 4, 1, 311, 61, 1, 1}\n)\n\n// extKeyUsageOIDs contains the mapping between an ExtKeyUsage and its OID.\nvar extKeyUsageOIDs = []struct {\n\textKeyUsage x509.ExtKeyUsage\n\toid         asn1.ObjectIdentifier\n}{\n\t{x509.ExtKeyUsageAny, oidExtKeyUsageAny},\n\t{x509.ExtKeyUsageServerAuth, oidExtKeyUsageServerAuth},\n\t{x509.ExtKeyUsageClientAuth, oidExtKeyUsageClientAuth},\n\t{x509.ExtKeyUsageCodeSigning, oidExtKeyUsageCodeSigning},\n\t{x509.ExtKeyUsageEmailProtection, oidExtKeyUsageEmailProtection},\n\t{x509.ExtKeyUsageIPSECEndSystem, oidExtKeyUsageIPSECEndSystem},\n\t{x509.ExtKeyUsageIPSECTunnel, oidExtKeyUsageIPSECTunnel},\n\t{x509.ExtKeyUsageIPSECUser, oidExtKeyUsageIPSECUser},\n\t{x509.ExtKeyUsageTimeStamping, oidExtKeyUsageTimeStamping},\n\t{x509.ExtKeyUsageOCSPSigning, oidExtKeyUsageOCSPSigning},\n\t{x509.ExtKeyUsageMicrosoftServerGatedCrypto, oidExtKeyUsageMicrosoftServerGatedCrypto},\n\t{x509.ExtKeyUsageNetscapeServerGatedCrypto, oidExtKeyUsageNetscapeServerGatedCrypto},\n\t{x509.ExtKeyUsageMicrosoftCommercialCodeSigning, oidExtKeyUsageMicrosoftCommercialCodeSigning},\n\t{x509.ExtKeyUsageMicrosoftKernelCodeSigning, oidExtKeyUsageMicrosoftKernelCodeSigning},\n}\n\nfunc oidFromExtKeyUsage(eku x509.ExtKeyUsage) (oid asn1.ObjectIdentifier, ok bool) {\n\tfor _, pair := range extKeyUsageOIDs {\n\t\tif eku == pair.extKeyUsage {\n\t\t\treturn pair.oid, true\n\t\t}\n\t}\n\treturn\n}\n\ntype basicConstraints struct {\n\tIsCA       bool `asn1:\"optional\"`\n\tMaxPathLen int  `asn1:\"optional,default:-1\"`\n}\n\n// RFC 5280,  4.2.1.1\ntype authKeyId struct {\n\tId []byte `asn1:\"optional,tag:0\"`\n}\n\n// RFC 5280, 4.2.2.1\ntype authorityInfoAccess struct {\n\tMethod   asn1.ObjectIdentifier\n\tLocation asn1.RawValue\n}\n\n// RFC 5280 4.2.1.4\ntype policyInformation struct {\n\tPolicy asn1.ObjectIdentifier\n\t// policyQualifiers omitted\n}\n\ntype distributionPointName struct {\n\tFullName     []asn1.RawValue  `asn1:\"optional,tag:0\"`\n\tRelativeName pkix.RDNSequence `asn1:\"optional,tag:1\"`\n}\n\n// RFC 5280, 4.2.1.14\ntype distributionPoint struct {\n\tDistributionPoint distributionPointName `asn1:\"optional,tag:0\"`\n\tReason            asn1.BitString        `asn1:\"optional,tag:1\"`\n\tCRLIssuer         asn1.RawValue         `asn1:\"optional,tag:2\"`\n}\n\nfunc isIA5String(s string) error {\n\tfor _, r := range s {\n\t\tif r >= utf8.RuneSelf {\n\t\t\treturn fmt.Errorf(\"x509: %q cannot be encoded as an IA5String\", s)\n\t\t}\n\t}\n\n\treturn nil\n}\n\nfunc buildExtensions(template *x509.Certificate, subjectIsEmpty bool, authorityKeyId []byte) (ret []pkix.Extension, err error) {\n\tret = make([]pkix.Extension, 10 /* maximum number of elements. */)\n\tn := 0\n\n\tif template.KeyUsage != 0 &&\n\t\t!oidInExtensions(oidExtensionKeyUsage, template.ExtraExtensions) {\n\t\tret[n].Id = oidExtensionKeyUsage\n\t\tret[n].Critical = true\n\n\t\tvar a [2]byte\n\t\ta[0] = reverseBitsInAByte(byte(template.KeyUsage))\n\t\ta[1] = reverseBitsInAByte(byte(template.KeyUsage >> 8))\n\n\t\tl := 1\n\t\tif a[1] != 0 {\n\t\t\tl = 2\n\t\t}\n\n\t\tbitString := a[:l]\n\t\tret[n].Value, err = asn1.Marshal(asn1.BitString{Bytes: bitString, BitLength: asn1BitLength(bitString)})\n\t\tif err != nil {\n\t\t\treturn\n\t\t}\n\t\tn++\n\t}\n\n\tif (len(template.ExtKeyUsage) > 0 || len(template.UnknownExtKeyUsage) > 0) &&\n\t\t!oidInExtensions(oidExtensionExtendedKeyUsage, template.ExtraExtensions) {\n\t\tret[n].Id = oidExtensionExtendedKeyUsage\n\n\t\tvar oids []asn1.ObjectIdentifier\n\t\tfor _, u := range template.ExtKeyUsage {\n\t\t\tif oid, ok := oidFromExtKeyUsage(u); ok {\n\t\t\t\toids = append(oids, oid)\n\t\t\t} else {\n\t\t\t\tpanic(\"internal error\")\n\t\t\t}\n\t\t}\n\n\t\toids = append(oids, template.UnknownExtKeyUsage...)\n\n\t\tret[n].Value, err = asn1.Marshal(oids)\n\t\tif err != nil {\n\t\t\treturn\n\t\t}\n\t\tn++\n\t}\n\n\tif template.BasicConstraintsValid && !oidInExtensions(oidExtensionBasicConstraints, template.ExtraExtensions) {\n\t\t// Leaving MaxPathLen as zero indicates that no maximum path\n\t\t// length is desired, unless MaxPathLenZero is set. A value of\n\t\t// -1 causes encoding/asn1 to omit the value as desired.\n\t\tmaxPathLen := template.MaxPathLen\n\t\tif maxPathLen == 0 && !template.MaxPathLenZero {\n\t\t\tmaxPathLen = -1\n\t\t}\n\t\tret[n].Id = oidExtensionBasicConstraints\n\t\tret[n].Value, err = asn1.Marshal(basicConstraints{template.IsCA, maxPathLen})\n\t\tret[n].Critical = true\n\t\tif err != nil {\n\t\t\treturn\n\t\t}\n\t\tn++\n\t}\n\n\tif len(template.SubjectKeyId) > 0 && !oidInExtensions(oidExtensionSubjectKeyId, template.ExtraExtensions) {\n\t\tret[n].Id = oidExtensionSubjectKeyId\n\t\tret[n].Value, err = asn1.Marshal(template.SubjectKeyId)\n\t\tif err != nil {\n\t\t\treturn\n\t\t}\n\t\tn++\n\t}\n\n\tif len(authorityKeyId) > 0 && !oidInExtensions(oidExtensionAuthorityKeyId, template.ExtraExtensions) {\n\t\tret[n].Id = oidExtensionAuthorityKeyId\n\t\tret[n].Value, err = asn1.Marshal(authKeyId{authorityKeyId})\n\t\tif err != nil {\n\t\t\treturn\n\t\t}\n\t\tn++\n\t}\n\n\tif (len(template.OCSPServer) > 0 || len(template.IssuingCertificateURL) > 0) &&\n\t\t!oidInExtensions(oidExtensionAuthorityInfoAccess, template.ExtraExtensions) {\n\t\tret[n].Id = oidExtensionAuthorityInfoAccess\n\t\tvar aiaValues []authorityInfoAccess\n\t\tfor _, name := range template.OCSPServer {\n\t\t\taiaValues = append(aiaValues, authorityInfoAccess{\n\t\t\t\tMethod:   oidAuthorityInfoAccessOcsp,\n\t\t\t\tLocation: asn1.RawValue{Tag: 6, Class: 2, Bytes: []byte(name)},\n\t\t\t})\n\t\t}\n\t\tfor _, name := range template.IssuingCertificateURL {\n\t\t\taiaValues = append(aiaValues, authorityInfoAccess{\n\t\t\t\tMethod:   oidAuthorityInfoAccessIssuers,\n\t\t\t\tLocation: asn1.RawValue{Tag: 6, Class: 2, Bytes: []byte(name)},\n\t\t\t})\n\t\t}\n\t\tret[n].Value, err = asn1.Marshal(aiaValues)\n\t\tif err != nil {\n\t\t\treturn\n\t\t}\n\t\tn++\n\t}\n\n\tif (len(template.DNSNames) > 0 || len(template.EmailAddresses) > 0 || len(template.IPAddresses) > 0 || len(template.URIs) > 0) &&\n\t\t!oidInExtensions(oidExtensionSubjectAltName, template.ExtraExtensions) {\n\t\tret[n].Id = oidExtensionSubjectAltName\n\t\t// https://tools.ietf.org/html/rfc5280#section-4.2.1.6\n\t\t// “If the subject field contains an empty sequence ... then\n\t\t// subjectAltName extension ... is marked as critical”\n\t\tret[n].Critical = subjectIsEmpty\n\t\tret[n].Value, err = marshalSANs(template.DNSNames, template.EmailAddresses, template.IPAddresses, template.URIs)\n\t\tif err != nil {\n\t\t\treturn\n\t\t}\n\t\tn++\n\t}\n\n\tif len(template.PolicyIdentifiers) > 0 &&\n\t\t!oidInExtensions(oidExtensionCertificatePolicies, template.ExtraExtensions) {\n\t\tret[n].Id = oidExtensionCertificatePolicies\n\t\tpolicies := make([]policyInformation, len(template.PolicyIdentifiers))\n\t\tfor i, policy := range template.PolicyIdentifiers {\n\t\t\tpolicies[i].Policy = policy\n\t\t}\n\t\tret[n].Value, err = asn1.Marshal(policies)\n\t\tif err != nil {\n\t\t\treturn\n\t\t}\n\t\tn++\n\t}\n\n\tif (len(template.PermittedDNSDomains) > 0 || len(template.ExcludedDNSDomains) > 0 ||\n\t\tlen(template.PermittedIPRanges) > 0 || len(template.ExcludedIPRanges) > 0 ||\n\t\tlen(template.PermittedEmailAddresses) > 0 || len(template.ExcludedEmailAddresses) > 0 ||\n\t\tlen(template.PermittedURIDomains) > 0 || len(template.ExcludedURIDomains) > 0) &&\n\t\t!oidInExtensions(oidExtensionNameConstraints, template.ExtraExtensions) {\n\t\tret[n].Id = oidExtensionNameConstraints\n\t\tret[n].Critical = template.PermittedDNSDomainsCritical\n\n\t\tipAndMask := func(ipNet *net.IPNet) []byte {\n\t\t\tmaskedIP := ipNet.IP.Mask(ipNet.Mask)\n\t\t\tipAndMask := make([]byte, 0, len(maskedIP)+len(ipNet.Mask))\n\t\t\tipAndMask = append(ipAndMask, maskedIP...)\n\t\t\tipAndMask = append(ipAndMask, ipNet.Mask...)\n\t\t\treturn ipAndMask\n\t\t}\n\n\t\tserialiseConstraints := func(dns []string, ips []*net.IPNet, emails []string, uriDomains []string) (der []byte, err error) {\n\t\t\tvar b cryptobyte.Builder\n\n\t\t\tfor _, name := range dns {\n\t\t\t\tif err = isIA5String(name); err != nil {\n\t\t\t\t\treturn nil, err\n\t\t\t\t}\n\n\t\t\t\tb.AddASN1(cryptobyte_asn1.SEQUENCE, func(b *cryptobyte.Builder) {\n\t\t\t\t\tb.AddASN1(cryptobyte_asn1.Tag(2).ContextSpecific(), func(b *cryptobyte.Builder) {\n\t\t\t\t\t\tb.AddBytes([]byte(name))\n\t\t\t\t\t})\n\t\t\t\t})\n\t\t\t}\n\n\t\t\tfor _, ipNet := range ips {\n\t\t\t\tb.AddASN1(cryptobyte_asn1.SEQUENCE, func(b *cryptobyte.Builder) {\n\t\t\t\t\tb.AddASN1(cryptobyte_asn1.Tag(7).ContextSpecific(), func(b *cryptobyte.Builder) {\n\t\t\t\t\t\tb.AddBytes(ipAndMask(ipNet))\n\t\t\t\t\t})\n\t\t\t\t})\n\t\t\t}\n\n\t\t\tfor _, email := range emails {\n\t\t\t\tif err = isIA5String(email); err != nil {\n\t\t\t\t\treturn nil, err\n\t\t\t\t}\n\n\t\t\t\tb.AddASN1(cryptobyte_asn1.SEQUENCE, func(b *cryptobyte.Builder) {\n\t\t\t\t\tb.AddASN1(cryptobyte_asn1.Tag(1).ContextSpecific(), func(b *cryptobyte.Builder) {\n\t\t\t\t\t\tb.AddBytes([]byte(email))\n\t\t\t\t\t})\n\t\t\t\t})\n\t\t\t}\n\n\t\t\tfor _, uriDomain := range uriDomains {\n\t\t\t\tif err = isIA5String(uriDomain); err != nil {\n\t\t\t\t\treturn nil, err\n\t\t\t\t}\n\n\t\t\t\tb.AddASN1(cryptobyte_asn1.SEQUENCE, func(b *cryptobyte.Builder) {\n\t\t\t\t\tb.AddASN1(cryptobyte_asn1.Tag(6).ContextSpecific(), func(b *cryptobyte.Builder) {\n\t\t\t\t\t\tb.AddBytes([]byte(uriDomain))\n\t\t\t\t\t})\n\t\t\t\t})\n\t\t\t}\n\n\t\t\treturn b.Bytes()\n\t\t}\n\n\t\tpermitted, err := serialiseConstraints(template.PermittedDNSDomains, template.PermittedIPRanges, template.PermittedEmailAddresses, template.PermittedURIDomains)\n\t\tif err != nil {\n\t\t\treturn nil, err\n\t\t}\n\n\t\texcluded, err := serialiseConstraints(template.ExcludedDNSDomains, template.ExcludedIPRanges, template.ExcludedEmailAddresses, template.ExcludedURIDomains)\n\t\tif err != nil {\n\t\t\treturn nil, err\n\t\t}\n\n\t\tvar b cryptobyte.Builder\n\t\tb.AddASN1(cryptobyte_asn1.SEQUENCE, func(b *cryptobyte.Builder) {\n\t\t\tif len(permitted) > 0 {\n\t\t\t\tb.AddASN1(cryptobyte_asn1.Tag(0).ContextSpecific().Constructed(), func(b *cryptobyte.Builder) {\n\t\t\t\t\tb.AddBytes(permitted)\n\t\t\t\t})\n\t\t\t}\n\n\t\t\tif len(excluded) > 0 {\n\t\t\t\tb.AddASN1(cryptobyte_asn1.Tag(1).ContextSpecific().Constructed(), func(b *cryptobyte.Builder) {\n\t\t\t\t\tb.AddBytes(excluded)\n\t\t\t\t})\n\t\t\t}\n\t\t})\n\n\t\tret[n].Value, err = b.Bytes()\n\t\tif err != nil {\n\t\t\treturn nil, err\n\t\t}\n\t\tn++\n\t}\n\n\tif len(template.CRLDistributionPoints) > 0 &&\n\t\t!oidInExtensions(oidExtensionCRLDistributionPoints, template.ExtraExtensions) {\n\t\tret[n].Id = oidExtensionCRLDistributionPoints\n\n\t\tvar crlDp []distributionPoint\n\t\tfor _, name := range template.CRLDistributionPoints {\n\t\t\tdp := distributionPoint{\n\t\t\t\tDistributionPoint: distributionPointName{\n\t\t\t\t\tFullName: []asn1.RawValue{\n\t\t\t\t\t\t{Tag: 6, Class: 2, Bytes: []byte(name)},\n\t\t\t\t\t},\n\t\t\t\t},\n\t\t\t}\n\t\t\tcrlDp = append(crlDp, dp)\n\t\t}\n\n\t\tret[n].Value, err = asn1.Marshal(crlDp)\n\t\tif err != nil {\n\t\t\treturn\n\t\t}\n\t\tn++\n\t}\n\n\t// Adding another extension here? Remember to update the maximum number\n\t// of elements in the make() at the top of the function.\n\n\treturn append(ret[:n], template.ExtraExtensions...), nil\n}\n\ntype validity struct {\n\tNotBefore, NotAfter time.Time\n}\n\ntype certificate struct {\n\tRaw                asn1.RawContent\n\tTBSCertificate     TBSCertificate\n\tSignatureAlgorithm pkix.AlgorithmIdentifier\n\tSignatureValue     asn1.BitString\n}\n\ntype tbsCertificate struct {\n\tRaw                asn1.RawContent\n\tVersion            int `asn1:\"optional,explicit,default:0,tag:0\"`\n\tSerialNumber       *big.Int\n\tSignatureAlgorithm pkix.AlgorithmIdentifier\n\tIssuer             asn1.RawValue\n\tValidity           validity\n\tSubject            asn1.RawValue\n\tPublicKey          publicKeyInfo\n\tUniqueId           asn1.BitString   `asn1:\"optional,tag:1\"`\n\tSubjectUniqueId    asn1.BitString   `asn1:\"optional,tag:2\"`\n\tExtensions         []pkix.Extension `asn1:\"optional,explicit,tag:3\"`\n}\n\ntype TBSCertificate tbsCertificate\n\n// emptyASN1Subject is the ASN.1 DER encoding of an empty Subject, which is\n// just an empty SEQUENCE.\nvar emptyASN1Subject = []byte{0x30, 0}\n\n// 为什么要将构建CertificateInfo和签发证书分开呢?\n// 是因为实际应用中的CA密钥大多数都是放在加密卡/加密机中的，签名由加密卡/加密机来完成\nfunc CreateCertificateInfo(template, parent *x509.Certificate, csr *x509.CertificateRequest) (*TBSCertificate, error) {\n\tif template.SerialNumber == nil {\n\t\treturn nil, errors.New(\"x509: no SerialNumber given\")\n\t}\n\n\tasn1Issuer, err := subjectBytes(parent)\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\n\tasn1Subject, err := subjectBytes(template)\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\n\tauthorityKeyId := template.AuthorityKeyId\n\tif !bytes.Equal(asn1Issuer, asn1Subject) && len(parent.SubjectKeyId) > 0 {\n\t\tauthorityKeyId = parent.SubjectKeyId\n\t}\n\n\textensions, err := buildExtensions(template, bytes.Equal(asn1Subject, emptyASN1Subject), authorityKeyId)\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\n\tvar sigAlgo pkix.AlgorithmIdentifier\n\tsigAlgo.Algorithm = oidSignatureSM3WithSM2\n\tvar subjectPubKeyInfo publicKeyInfo\n\trest, err := asn1.Unmarshal(csr.RawSubjectPublicKeyInfo, &subjectPubKeyInfo)\n\tif err != nil {\n\t\treturn nil, err\n\t} else if len(rest) != 0 {\n\t\treturn nil, asn1.SyntaxError{Msg: \"trailing data\"}\n\t}\n\tc := TBSCertificate{\n\t\tVersion:            2,\n\t\tSerialNumber:       template.SerialNumber,\n\t\tSignatureAlgorithm: sigAlgo,\n\t\tIssuer:             asn1.RawValue{FullBytes: asn1Issuer},\n\t\tValidity:           validity{template.NotBefore.UTC(), template.NotAfter.UTC()},\n\t\tSubject:            asn1.RawValue{FullBytes: asn1Subject},\n\t\tPublicKey:          subjectPubKeyInfo,\n\t\tExtensions:         extensions,\n\t}\n\n\ttbsCertContents, err := asn1.Marshal(c)\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\tc.Raw = tbsCertContents\n\treturn &c, nil\n}\n\nfunc IssueCertificateBySoftCAKey(cinfo *TBSCertificate, caPri *sm2.PrivateKey, userId []byte) ([]byte, error) {\n\tsignature, err := sm2.Sign(caPri, userId, cinfo.Raw)\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\treturn CreateCertificate(cinfo, signature)\n}\n\nfunc CreateCertificate(cinfo *TBSCertificate, signature []byte) ([]byte, error) {\n\tvar sigAlgo pkix.AlgorithmIdentifier\n\tsigAlgo.Algorithm = oidSignatureSM3WithSM2\n\treturn asn1.Marshal(certificate{\n\t\tnil,\n\t\t*cinfo,\n\t\tsigAlgo,\n\t\tasn1.BitString{Bytes: signature, BitLength: len(signature) * 8},\n\t})\n}\n\n// ParseCertificate parses a single certificate from the given ASN.1 DER data.\nfunc ParseCertificate(asn1Data []byte) (*x509.Certificate, error) {\n\tvar cert certificate\n\trest, err := asn1.Unmarshal(asn1Data, &cert)\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\tif len(rest) > 0 {\n\t\treturn nil, asn1.SyntaxError{Msg: \"trailing data\"}\n\t}\n\n\treturn parseCertificate(&cert)\n}\n\nfunc parseCertificate(in *certificate) (*x509.Certificate, error) {\n\tout := new(x509.Certificate)\n\tout.Raw = in.Raw\n\tout.RawTBSCertificate = in.TBSCertificate.Raw\n\tout.RawSubjectPublicKeyInfo = in.TBSCertificate.PublicKey.Raw\n\tout.RawSubject = in.TBSCertificate.Subject.FullBytes\n\tout.RawIssuer = in.TBSCertificate.Issuer.FullBytes\n\n\tout.Signature = in.SignatureValue.RightAlign()\n\tout.SignatureAlgorithm = 0\n\tout.PublicKeyAlgorithm = 0\n\n\tif !oidSignatureSM3WithSM2.Equal(in.SignatureAlgorithm.Algorithm) {\n\t\treturn nil, errors.New(\"x509: illegal signature algorithm OID\")\n\t}\n\tif !oidPublicKeyECDSA.Equal(in.TBSCertificate.PublicKey.Algorithm.Algorithm) {\n\t\treturn nil, errors.New(\"x509: illegal publick key algorithm OID\")\n\t}\n\n\tvar err error\n\tout.PublicKey, err = parsePublicKey(&in.TBSCertificate.PublicKey)\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\n\tout.Version = in.TBSCertificate.Version + 1\n\tout.SerialNumber = in.TBSCertificate.SerialNumber\n\n\tvar issuer, subject pkix.RDNSequence\n\tif rest, err := asn1.Unmarshal(in.TBSCertificate.Subject.FullBytes, &subject); err != nil {\n\t\treturn nil, err\n\t} else if len(rest) != 0 {\n\t\treturn nil, errors.New(\"x509: trailing data after X.509 subject\")\n\t}\n\tif rest, err := asn1.Unmarshal(in.TBSCertificate.Issuer.FullBytes, &issuer); err != nil {\n\t\treturn nil, err\n\t} else if len(rest) != 0 {\n\t\treturn nil, errors.New(\"x509: trailing data after X.509 subject\")\n\t}\n\n\tout.Issuer.FillFromRDNSequence(&issuer)\n\tout.Subject.FillFromRDNSequence(&subject)\n\n\tout.NotBefore = in.TBSCertificate.Validity.NotBefore\n\tout.NotAfter = in.TBSCertificate.Validity.NotAfter\n\n\tfor _, e := range in.TBSCertificate.Extensions {\n\t\tout.Extensions = append(out.Extensions, e)\n\t\tunhandled := false\n\n\t\tif len(e.Id) == 4 && e.Id[0] == 2 && e.Id[1] == 5 && e.Id[2] == 29 {\n\t\t\tswitch e.Id[3] {\n\t\t\tcase 15:\n\t\t\t\t// RFC 5280, 4.2.1.3\n\t\t\t\tvar usageBits asn1.BitString\n\t\t\t\tif rest, err := asn1.Unmarshal(e.Value, &usageBits); err != nil {\n\t\t\t\t\treturn nil, err\n\t\t\t\t} else if len(rest) != 0 {\n\t\t\t\t\treturn nil, errors.New(\"x509: trailing data after X.509 KeyUsage\")\n\t\t\t\t}\n\n\t\t\t\tvar usage int\n\t\t\t\tfor i := 0; i < 9; i++ {\n\t\t\t\t\tif usageBits.At(i) != 0 {\n\t\t\t\t\t\tusage |= 1 << uint(i)\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tout.KeyUsage = x509.KeyUsage(usage)\n\n\t\t\tcase 19:\n\t\t\t\t// RFC 5280, 4.2.1.9\n\t\t\t\tvar constraints basicConstraints\n\t\t\t\tif rest, err := asn1.Unmarshal(e.Value, &constraints); err != nil {\n\t\t\t\t\treturn nil, err\n\t\t\t\t} else if len(rest) != 0 {\n\t\t\t\t\treturn nil, errors.New(\"x509: trailing data after X.509 BasicConstraints\")\n\t\t\t\t}\n\n\t\t\t\tout.BasicConstraintsValid = true\n\t\t\t\tout.IsCA = constraints.IsCA\n\t\t\t\tout.MaxPathLen = constraints.MaxPathLen\n\t\t\t\tout.MaxPathLenZero = out.MaxPathLen == 0\n\t\t\t\t// TODO: map out.MaxPathLen to 0 if it has the -1 default value? (Issue 19285)\n\t\t\tcase 17:\n\t\t\t\tout.DNSNames, out.EmailAddresses, out.IPAddresses, out.URIs, err = parseSANExtension(e.Value)\n\t\t\t\tif err != nil {\n\t\t\t\t\treturn nil, err\n\t\t\t\t}\n\n\t\t\t\tif len(out.DNSNames) == 0 && len(out.EmailAddresses) == 0 && len(out.IPAddresses) == 0 && len(out.URIs) == 0 {\n\t\t\t\t\t// If we didn't parse anything then we do the critical check, below.\n\t\t\t\t\tunhandled = true\n\t\t\t\t}\n\n\t\t\tcase 30:\n\t\t\t\tunhandled, err = parseNameConstraintsExtension(out, e)\n\t\t\t\tif err != nil {\n\t\t\t\t\treturn nil, err\n\t\t\t\t}\n\n\t\t\tcase 31:\n\t\t\t\t// RFC 5280, 4.2.1.13\n\n\t\t\t\t// CRLDistributionPoints ::= SEQUENCE SIZE (1..MAX) OF DistributionPoint\n\t\t\t\t//\n\t\t\t\t// DistributionPoint ::= SEQUENCE {\n\t\t\t\t//     distributionPoint       [0]     DistributionPointName OPTIONAL,\n\t\t\t\t//     reasons                 [1]     ReasonFlags OPTIONAL,\n\t\t\t\t//     cRLIssuer               [2]     GeneralNames OPTIONAL }\n\t\t\t\t//\n\t\t\t\t// DistributionPointName ::= CHOICE {\n\t\t\t\t//     fullName                [0]     GeneralNames,\n\t\t\t\t//     nameRelativeToCRLIssuer [1]     RelativeDistinguishedName }\n\n\t\t\t\tvar cdp []distributionPoint\n\t\t\t\tif rest, err := asn1.Unmarshal(e.Value, &cdp); err != nil {\n\t\t\t\t\treturn nil, err\n\t\t\t\t} else if len(rest) != 0 {\n\t\t\t\t\treturn nil, errors.New(\"x509: trailing data after X.509 CRL distribution point\")\n\t\t\t\t}\n\n\t\t\t\tfor _, dp := range cdp {\n\t\t\t\t\t// Per RFC 5280, 4.2.1.13, one of distributionPoint or cRLIssuer may be empty.\n\t\t\t\t\tif len(dp.DistributionPoint.FullName) == 0 {\n\t\t\t\t\t\tcontinue\n\t\t\t\t\t}\n\n\t\t\t\t\tfor _, fullName := range dp.DistributionPoint.FullName {\n\t\t\t\t\t\tif fullName.Tag == 6 {\n\t\t\t\t\t\t\tout.CRLDistributionPoints = append(out.CRLDistributionPoints, string(fullName.Bytes))\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\tcase 35:\n\t\t\t\t// RFC 5280, 4.2.1.1\n\t\t\t\tvar a authKeyId\n\t\t\t\tif rest, err := asn1.Unmarshal(e.Value, &a); err != nil {\n\t\t\t\t\treturn nil, err\n\t\t\t\t} else if len(rest) != 0 {\n\t\t\t\t\treturn nil, errors.New(\"x509: trailing data after X.509 authority key-id\")\n\t\t\t\t}\n\t\t\t\tout.AuthorityKeyId = a.Id\n\n\t\t\tcase 37:\n\t\t\t\t// RFC 5280, 4.2.1.12.  Extended Key Usage\n\n\t\t\t\t// id-ce-extKeyUsage OBJECT IDENTIFIER ::= { id-ce 37 }\n\t\t\t\t//\n\t\t\t\t// ExtKeyUsageSyntax ::= SEQUENCE SIZE (1..MAX) OF KeyPurposeId\n\t\t\t\t//\n\t\t\t\t// KeyPurposeId ::= OBJECT IDENTIFIER\n\n\t\t\t\tvar keyUsage []asn1.ObjectIdentifier\n\t\t\t\tif rest, err := asn1.Unmarshal(e.Value, &keyUsage); err != nil {\n\t\t\t\t\treturn nil, err\n\t\t\t\t} else if len(rest) != 0 {\n\t\t\t\t\treturn nil, errors.New(\"x509: trailing data after X.509 ExtendedKeyUsage\")\n\t\t\t\t}\n\n\t\t\t\tfor _, u := range keyUsage {\n\t\t\t\t\tif extKeyUsage, ok := extKeyUsageFromOID(u); ok {\n\t\t\t\t\t\tout.ExtKeyUsage = append(out.ExtKeyUsage, extKeyUsage)\n\t\t\t\t\t} else {\n\t\t\t\t\t\tout.UnknownExtKeyUsage = append(out.UnknownExtKeyUsage, u)\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\tcase 14:\n\t\t\t\t// RFC 5280, 4.2.1.2\n\t\t\t\tvar keyid []byte\n\t\t\t\tif rest, err := asn1.Unmarshal(e.Value, &keyid); err != nil {\n\t\t\t\t\treturn nil, err\n\t\t\t\t} else if len(rest) != 0 {\n\t\t\t\t\treturn nil, errors.New(\"x509: trailing data after X.509 key-id\")\n\t\t\t\t}\n\t\t\t\tout.SubjectKeyId = keyid\n\n\t\t\tcase 32:\n\t\t\t\t// RFC 5280 4.2.1.4: Certificate Policies\n\t\t\t\tvar policies []policyInformation\n\t\t\t\tif rest, err := asn1.Unmarshal(e.Value, &policies); err != nil {\n\t\t\t\t\treturn nil, err\n\t\t\t\t} else if len(rest) != 0 {\n\t\t\t\t\treturn nil, errors.New(\"x509: trailing data after X.509 certificate policies\")\n\t\t\t\t}\n\t\t\t\tout.PolicyIdentifiers = make([]asn1.ObjectIdentifier, len(policies))\n\t\t\t\tfor i, policy := range policies {\n\t\t\t\t\tout.PolicyIdentifiers[i] = policy.Policy\n\t\t\t\t}\n\n\t\t\tdefault:\n\t\t\t\t// Unknown extensions are recorded if critical.\n\t\t\t\tunhandled = true\n\t\t\t}\n\t\t} else if e.Id.Equal(oidExtensionAuthorityInfoAccess) {\n\t\t\t// RFC 5280 4.2.2.1: Authority Information Access\n\t\t\tvar aia []authorityInfoAccess\n\t\t\tif rest, err := asn1.Unmarshal(e.Value, &aia); err != nil {\n\t\t\t\treturn nil, err\n\t\t\t} else if len(rest) != 0 {\n\t\t\t\treturn nil, errors.New(\"x509: trailing data after X.509 authority information\")\n\t\t\t}\n\n\t\t\tfor _, v := range aia {\n\t\t\t\t// GeneralName: uniformResourceIdentifier [6] IA5String\n\t\t\t\tif v.Location.Tag != 6 {\n\t\t\t\t\tcontinue\n\t\t\t\t}\n\t\t\t\tif v.Method.Equal(oidAuthorityInfoAccessOcsp) {\n\t\t\t\t\tout.OCSPServer = append(out.OCSPServer, string(v.Location.Bytes))\n\t\t\t\t} else if v.Method.Equal(oidAuthorityInfoAccessIssuers) {\n\t\t\t\t\tout.IssuingCertificateURL = append(out.IssuingCertificateURL, string(v.Location.Bytes))\n\t\t\t\t}\n\t\t\t}\n\t\t} else {\n\t\t\t// Unknown extensions are recorded if critical.\n\t\t\tunhandled = true\n\t\t}\n\n\t\tif e.Critical && unhandled {\n\t\t\tout.UnhandledCriticalExtensions = append(out.UnhandledCriticalExtensions, e.Id)\n\t\t}\n\t}\n\n\treturn out, nil\n}\n\nfunc parseNameConstraintsExtension(out *x509.Certificate, e pkix.Extension) (unhandled bool, err error) {\n\t// RFC 5280, 4.2.1.10\n\n\t// NameConstraints ::= SEQUENCE {\n\t//      permittedSubtrees       [0]     GeneralSubtrees OPTIONAL,\n\t//      excludedSubtrees        [1]     GeneralSubtrees OPTIONAL }\n\t//\n\t// GeneralSubtrees ::= SEQUENCE SIZE (1..MAX) OF GeneralSubtree\n\t//\n\t// GeneralSubtree ::= SEQUENCE {\n\t//      base                    GeneralName,\n\t//      minimum         [0]     BaseDistance DEFAULT 0,\n\t//      maximum         [1]     BaseDistance OPTIONAL }\n\t//\n\t// BaseDistance ::= INTEGER (0..MAX)\n\n\touter := cryptobyte.String(e.Value)\n\tvar toplevel, permitted, excluded cryptobyte.String\n\tvar havePermitted, haveExcluded bool\n\tif !outer.ReadASN1(&toplevel, cryptobyte_asn1.SEQUENCE) ||\n\t\t!outer.Empty() ||\n\t\t!toplevel.ReadOptionalASN1(&permitted, &havePermitted, cryptobyte_asn1.Tag(0).ContextSpecific().Constructed()) ||\n\t\t!toplevel.ReadOptionalASN1(&excluded, &haveExcluded, cryptobyte_asn1.Tag(1).ContextSpecific().Constructed()) ||\n\t\t!toplevel.Empty() {\n\t\treturn false, errors.New(\"x509: invalid NameConstraints extension\")\n\t}\n\n\tif !havePermitted && !haveExcluded || len(permitted) == 0 && len(excluded) == 0 {\n\t\t// https://tools.ietf.org/html/rfc5280#section-4.2.1.10:\n\t\t//   “either the permittedSubtrees field\n\t\t//   or the excludedSubtrees MUST be\n\t\t//   present”\n\t\treturn false, errors.New(\"x509: empty name constraints extension\")\n\t}\n\n\tgetValues := func(subtrees cryptobyte.String) (dnsNames []string, ips []*net.IPNet, emails, uriDomains []string, err error) {\n\t\tfor !subtrees.Empty() {\n\t\t\tvar seq, value cryptobyte.String\n\t\t\tvar tag cryptobyte_asn1.Tag\n\t\t\tif !subtrees.ReadASN1(&seq, cryptobyte_asn1.SEQUENCE) ||\n\t\t\t\t!seq.ReadAnyASN1(&value, &tag) {\n\t\t\t\treturn nil, nil, nil, nil, fmt.Errorf(\"x509: invalid NameConstraints extension\")\n\t\t\t}\n\n\t\t\tvar (\n\t\t\t\tdnsTag   = cryptobyte_asn1.Tag(2).ContextSpecific()\n\t\t\t\temailTag = cryptobyte_asn1.Tag(1).ContextSpecific()\n\t\t\t\tipTag    = cryptobyte_asn1.Tag(7).ContextSpecific()\n\t\t\t\turiTag   = cryptobyte_asn1.Tag(6).ContextSpecific()\n\t\t\t)\n\n\t\t\tswitch tag {\n\t\t\tcase dnsTag:\n\t\t\t\tdomain := string(value)\n\t\t\t\tif err := isIA5String(domain); err != nil {\n\t\t\t\t\treturn nil, nil, nil, nil, errors.New(\"x509: invalid constraint value: \" + err.Error())\n\t\t\t\t}\n\n\t\t\t\ttrimmedDomain := domain\n\t\t\t\tif len(trimmedDomain) > 0 && trimmedDomain[0] == '.' {\n\t\t\t\t\t// constraints can have a leading\n\t\t\t\t\t// period to exclude the domain\n\t\t\t\t\t// itself, but that's not valid in a\n\t\t\t\t\t// normal domain name.\n\t\t\t\t\ttrimmedDomain = trimmedDomain[1:]\n\t\t\t\t}\n\t\t\t\tif _, ok := domainToReverseLabels(trimmedDomain); !ok {\n\t\t\t\t\treturn nil, nil, nil, nil, fmt.Errorf(\"x509: failed to parse dnsName constraint %q\", domain)\n\t\t\t\t}\n\t\t\t\tdnsNames = append(dnsNames, domain)\n\n\t\t\tcase ipTag:\n\t\t\t\tl := len(value)\n\t\t\t\tvar ip, mask []byte\n\n\t\t\t\tswitch l {\n\t\t\t\tcase 8:\n\t\t\t\t\tip = value[:4]\n\t\t\t\t\tmask = value[4:]\n\n\t\t\t\tcase 32:\n\t\t\t\t\tip = value[:16]\n\t\t\t\t\tmask = value[16:]\n\n\t\t\t\tdefault:\n\t\t\t\t\treturn nil, nil, nil, nil, fmt.Errorf(\"x509: IP constraint contained value of length %d\", l)\n\t\t\t\t}\n\n\t\t\t\tif !isValidIPMask(mask) {\n\t\t\t\t\treturn nil, nil, nil, nil, fmt.Errorf(\"x509: IP constraint contained invalid mask %x\", mask)\n\t\t\t\t}\n\n\t\t\t\tips = append(ips, &net.IPNet{IP: net.IP(ip), Mask: net.IPMask(mask)})\n\n\t\t\tcase emailTag:\n\t\t\t\tconstraint := string(value)\n\t\t\t\tif err := isIA5String(constraint); err != nil {\n\t\t\t\t\treturn nil, nil, nil, nil, errors.New(\"x509: invalid constraint value: \" + err.Error())\n\t\t\t\t}\n\n\t\t\t\t// If the constraint contains an @ then\n\t\t\t\t// it specifies an exact mailbox name.\n\t\t\t\tif strings.Contains(constraint, \"@\") {\n\t\t\t\t\tif _, ok := parseRFC2821Mailbox(constraint); !ok {\n\t\t\t\t\t\treturn nil, nil, nil, nil, fmt.Errorf(\"x509: failed to parse rfc822Name constraint %q\", constraint)\n\t\t\t\t\t}\n\t\t\t\t} else {\n\t\t\t\t\t// Otherwise it's a domain name.\n\t\t\t\t\tdomain := constraint\n\t\t\t\t\tif len(domain) > 0 && domain[0] == '.' {\n\t\t\t\t\t\tdomain = domain[1:]\n\t\t\t\t\t}\n\t\t\t\t\tif _, ok := domainToReverseLabels(domain); !ok {\n\t\t\t\t\t\treturn nil, nil, nil, nil, fmt.Errorf(\"x509: failed to parse rfc822Name constraint %q\", constraint)\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\temails = append(emails, constraint)\n\n\t\t\tcase uriTag:\n\t\t\t\tdomain := string(value)\n\t\t\t\tif err := isIA5String(domain); err != nil {\n\t\t\t\t\treturn nil, nil, nil, nil, errors.New(\"x509: invalid constraint value: \" + err.Error())\n\t\t\t\t}\n\n\t\t\t\tif net.ParseIP(domain) != nil {\n\t\t\t\t\treturn nil, nil, nil, nil, fmt.Errorf(\"x509: failed to parse URI constraint %q: cannot be IP address\", domain)\n\t\t\t\t}\n\n\t\t\t\ttrimmedDomain := domain\n\t\t\t\tif len(trimmedDomain) > 0 && trimmedDomain[0] == '.' {\n\t\t\t\t\t// constraints can have a leading\n\t\t\t\t\t// period to exclude the domain itself,\n\t\t\t\t\t// but that's not valid in a normal\n\t\t\t\t\t// domain name.\n\t\t\t\t\ttrimmedDomain = trimmedDomain[1:]\n\t\t\t\t}\n\t\t\t\tif _, ok := domainToReverseLabels(trimmedDomain); !ok {\n\t\t\t\t\treturn nil, nil, nil, nil, fmt.Errorf(\"x509: failed to parse URI constraint %q\", domain)\n\t\t\t\t}\n\t\t\t\turiDomains = append(uriDomains, domain)\n\n\t\t\tdefault:\n\t\t\t\tunhandled = true\n\t\t\t}\n\t\t}\n\n\t\treturn dnsNames, ips, emails, uriDomains, nil\n\t}\n\n\tif out.PermittedDNSDomains, out.PermittedIPRanges, out.PermittedEmailAddresses, out.PermittedURIDomains, err = getValues(permitted); err != nil {\n\t\treturn false, err\n\t}\n\tif out.ExcludedDNSDomains, out.ExcludedIPRanges, out.ExcludedEmailAddresses, out.ExcludedURIDomains, err = getValues(excluded); err != nil {\n\t\treturn false, err\n\t}\n\tout.PermittedDNSDomainsCritical = e.Critical\n\n\treturn unhandled, nil\n}\n\n// isValidIPMask returns true iff mask consists of zero or more 1 bits, followed by zero bits.\nfunc isValidIPMask(mask []byte) bool {\n\tseenZero := false\n\n\tfor _, b := range mask {\n\t\tif seenZero {\n\t\t\tif b != 0 {\n\t\t\t\treturn false\n\t\t\t}\n\n\t\t\tcontinue\n\t\t}\n\n\t\tswitch b {\n\t\tcase 0x00, 0x80, 0xc0, 0xe0, 0xf0, 0xf8, 0xfc, 0xfe:\n\t\t\tseenZero = true\n\t\tcase 0xff:\n\t\tdefault:\n\t\t\treturn false\n\t\t}\n\t}\n\n\treturn true\n}\n\n// rfc2821Mailbox represents a “mailbox” (which is an email address to most\n// people) by breaking it into the “local” (i.e. before the '@') and “domain”\n// parts.\ntype rfc2821Mailbox struct {\n\tlocal, domain string\n}\n\n// parseRFC2821Mailbox parses an email address into local and domain parts,\n// based on the ABNF for a “Mailbox” from RFC 2821. According to\n// https://tools.ietf.org/html/rfc5280#section-4.2.1.6 that's correct for an\n// rfc822Name from a certificate: “The format of an rfc822Name is a \"Mailbox\"\n// as defined in https://tools.ietf.org/html/rfc2821#section-4.1.2”.\nfunc parseRFC2821Mailbox(in string) (mailbox rfc2821Mailbox, ok bool) {\n\tif len(in) == 0 {\n\t\treturn mailbox, false\n\t}\n\n\tlocalPartBytes := make([]byte, 0, len(in)/2)\n\n\tif in[0] == '\"' {\n\t\t// Quoted-string = DQUOTE *qcontent DQUOTE\n\t\t// non-whitespace-control = %d1-8 / %d11 / %d12 / %d14-31 / %d127\n\t\t// qcontent = qtext / quoted-pair\n\t\t// qtext = non-whitespace-control /\n\t\t//         %d33 / %d35-91 / %d93-126\n\t\t// quoted-pair = (\"\\\" text) / obs-qp\n\t\t// text = %d1-9 / %d11 / %d12 / %d14-127 / obs-text\n\t\t//\n\t\t// (Names beginning with “obs-” are the obsolete syntax from\n\t\t// https://tools.ietf.org/html/rfc2822#section-4. Since it has\n\t\t// been 16 years, we no longer accept that.)\n\t\tin = in[1:]\n\tQuotedString:\n\t\tfor {\n\t\t\tif len(in) == 0 {\n\t\t\t\treturn mailbox, false\n\t\t\t}\n\t\t\tc := in[0]\n\t\t\tin = in[1:]\n\n\t\t\tswitch {\n\t\t\tcase c == '\"':\n\t\t\t\tbreak QuotedString\n\n\t\t\tcase c == '\\\\':\n\t\t\t\t// quoted-pair\n\t\t\t\tif len(in) == 0 {\n\t\t\t\t\treturn mailbox, false\n\t\t\t\t}\n\t\t\t\tif in[0] == 11 ||\n\t\t\t\t\tin[0] == 12 ||\n\t\t\t\t\t(1 <= in[0] && in[0] <= 9) ||\n\t\t\t\t\t(14 <= in[0] && in[0] <= 127) {\n\t\t\t\t\tlocalPartBytes = append(localPartBytes, in[0])\n\t\t\t\t\tin = in[1:]\n\t\t\t\t} else {\n\t\t\t\t\treturn mailbox, false\n\t\t\t\t}\n\n\t\t\tcase c == 11 ||\n\t\t\t\tc == 12 ||\n\t\t\t\t// Space (char 32) is not allowed based on the\n\t\t\t\t// BNF, but RFC 3696 gives an example that\n\t\t\t\t// assumes that it is. Several “verified”\n\t\t\t\t// errata continue to argue about this point.\n\t\t\t\t// We choose to accept it.\n\t\t\t\tc == 32 ||\n\t\t\t\tc == 33 ||\n\t\t\t\tc == 127 ||\n\t\t\t\t(1 <= c && c <= 8) ||\n\t\t\t\t(14 <= c && c <= 31) ||\n\t\t\t\t(35 <= c && c <= 91) ||\n\t\t\t\t(93 <= c && c <= 126):\n\t\t\t\t// qtext\n\t\t\t\tlocalPartBytes = append(localPartBytes, c)\n\n\t\t\tdefault:\n\t\t\t\treturn mailbox, false\n\t\t\t}\n\t\t}\n\t} else {\n\t\t// Atom (\".\" Atom)*\n\tNextChar:\n\t\tfor len(in) > 0 {\n\t\t\t// atext from https://tools.ietf.org/html/rfc2822#section-3.2.4\n\t\t\tc := in[0]\n\n\t\t\tswitch {\n\t\t\tcase c == '\\\\':\n\t\t\t\t// Examples given in RFC 3696 suggest that\n\t\t\t\t// escaped characters can appear outside of a\n\t\t\t\t// quoted string. Several “verified” errata\n\t\t\t\t// continue to argue the point. We choose to\n\t\t\t\t// accept it.\n\t\t\t\tin = in[1:]\n\t\t\t\tif len(in) == 0 {\n\t\t\t\t\treturn mailbox, false\n\t\t\t\t}\n\t\t\t\tfallthrough\n\n\t\t\tcase ('0' <= c && c <= '9') ||\n\t\t\t\t('a' <= c && c <= 'z') ||\n\t\t\t\t('A' <= c && c <= 'Z') ||\n\t\t\t\tc == '!' || c == '#' || c == '$' || c == '%' ||\n\t\t\t\tc == '&' || c == '\\'' || c == '*' || c == '+' ||\n\t\t\t\tc == '-' || c == '/' || c == '=' || c == '?' ||\n\t\t\t\tc == '^' || c == '_' || c == '`' || c == '{' ||\n\t\t\t\tc == '|' || c == '}' || c == '~' || c == '.':\n\t\t\t\tlocalPartBytes = append(localPartBytes, in[0])\n\t\t\t\tin = in[1:]\n\n\t\t\tdefault:\n\t\t\t\tbreak NextChar\n\t\t\t}\n\t\t}\n\n\t\tif len(localPartBytes) == 0 {\n\t\t\treturn mailbox, false\n\t\t}\n\n\t\t// https://tools.ietf.org/html/rfc3696#section-3\n\t\t// “period (\".\") may also appear, but may not be used to start\n\t\t// or end the local part, nor may two or more consecutive\n\t\t// periods appear.”\n\t\ttwoDots := []byte{'.', '.'}\n\t\tif localPartBytes[0] == '.' ||\n\t\t\tlocalPartBytes[len(localPartBytes)-1] == '.' ||\n\t\t\tbytes.Contains(localPartBytes, twoDots) {\n\t\t\treturn mailbox, false\n\t\t}\n\t}\n\n\tif len(in) == 0 || in[0] != '@' {\n\t\treturn mailbox, false\n\t}\n\tin = in[1:]\n\n\t// The RFC species a format for domains, but that's known to be\n\t// violated in practice so we accept that anything after an '@' is the\n\t// domain part.\n\tif _, ok := domainToReverseLabels(in); !ok {\n\t\treturn mailbox, false\n\t}\n\n\tmailbox.local = string(localPartBytes)\n\tmailbox.domain = in\n\treturn mailbox, true\n}\n\nfunc extKeyUsageFromOID(oid asn1.ObjectIdentifier) (eku x509.ExtKeyUsage, ok bool) {\n\tfor _, pair := range extKeyUsageOIDs {\n\t\tif oid.Equal(pair.oid) {\n\t\t\treturn pair.extKeyUsage, true\n\t\t}\n\t}\n\treturn\n}\n"
  },
  {
    "path": "sm2/cert/gmx509_test.go",
    "content": "package cert\n\nimport (\n\t\"bytes\"\n\t\"crypto/rand\"\n\t\"crypto/x509\"\n\t\"crypto/x509/pkix\"\n\t\"encoding/asn1\"\n\t\"fmt\"\n\t\"io/ioutil\"\n\t\"math/big\"\n\t\"testing\"\n\t\"time\"\n\n\t\"github.com/ZZMarquis/gm/sm2\"\n)\n\nfunc TestX500Name(t *testing.T) {\n\tname := new(pkix.Name)\n\tname.CommonName = \"ID=Mock Root CA\"\n\tname.Country = []string{\"CN\"}\n\tname.Province = []string{\"Beijing\"}\n\tname.Locality = []string{\"Beijing\"}\n\tname.Organization = []string{\"org.zz\"}\n\tname.OrganizationalUnit = []string{\"org.zz\"}\n\tfmt.Println(name.String())\n}\n\nfunc TestCreateCertificateRequest(t *testing.T) {\n\tpri, pub, err := sm2.GenerateKey(rand.Reader)\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\n\tsanContents, err := marshalSANs([]string{\"foo.example.com\"}, nil, nil, nil)\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\n\ttemplate := x509.CertificateRequest{\n\t\tSubject: pkix.Name{\n\t\t\tCommonName:   \"test.example.com\",\n\t\t\tOrganization: []string{\"Σ Acme Co\"},\n\t\t},\n\t\tDNSNames: []string{\"test.example.com\"},\n\n\t\t// An explicit extension should override the DNSNames from the\n\t\t// template.\n\t\tExtraExtensions: []pkix.Extension{\n\t\t\t{\n\t\t\t\tId:    oidExtensionSubjectAltName,\n\t\t\t\tValue: sanContents,\n\t\t\t},\n\t\t},\n\t}\n\n\tderBytes, err := CreateCertificateRequest(&template, pub, pri, nil)\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\tioutil.WriteFile(\"sample.csr\", derBytes, 0644)\n\n\tcsr, err := ParseCertificateRequest(derBytes)\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\tcsrPub := csr.PublicKey.(*sm2.PublicKey)\n\tif !bytes.Equal(pub.GetUnCompressBytes(), csrPub.GetUnCompressBytes()) {\n\t\tt.Fatal(\"public key not equals\")\n\t}\n\n\tb, err := VerifyDERCSRSign(derBytes, nil)\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\tif !b {\n\t\tt.Fatal(\"Verify CSR sign not pass\")\n\t}\n}\n\nfunc TestCreateCertificate(t *testing.T) {\n\tpri, pub, err := sm2.GenerateKey(rand.Reader)\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\n\tsanContents, err := marshalSANs([]string{\"foo.example.com\"}, nil, nil, nil)\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\n\ttemplate := x509.CertificateRequest{\n\t\tSubject: pkix.Name{\n\t\t\tCommonName:   \"test.example.com\",\n\t\t\tOrganization: []string{\"Σ Acme Co\"},\n\t\t},\n\t\tDNSNames: []string{\"test.example.com\"},\n\n\t\t// An explicit extension should override the DNSNames from the\n\t\t// template.\n\t\tExtraExtensions: []pkix.Extension{\n\t\t\t{\n\t\t\t\tId:    oidExtensionSubjectAltName,\n\t\t\t\tValue: sanContents,\n\t\t\t},\n\t\t},\n\t}\n\n\tderBytes, err := CreateCertificateRequest(&template, pub, pri, nil)\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\n\tcsr, err := ParseCertificateRequest(derBytes)\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\n\ttestExtKeyUsage := []x509.ExtKeyUsage{x509.ExtKeyUsageClientAuth, x509.ExtKeyUsageServerAuth}\n\ttestUnknownExtKeyUsage := []asn1.ObjectIdentifier{[]int{1, 2, 3}, []int{2, 59, 1}}\n\tcerTemplate := x509.Certificate{\n\t\t// SerialNumber is negative to ensure that negative\n\t\t// values are parsed. This is due to the prevalence of\n\t\t// buggy code that produces certificates with negative\n\t\t// serial numbers.\n\t\tSerialNumber: big.NewInt(-1),\n\t\tNotBefore:    time.Now(),\n\t\tNotAfter:     time.Unix(time.Now().Unix()+100000000, 0),\n\n\t\tSubjectKeyId: []byte{1, 2, 3, 4},\n\t\tKeyUsage:     x509.KeyUsageCertSign,\n\n\t\tExtKeyUsage:        testExtKeyUsage,\n\t\tUnknownExtKeyUsage: testUnknownExtKeyUsage,\n\n\t\tBasicConstraintsValid: true,\n\t\tIsCA:                  true,\n\n\t\tOCSPServer:            []string{\"http://ocsp.example.com\"},\n\t\tIssuingCertificateURL: []string{\"http://crt.example.com/ca1.crt\"},\n\n\t\tPolicyIdentifiers: []asn1.ObjectIdentifier{[]int{1, 2, 3}},\n\n\t\tCRLDistributionPoints: []string{\"http://crl1.example.com/ca1.crl\", \"http://crl2.example.com/ca1.crl\"},\n\t}\n\n\tFillCertificateTemplateByCSR(&cerTemplate, csr)\n\n\tcinfo, err := CreateCertificateInfo(&cerTemplate, &cerTemplate, csr)\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\n\tsign, err := sm2.Sign(pri, nil, cinfo.Raw)\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\n\tcer, err := CreateCertificate(cinfo, sign)\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\tioutil.WriteFile(\"sample.cer\", cer, 0644)\n\n\tcertificate, err := ParseCertificate(cer)\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\tfmt.Println(certificate.DNSNames)\n}\n"
  },
  {
    "path": "sm2/keyexchange.go",
    "content": "package sm2\n\nimport (\n\t\"bytes\"\n\t\"encoding/binary\"\n\t\"errors\"\n\t\"github.com/ZZMarquis/gm/sm3\"\n\t\"github.com/ZZMarquis/gm/util\"\n\t\"hash\"\n\t\"math/big\"\n)\n\ntype ExchangeResult struct {\n\tKey []byte\n\tS1  []byte\n\tS2  []byte\n}\n\nfunc reduce(x *big.Int, w int) *big.Int {\n\tintOne := new(big.Int).SetInt64(1)\n\tresult := util.Lsh(intOne, uint(w))\n\tresult = util.Sub(result, intOne)\n\tresult = util.And(x, result)\n\tresult = util.SetBit(result, w, 1)\n\treturn result\n}\n\nfunc calculateU(w int, selfStaticPriv *PrivateKey, selfEphemeralPriv *PrivateKey, selfEphemeralPub *PublicKey,\n\totherStaticPub *PublicKey, otherEphemeralPub *PublicKey) (x *big.Int, y *big.Int) {\n\tx1 := reduce(selfEphemeralPub.X, w)\n\tx2 := reduce(otherEphemeralPub.X, w)\n\ttA := util.Mul(x1, selfEphemeralPriv.D)\n\ttA = util.Add(selfStaticPriv.D, tA)\n\tk1 := util.Mul(sm2H, tA)\n\tk1 = util.Mod(k1, selfStaticPriv.Curve.N)\n\tk2 := util.Mul(k1, x2)\n\tk2 = util.Mod(k2, selfStaticPriv.Curve.N)\n\n\tp1x, p1y := selfStaticPriv.Curve.ScalarMult(otherStaticPub.X, otherStaticPub.Y, k1.Bytes())\n\tp2x, p2y := selfStaticPriv.Curve.ScalarMult(otherEphemeralPub.X, otherEphemeralPub.Y, k2.Bytes())\n\tx, y = selfStaticPriv.Curve.Add(p1x, p1y, p2x, p2y)\n\treturn\n}\n\nfunc kdfForExch(digest hash.Hash, ux, uy *big.Int, za, zb []byte, keyBits int) []byte {\n\tbufSize := 4\n\tif bufSize < digest.BlockSize() {\n\t\tbufSize = digest.BlockSize()\n\t}\n\tbuf := make([]byte, bufSize)\n\n\trv := make([]byte, (keyBits+7)/8)\n\trvLen := len(rv)\n\tuxBytes := ux.Bytes()\n\tuyBytes := uy.Bytes()\n\toff := 0\n\tct := uint32(0)\n\tfor off < rvLen {\n\t\tdigest.Reset()\n\t\tdigest.Write(uxBytes)\n\t\tdigest.Write(uyBytes)\n\t\tdigest.Write(za)\n\t\tdigest.Write(zb)\n\t\tct++\n\t\tbinary.BigEndian.PutUint32(buf, ct)\n\t\tdigest.Write(buf[:4])\n\t\ttmp := digest.Sum(nil)\n\t\tcopy(buf[:bufSize], tmp[:bufSize])\n\n\t\tcopyLen := rvLen - off\n\t\tcopy(rv[off:off+copyLen], buf[:copyLen])\n\t\toff += copyLen\n\t}\n\treturn rv\n}\n\nfunc calculateInnerHash(digest hash.Hash, ux *big.Int, za, zb []byte, p1x, p1y *big.Int, p2x, p2y *big.Int) []byte {\n\tdigest.Reset()\n\tdigest.Write(ux.Bytes())\n\tdigest.Write(za)\n\tdigest.Write(zb)\n\tdigest.Write(p1x.Bytes())\n\tdigest.Write(p1y.Bytes())\n\tdigest.Write(p2x.Bytes())\n\tdigest.Write(p2y.Bytes())\n\treturn digest.Sum(nil)\n}\n\nfunc s1(digest hash.Hash, uy *big.Int, innerHash []byte) []byte {\n\tdigest.Reset()\n\tdigest.Write([]byte{0x02})\n\tdigest.Write(uy.Bytes())\n\tdigest.Write(innerHash)\n\treturn digest.Sum(nil)\n}\n\nfunc s2(digest hash.Hash, uy *big.Int, innerHash []byte) []byte {\n\tdigest.Reset()\n\tdigest.Write([]byte{0x03})\n\tdigest.Write(uy.Bytes())\n\tdigest.Write(innerHash)\n\treturn digest.Sum(nil)\n}\n\nfunc CalculateKeyWithConfirmation(initiator bool, keyBits int, confirmationTag []byte,\n\tselfStaticPriv *PrivateKey, selfEphemeralPriv *PrivateKey, selfId []byte,\n\totherStaticPub *PublicKey, otherEphemeralPub *PublicKey, otherId []byte) (*ExchangeResult, error) {\n\tif selfId == nil {\n\t\tselfId = make([]byte, 0)\n\t}\n\tif otherId == nil {\n\t\totherId = make([]byte, 0)\n\t}\n\tif initiator && confirmationTag == nil {\n\t\treturn nil, errors.New(\"if initiating, confirmationTag must be set\")\n\t}\n\n\tselfStaticPub := CalculatePubKey(selfStaticPriv)\n\tdigest := sm3.New()\n\tza := getZ(digest, &selfStaticPriv.Curve, selfStaticPub.X, selfStaticPub.Y, selfId)\n\tzb := getZ(digest, &selfStaticPriv.Curve, otherStaticPub.X, otherStaticPub.Y, otherId)\n\n\tw := selfStaticPriv.Curve.BitSize/2 - 1\n\tselfEphemeralPub := CalculatePubKey(selfEphemeralPriv)\n\tux, uy := calculateU(w, selfStaticPriv, selfEphemeralPriv, selfEphemeralPub, otherStaticPub, otherEphemeralPub)\n\tif initiator {\n\t\trv := kdfForExch(digest, ux, uy, za, zb, keyBits)\n\t\tinnerHash := calculateInnerHash(digest, ux, za, zb, selfEphemeralPub.X, selfEphemeralPub.Y,\n\t\t\totherEphemeralPub.X, otherEphemeralPub.Y)\n\t\ts1 := s1(digest, uy, innerHash)\n\t\tif !bytes.Equal(s1, confirmationTag) {\n\t\t\treturn nil, errors.New(\"confirmation tag mismatch\")\n\t\t}\n\t\ts2 := s2(digest, uy, innerHash)\n\t\treturn &ExchangeResult{Key: rv, S2: s2}, nil\n\t} else {\n\t\trv := kdfForExch(digest, ux, uy, zb, za, keyBits)\n\t\tinnerHash := calculateInnerHash(digest, ux, zb, za, otherEphemeralPub.X, otherEphemeralPub.Y,\n\t\t\tselfEphemeralPub.X, selfEphemeralPub.Y)\n\t\ts1 := s1(digest, uy, innerHash)\n\t\ts2 := s2(digest, uy, innerHash)\n\t\treturn &ExchangeResult{Key: rv, S1: s1, S2: s2}, nil\n\t}\n}\n\nfunc ResponderConfirm(responderS2 []byte, initiatorS2 []byte) bool {\n\treturn bytes.Equal(responderS2, initiatorS2)\n}\n"
  },
  {
    "path": "sm2/keyexchange_test.go",
    "content": "package sm2\n\nimport (\n\t\"crypto/rand\"\n\t\"testing\"\n)\n\nconst (\n\tKeyBits = 128\n)\n\nvar (\n\tinitiatorId = []byte(\"ABCDEFG1234\")\n\tresponderId = []byte(\"1234567ABCD\")\n)\n\nfunc TestSM2KeyExchange(t *testing.T) {\n\tinitiatorStaticPriv, initiatorStaticPub, _ := GenerateKey(rand.Reader)\n\tinitiatorEphemeralPriv, initiatorEphemeralPub, _ := GenerateKey(rand.Reader)\n\tresponderStaticPriv, responderStaticPub, _ := GenerateKey(rand.Reader)\n\tresponderEphemeralPriv, responderEphemeralPub, _ := GenerateKey(rand.Reader)\n\n\tresponderResult, err := CalculateKeyWithConfirmation(false, KeyBits, nil,\n\t\tresponderStaticPriv, responderEphemeralPriv, responderId,\n\t\tinitiatorStaticPub, initiatorEphemeralPub, initiatorId)\n\tif err != nil {\n\t\tt.Error(err.Error())\n\t\treturn\n\t}\n\n\tinitiatorResult, err := CalculateKeyWithConfirmation(true, KeyBits, responderResult.S1,\n\t\tinitiatorStaticPriv, initiatorEphemeralPriv, initiatorId,\n\t\tresponderStaticPub, responderEphemeralPub, responderId)\n\tif err != nil {\n\t\tt.Error(err.Error())\n\t\treturn\n\t}\n\n\tif !ResponderConfirm(responderResult.S2, initiatorResult.S2) {\n\t\tt.Error(\"responder confirm s2 failed\")\n\t\treturn\n\t}\n}\n"
  },
  {
    "path": "sm2/sm2.go",
    "content": "package sm2\n\nimport (\n\t\"bytes\"\n\t\"crypto/elliptic\"\n\t\"crypto/rand\"\n\t\"encoding/asn1\"\n\t\"encoding/binary\"\n\t\"errors\"\n\t\"fmt\"\n\t\"hash\"\n\t\"io\"\n\t\"math/big\"\n\n\t\"github.com/ZZMarquis/gm/sm3\"\n\t\"github.com/ZZMarquis/gm/util\"\n)\n\nconst (\n\tBitSize    = 256\n\tKeyBytes   = (BitSize + 7) / 8\n\tUnCompress = 0x04\n)\n\ntype Sm2CipherTextType int32\n\nconst (\n\t// 旧标准的密文顺序\n\tC1C2C3 Sm2CipherTextType = 1\n\t// [GM/T 0009-2012]标准规定的顺序\n\tC1C3C2 Sm2CipherTextType = 2\n)\n\nvar (\n\tsm2H                 = new(big.Int).SetInt64(1)\n\tsm2SignDefaultUserId = []byte{\n\t\t0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38,\n\t\t0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38}\n)\n\nvar sm2P256V1 P256V1Curve\n\ntype P256V1Curve struct {\n\t*elliptic.CurveParams\n\tA *big.Int\n}\n\ntype PublicKey struct {\n\tX, Y  *big.Int\n\tCurve P256V1Curve\n}\n\ntype PrivateKey struct {\n\tD     *big.Int\n\tCurve P256V1Curve\n}\n\ntype sm2Signature struct {\n\tR, S *big.Int\n}\n\ntype sm2CipherC1C3C2 struct {\n\tX, Y *big.Int\n\tC3   []byte\n\tC2   []byte\n}\n\ntype sm2CipherC1C2C3 struct {\n\tX, Y *big.Int\n\tC2   []byte\n\tC3   []byte\n}\n\nfunc init() {\n\tinitSm2P256V1()\n}\n\nfunc initSm2P256V1() {\n\tsm2P, _ := new(big.Int).SetString(\"FFFFFFFEFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF00000000FFFFFFFFFFFFFFFF\", 16)\n\tsm2A, _ := new(big.Int).SetString(\"FFFFFFFEFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF00000000FFFFFFFFFFFFFFFC\", 16)\n\tsm2B, _ := new(big.Int).SetString(\"28E9FA9E9D9F5E344D5A9E4BCF6509A7F39789F515AB8F92DDBCBD414D940E93\", 16)\n\tsm2N, _ := new(big.Int).SetString(\"FFFFFFFEFFFFFFFFFFFFFFFFFFFFFFFF7203DF6B21C6052B53BBF40939D54123\", 16)\n\tsm2Gx, _ := new(big.Int).SetString(\"32C4AE2C1F1981195F9904466A39C9948FE30BBFF2660BE1715A4589334C74C7\", 16)\n\tsm2Gy, _ := new(big.Int).SetString(\"BC3736A2F4F6779C59BDCEE36B692153D0A9877CC62A474002DF32E52139F0A0\", 16)\n\tsm2P256V1.CurveParams = &elliptic.CurveParams{Name: \"SM2-P-256-V1\"}\n\tsm2P256V1.P = sm2P\n\tsm2P256V1.A = sm2A\n\tsm2P256V1.B = sm2B\n\tsm2P256V1.N = sm2N\n\tsm2P256V1.Gx = sm2Gx\n\tsm2P256V1.Gy = sm2Gy\n\tsm2P256V1.BitSize = BitSize\n}\n\nfunc GetSm2P256V1() P256V1Curve {\n\treturn sm2P256V1\n}\n\nfunc GenerateKey(rand io.Reader) (*PrivateKey, *PublicKey, error) {\n\tpriv, x, y, err := elliptic.GenerateKey(sm2P256V1, rand)\n\tif err != nil {\n\t\treturn nil, nil, err\n\t}\n\tprivateKey := new(PrivateKey)\n\tprivateKey.Curve = sm2P256V1\n\tprivateKey.D = new(big.Int).SetBytes(priv)\n\tpublicKey := new(PublicKey)\n\tpublicKey.Curve = sm2P256V1\n\tpublicKey.X = x\n\tpublicKey.Y = y\n\treturn privateKey, publicKey, nil\n}\n\nfunc RawBytesToPublicKey(bytes []byte) (*PublicKey, error) {\n\tif len(bytes) != KeyBytes*2 {\n\t\treturn nil, errors.New(fmt.Sprintf(\"Public key raw bytes length must be %d\", KeyBytes*2))\n\t}\n\tpublicKey := new(PublicKey)\n\tpublicKey.Curve = sm2P256V1\n\tpublicKey.X = new(big.Int).SetBytes(bytes[:KeyBytes])\n\tpublicKey.Y = new(big.Int).SetBytes(bytes[KeyBytes:])\n\treturn publicKey, nil\n}\n\nfunc RawBytesToPrivateKey(bytes []byte) (*PrivateKey, error) {\n\tif len(bytes) != KeyBytes {\n\t\treturn nil, errors.New(fmt.Sprintf(\"Private key raw bytes length must be %d\", KeyBytes))\n\t}\n\tprivateKey := new(PrivateKey)\n\tprivateKey.Curve = sm2P256V1\n\tprivateKey.D = new(big.Int).SetBytes(bytes)\n\treturn privateKey, nil\n}\n\nfunc (pub *PublicKey) GetUnCompressBytes() []byte {\n\txBytes := bigIntTo32Bytes(pub.X)\n\tyBytes := bigIntTo32Bytes(pub.Y)\n\txl := len(xBytes)\n\tyl := len(yBytes)\n\n\traw := make([]byte, 1+KeyBytes*2)\n\traw[0] = UnCompress\n\tif xl > KeyBytes {\n\t\tcopy(raw[1:1+KeyBytes], xBytes[xl-KeyBytes:])\n\t} else if xl < KeyBytes {\n\t\tcopy(raw[1+(KeyBytes-xl):1+KeyBytes], xBytes)\n\t} else {\n\t\tcopy(raw[1:1+KeyBytes], xBytes)\n\t}\n\n\tif yl > KeyBytes {\n\t\tcopy(raw[1+KeyBytes:], yBytes[yl-KeyBytes:])\n\t} else if yl < KeyBytes {\n\t\tcopy(raw[1+KeyBytes+(KeyBytes-yl):], yBytes)\n\t} else {\n\t\tcopy(raw[1+KeyBytes:], yBytes)\n\t}\n\treturn raw\n}\n\nfunc (pub *PublicKey) GetRawBytes() []byte {\n\traw := pub.GetUnCompressBytes()\n\treturn raw[1:]\n}\n\nfunc (pri *PrivateKey) GetRawBytes() []byte {\n\tdBytes := bigIntTo32Bytes(pri.D)\n\tdl := len(dBytes)\n\tif dl > KeyBytes {\n\t\traw := make([]byte, KeyBytes)\n\t\tcopy(raw, dBytes[dl-KeyBytes:])\n\t\treturn raw\n\t} else if dl < KeyBytes {\n\t\traw := make([]byte, KeyBytes)\n\t\tcopy(raw[KeyBytes-dl:], dBytes)\n\t\treturn raw\n\t} else {\n\t\treturn dBytes\n\t}\n}\n\nfunc CalculatePubKey(priv *PrivateKey) *PublicKey {\n\tpub := new(PublicKey)\n\tpub.Curve = priv.Curve\n\tpub.X, pub.Y = priv.Curve.ScalarBaseMult(priv.D.Bytes())\n\treturn pub\n}\n\nfunc nextK(rnd io.Reader, max *big.Int) (*big.Int, error) {\n\tintOne := new(big.Int).SetInt64(1)\n\tvar k *big.Int\n\tvar err error\n\tfor {\n\t\tk, err = rand.Int(rnd, max)\n\t\tif err != nil {\n\t\t\treturn nil, err\n\t\t}\n\t\tif k.Cmp(intOne) >= 0 {\n\t\t\treturn k, err\n\t\t}\n\t}\n}\n\nfunc xor(data []byte, kdfOut []byte, dRemaining int) {\n\tfor i := 0; i != dRemaining; i++ {\n\t\tdata[i] ^= kdfOut[i]\n\t}\n}\n\n// 表示SM2 Key的大数比较小时，直接通过Bytes()函数得到的字节数组可能不够32字节，这个时候要补齐成32字节\nfunc bigIntTo32Bytes(bn *big.Int) []byte {\n\tbyteArr := bn.Bytes()\n\tbyteArrLen := len(byteArr)\n\tif byteArrLen == KeyBytes {\n\t\treturn byteArr\n\t}\n\tbyteArr = append(make([]byte, KeyBytes-byteArrLen), byteArr...)\n\treturn byteArr\n}\n\nfunc kdf(digest hash.Hash, c1x *big.Int, c1y *big.Int, encData []byte) {\n\tbufSize := 4\n\tif bufSize < digest.Size() {\n\t\tbufSize = digest.Size()\n\t}\n\tbuf := make([]byte, bufSize)\n\n\tencDataLen := len(encData)\n\tc1xBytes := bigIntTo32Bytes(c1x)\n\tc1yBytes := bigIntTo32Bytes(c1y)\n\toff := 0\n\tct := uint32(0)\n\tfor off < encDataLen {\n\t\tdigest.Reset()\n\t\tdigest.Write(c1xBytes)\n\t\tdigest.Write(c1yBytes)\n\t\tct++\n\t\tbinary.BigEndian.PutUint32(buf, ct)\n\t\tdigest.Write(buf[:4])\n\t\ttmp := digest.Sum(nil)\n\t\tcopy(buf[:bufSize], tmp[:bufSize])\n\n\t\txorLen := encDataLen - off\n\t\tif xorLen > digest.Size() {\n\t\t\txorLen = digest.Size()\n\t\t}\n\t\txor(encData[off:], buf, xorLen)\n\t\toff += xorLen\n\t}\n}\n\nfunc notEncrypted(encData []byte, in []byte) bool {\n\tencDataLen := len(encData)\n\tfor i := 0; i != encDataLen; i++ {\n\t\tif encData[i] != in[i] {\n\t\t\treturn false\n\t\t}\n\t}\n\treturn true\n}\n\nfunc Encrypt(pub *PublicKey, in []byte, cipherTextType Sm2CipherTextType) ([]byte, error) {\n\tc2 := make([]byte, len(in))\n\tcopy(c2, in)\n\tvar c1 []byte\n\tdigest := sm3.New()\n\tvar kPBx, kPBy *big.Int\n\tfor {\n\t\tk, err := nextK(rand.Reader, pub.Curve.N)\n\t\tif err != nil {\n\t\t\treturn nil, err\n\t\t}\n\t\tkBytes := k.Bytes()\n\t\tc1x, c1y := pub.Curve.ScalarBaseMult(kBytes)\n\t\tc1 = elliptic.Marshal(pub.Curve, c1x, c1y)\n\t\tkPBx, kPBy = pub.Curve.ScalarMult(pub.X, pub.Y, kBytes)\n\t\tkdf(digest, kPBx, kPBy, c2)\n\n\t\tif !notEncrypted(c2, in) {\n\t\t\tbreak\n\t\t}\n\t}\n\n\tdigest.Reset()\n\tdigest.Write(bigIntTo32Bytes(kPBx))\n\tdigest.Write(in)\n\tdigest.Write(bigIntTo32Bytes(kPBy))\n\tc3 := digest.Sum(nil)\n\n\tc1Len := len(c1)\n\tc2Len := len(c2)\n\tc3Len := len(c3)\n\tresult := make([]byte, c1Len+c2Len+c3Len)\n\tif cipherTextType == C1C2C3 {\n\t\tcopy(result[:c1Len], c1)\n\t\tcopy(result[c1Len:c1Len+c2Len], c2)\n\t\tcopy(result[c1Len+c2Len:], c3)\n\t} else if cipherTextType == C1C3C2 {\n\t\tcopy(result[:c1Len], c1)\n\t\tcopy(result[c1Len:c1Len+c3Len], c3)\n\t\tcopy(result[c1Len+c3Len:], c2)\n\t} else {\n\t\treturn nil, errors.New(\"unknown cipherTextType:\" + string(cipherTextType))\n\t}\n\treturn result, nil\n}\n\nfunc Decrypt(priv *PrivateKey, in []byte, cipherTextType Sm2CipherTextType) ([]byte, error) {\n\tc1Len := ((priv.Curve.BitSize+7)>>3)*2 + 1\n\tc1 := make([]byte, c1Len)\n\tcopy(c1, in[:c1Len])\n\tc1x, c1y := elliptic.Unmarshal(priv.Curve, c1)\n\tsx, sy := priv.Curve.ScalarMult(c1x, c1y, sm2H.Bytes())\n\tif util.IsEcPointInfinity(sx, sy) {\n\t\treturn nil, errors.New(\"[h]C1 at infinity\")\n\t}\n\tc1x, c1y = priv.Curve.ScalarMult(c1x, c1y, priv.D.Bytes())\n\n\tdigest := sm3.New()\n\tc3Len := digest.Size()\n\tc2Len := len(in) - c1Len - c3Len\n\tc2 := make([]byte, c2Len)\n\tc3 := make([]byte, c3Len)\n\tif cipherTextType == C1C2C3 {\n\t\tcopy(c2, in[c1Len:c1Len+c2Len])\n\t\tcopy(c3, in[c1Len+c2Len:])\n\t} else if cipherTextType == C1C3C2 {\n\t\tcopy(c3, in[c1Len:c1Len+c3Len])\n\t\tcopy(c2, in[c1Len+c3Len:])\n\t} else {\n\t\treturn nil, errors.New(\"unknown cipherTextType:\" + string(cipherTextType))\n\t}\n\n\tkdf(digest, c1x, c1y, c2)\n\n\tdigest.Reset()\n\tdigest.Write(bigIntTo32Bytes(c1x))\n\tdigest.Write(c2)\n\tdigest.Write(bigIntTo32Bytes(c1y))\n\tnewC3 := digest.Sum(nil)\n\n\tif !bytes.Equal(newC3, c3) {\n\t\treturn nil, errors.New(\"invalid cipher text\")\n\t}\n\treturn c2, nil\n}\n\nfunc MarshalCipher(in []byte, cipherTextType Sm2CipherTextType) ([]byte, error) {\n\tbyteLen := (sm2P256V1.Params().BitSize + 7) >> 3\n\tc1x := make([]byte, byteLen)\n\tc1y := make([]byte, byteLen)\n\tc2Len := len(in) - (1 + byteLen*2) - sm3.DigestLength\n\tc2 := make([]byte, c2Len)\n\tc3 := make([]byte, sm3.DigestLength)\n\tpos := 1\n\n\tcopy(c1x, in[pos:pos+byteLen])\n\tpos += byteLen\n\tcopy(c1y, in[pos:pos+byteLen])\n\tpos += byteLen\n\tnc1x := new(big.Int).SetBytes(c1x)\n\tnc1y := new(big.Int).SetBytes(c1y)\n\n\tif cipherTextType == C1C2C3 {\n\t\tcopy(c2, in[pos:pos+c2Len])\n\t\tpos += c2Len\n\t\tcopy(c3, in[pos:pos+sm3.DigestLength])\n\t\tresult, err := asn1.Marshal(sm2CipherC1C2C3{nc1x, nc1y, c2, c3})\n\t\tif err != nil {\n\t\t\treturn nil, err\n\t\t}\n\t\treturn result, nil\n\t} else if cipherTextType == C1C3C2 {\n\t\tcopy(c3, in[pos:pos+sm3.DigestLength])\n\t\tpos += sm3.DigestLength\n\t\tcopy(c2, in[pos:pos+c2Len])\n\t\tresult, err := asn1.Marshal(sm2CipherC1C3C2{nc1x, nc1y, c3, c2})\n\t\tif err != nil {\n\t\t\treturn nil, err\n\t\t}\n\t\treturn result, nil\n\t} else {\n\t\treturn nil, errors.New(\"unknown cipherTextType:\" + string(cipherTextType))\n\t}\n}\n\nfunc UnmarshalCipher(in []byte, cipherTextType Sm2CipherTextType) (out []byte, err error) {\n\tif cipherTextType == C1C2C3 {\n\t\tcipher := new(sm2CipherC1C2C3)\n\t\t_, err = asn1.Unmarshal(in, cipher)\n\t\tif err != nil {\n\t\t\treturn nil, err\n\t\t}\n\t\tc1xBytes := bigIntTo32Bytes(cipher.X)\n\t\tc1yBytes := bigIntTo32Bytes(cipher.Y)\n\t\tc1xLen := len(c1xBytes)\n\t\tc1yLen := len(c1yBytes)\n\t\tc2Len := len(cipher.C2)\n\t\tc3Len := len(cipher.C3)\n\t\tresult := make([]byte, 1+c1xLen+c1yLen+c2Len+c3Len)\n\t\tpos := 0\n\t\tresult[pos] = UnCompress\n\t\tpos += 1\n\t\tcopy(result[pos:pos+c1xLen], c1xBytes)\n\t\tpos += c1xLen\n\t\tcopy(result[pos:pos+c1yLen], c1yBytes)\n\t\tpos += c1yLen\n\t\tcopy(result[pos:pos+c2Len], cipher.C2)\n\t\tpos += c2Len\n\t\tcopy(result[pos:pos+c3Len], cipher.C3)\n\t\treturn result, nil\n\t} else if cipherTextType == C1C3C2 {\n\t\tcipher := new(sm2CipherC1C3C2)\n\t\t_, err = asn1.Unmarshal(in, cipher)\n\t\tif err != nil {\n\t\t\treturn nil, err\n\t\t}\n\t\tc1xBytes := bigIntTo32Bytes(cipher.X)\n\t\tc1yBytes := bigIntTo32Bytes(cipher.Y)\n\t\tc1xLen := len(c1xBytes)\n\t\tc1yLen := len(c1yBytes)\n\t\tc2Len := len(cipher.C2)\n\t\tc3Len := len(cipher.C3)\n\t\tresult := make([]byte, 1+c1xLen+c1yLen+c2Len+c3Len)\n\t\tpos := 0\n\t\tresult[pos] = UnCompress\n\t\tpos += 1\n\t\tcopy(result[pos:pos+c1xLen], c1xBytes)\n\t\tpos += c1xLen\n\t\tcopy(result[pos:pos+c1yLen], c1yBytes)\n\t\tpos += c1yLen\n\t\tcopy(result[pos:pos+c3Len], cipher.C3)\n\t\tpos += c3Len\n\t\tcopy(result[pos:pos+c2Len], cipher.C2)\n\t\treturn result, nil\n\t} else {\n\t\treturn nil, errors.New(\"unknown cipherTextType:\" + string(cipherTextType))\n\t}\n}\n\nfunc getZ(digest hash.Hash, curve *P256V1Curve, pubX *big.Int, pubY *big.Int, userId []byte) []byte {\n\tdigest.Reset()\n\n\tuserIdLen := uint16(len(userId) * 8)\n\tvar userIdLenBytes [2]byte\n\tbinary.BigEndian.PutUint16(userIdLenBytes[:], userIdLen)\n\tdigest.Write(userIdLenBytes[:])\n\tif userId != nil && len(userId) > 0 {\n\t\tdigest.Write(userId)\n\t}\n\n\tdigest.Write(bigIntTo32Bytes(curve.A))\n\tdigest.Write(bigIntTo32Bytes(curve.B))\n\tdigest.Write(bigIntTo32Bytes(curve.Gx))\n\tdigest.Write(bigIntTo32Bytes(curve.Gy))\n\tdigest.Write(bigIntTo32Bytes(pubX))\n\tdigest.Write(bigIntTo32Bytes(pubY))\n\treturn digest.Sum(nil)\n}\n\nfunc calculateE(digest hash.Hash, curve *P256V1Curve, pubX *big.Int, pubY *big.Int, userId []byte, src []byte) *big.Int {\n\tz := getZ(digest, curve, pubX, pubY, userId)\n\n\tdigest.Reset()\n\tdigest.Write(z)\n\tdigest.Write(src)\n\teHash := digest.Sum(nil)\n\treturn new(big.Int).SetBytes(eHash)\n}\n\nfunc MarshalSign(r, s *big.Int) ([]byte, error) {\n\tresult, err := asn1.Marshal(sm2Signature{r, s})\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\treturn result, nil\n}\n\nfunc UnmarshalSign(sign []byte) (r, s *big.Int, err error) {\n\tsm2Sign := new(sm2Signature)\n\t_, err = asn1.Unmarshal(sign, sm2Sign)\n\tif err != nil {\n\t\treturn nil, nil, err\n\t}\n\treturn sm2Sign.R, sm2Sign.S, nil\n}\n\nfunc SignToRS(priv *PrivateKey, userId []byte, in []byte) (r, s *big.Int, err error) {\n\tdigest := sm3.New()\n\tpubX, pubY := priv.Curve.ScalarBaseMult(priv.D.Bytes())\n\tif userId == nil {\n\t\tuserId = sm2SignDefaultUserId\n\t}\n\te := calculateE(digest, &priv.Curve, pubX, pubY, userId, in)\n\n\tintZero := new(big.Int).SetInt64(0)\n\tintOne := new(big.Int).SetInt64(1)\n\tfor {\n\t\tvar k *big.Int\n\t\tvar err error\n\t\tfor {\n\t\t\tk, err = nextK(rand.Reader, priv.Curve.N)\n\t\t\tif err != nil {\n\t\t\t\treturn nil, nil, err\n\t\t\t}\n\t\t\tpx, _ := priv.Curve.ScalarBaseMult(k.Bytes())\n\t\t\tr = util.Add(e, px)\n\t\t\tr = util.Mod(r, priv.Curve.N)\n\n\t\t\trk := new(big.Int).Set(r)\n\t\t\trk = rk.Add(rk, k)\n\t\t\tif r.Cmp(intZero) != 0 && rk.Cmp(priv.Curve.N) != 0 {\n\t\t\t\tbreak\n\t\t\t}\n\t\t}\n\n\t\tdPlus1ModN := util.Add(priv.D, intOne)\n\t\tdPlus1ModN = util.ModInverse(dPlus1ModN, priv.Curve.N)\n\t\ts = util.Mul(r, priv.D)\n\t\ts = util.Sub(k, s)\n\t\ts = util.Mod(s, priv.Curve.N)\n\t\ts = util.Mul(dPlus1ModN, s)\n\t\ts = util.Mod(s, priv.Curve.N)\n\n\t\tif s.Cmp(intZero) != 0 {\n\t\t\tbreak\n\t\t}\n\t}\n\n\treturn r, s, nil\n}\n\n// 签名结果为DER编码的字节数组\nfunc Sign(priv *PrivateKey, userId []byte, in []byte) ([]byte, error) {\n\tr, s, err := SignToRS(priv, userId, in)\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\n\treturn MarshalSign(r, s)\n}\n\nfunc VerifyByRS(pub *PublicKey, userId []byte, src []byte, r, s *big.Int) bool {\n\tintOne := new(big.Int).SetInt64(1)\n\tif r.Cmp(intOne) == -1 || r.Cmp(pub.Curve.N) >= 0 {\n\t\treturn false\n\t}\n\tif s.Cmp(intOne) == -1 || s.Cmp(pub.Curve.N) >= 0 {\n\t\treturn false\n\t}\n\n\tdigest := sm3.New()\n\tif userId == nil {\n\t\tuserId = sm2SignDefaultUserId\n\t}\n\te := calculateE(digest, &pub.Curve, pub.X, pub.Y, userId, src)\n\n\tintZero := new(big.Int).SetInt64(0)\n\tt := util.Add(r, s)\n\tt = util.Mod(t, pub.Curve.N)\n\tif t.Cmp(intZero) == 0 {\n\t\treturn false\n\t}\n\n\tsgx, sgy := pub.Curve.ScalarBaseMult(s.Bytes())\n\ttpx, tpy := pub.Curve.ScalarMult(pub.X, pub.Y, t.Bytes())\n\tx, y := pub.Curve.Add(sgx, sgy, tpx, tpy)\n\tif util.IsEcPointInfinity(x, y) {\n\t\treturn false\n\t}\n\n\texpectedR := util.Add(e, x)\n\texpectedR = util.Mod(expectedR, pub.Curve.N)\n\treturn expectedR.Cmp(r) == 0\n}\n\n// 输入签名须为DER编码的字节数组\nfunc Verify(pub *PublicKey, userId []byte, src []byte, sign []byte) bool {\n\tr, s, err := UnmarshalSign(sign)\n\tif err != nil {\n\t\treturn false\n\t}\n\n\treturn VerifyByRS(pub, userId, src, r, s)\n}\n"
  },
  {
    "path": "sm2/sm2_loop_test.go",
    "content": "package sm2\n\nimport (\n\t\"crypto/rand\"\n\t\"encoding/hex\"\n\t\"fmt\"\n\t\"math/big\"\n\t\"testing\"\n)\n\nconst loopCount = 10\n\nvar loopTestSignData = []testSm2SignData{\n\t{\n\t\td:  \"5DD701828C424B84C5D56770ECF7C4FE882E654CAC53C7CC89A66B1709068B9D\",\n\t\tx:  \"FF6712D3A7FC0D1B9E01FF471A87EA87525E47C7775039D19304E554DEFE0913\",\n\t\ty:  \"F632025F692776D4C13470ECA36AC85D560E794E1BCCF53D82C015988E0EB956\",\n\t\tin: \"0102030405060708010203040506070801020304050607080102030405060708010203040506070801020304050607080102030405060708010203040506070830450220213C6CD6EBD6A4D5C2D0AB38E29D441836D1457A8118D34864C247D727831962022100D9248480342AC8513CCDF0F89A2250DC8F6EB4F2471E144E9A812E0AF497F801\",\n\t},\n}\n\nfunc TestSignVerifyLoop(t *testing.T) {\n\tpriv := new(PrivateKey)\n\tpriv.Curve = GetSm2P256V1()\n\tdBytes, _ := hex.DecodeString(loopTestSignData[0].d)\n\tpriv.D = new(big.Int).SetBytes(dBytes)\n\n\tpub := new(PublicKey)\n\tpub.Curve = GetSm2P256V1()\n\txBytes, _ := hex.DecodeString(loopTestSignData[0].x)\n\tyBytes, _ := hex.DecodeString(loopTestSignData[0].y)\n\tpub.X = new(big.Int).SetBytes(xBytes)\n\tpub.Y = new(big.Int).SetBytes(yBytes)\n\n\tfor i := 0; i < loopCount; i++ {\n\t\tinBytes, _ := hex.DecodeString(loopTestSignData[0].in)\n\t\tsign, err := Sign(priv, nil, inBytes)\n\t\tif err != nil {\n\t\t\tt.Error(err.Error())\n\t\t\tbreak\n\t\t}\n\n\t\tresult := Verify(pub, nil, inBytes, sign)\n\t\tif !result {\n\t\t\tt.Error(\"verify failed\")\n\t\t\tbreak\n\t\t}\n\n\t\tfmt.Printf(\"%d pass\\n\", i)\n\t}\n}\n\nfunc TestSignVerifyLoop2(t *testing.T) {\n\tfor i := 0; i < loopCount; i++ {\n\t\tpriv, pub, err := GenerateKey(rand.Reader)\n\t\tif err != nil {\n\t\t\tt.Error(err.Error())\n\t\t\tbreak\n\t\t}\n\n\t\tinBytes, _ := hex.DecodeString(loopTestSignData[0].in)\n\t\tsign, err := Sign(priv, nil, inBytes)\n\t\tif err != nil {\n\t\t\tt.Error(err.Error())\n\t\t\tbreak\n\t\t}\n\n\t\tresult := Verify(pub, nil, inBytes, sign)\n\t\tif !result {\n\t\t\tt.Error(\"verify failed\")\n\t\t\tbreak\n\t\t}\n\n\t\tfmt.Printf(\"%d pass\\n\", i)\n\t}\n}\n\nfunc TestSignVerifyLoop3(t *testing.T) {\n\tpriv, pub, err := GenerateKey(rand.Reader)\n\tif err != nil {\n\t\tt.Error(err.Error())\n\t\treturn\n\t}\n\n\tfor i := 0; i < loopCount; i++ {\n\t\tinBytes, _ := hex.DecodeString(loopTestSignData[0].in)\n\t\tsign, err := Sign(priv, nil, inBytes)\n\t\tif err != nil {\n\t\t\tt.Error(err.Error())\n\t\t\tbreak\n\t\t}\n\n\t\tresult := Verify(pub, nil, inBytes, sign)\n\t\tif !result {\n\t\t\tt.Error(\"verify failed\")\n\t\t\tbreak\n\t\t}\n\n\t\tfmt.Printf(\"%d pass\\n\", i)\n\t}\n}\n"
  },
  {
    "path": "sm2/sm2_test.go",
    "content": "package sm2\n\nimport (\n\t\"bytes\"\n\t\"crypto/rand\"\n\t\"encoding/hex\"\n\t\"fmt\"\n\t\"math/big\"\n\t\"testing\"\n)\n\nfunc TestGetSm2P256V1(t *testing.T) {\n\tcurve := GetSm2P256V1()\n\tfmt.Printf(\"P:%s\\n\", curve.Params().P.Text(16))\n\tfmt.Printf(\"B:%s\\n\", curve.Params().B.Text(16))\n\tfmt.Printf(\"N:%s\\n\", curve.Params().N.Text(16))\n\tfmt.Printf(\"Gx:%s\\n\", curve.Params().Gx.Text(16))\n\tfmt.Printf(\"Gy:%s\\n\", curve.Params().Gy.Text(16))\n}\n\nfunc TestGenerateKey(t *testing.T) {\n\tpriv, pub, err := GenerateKey(rand.Reader)\n\tif err != nil {\n\t\tt.Error(err.Error())\n\t\treturn\n\t}\n\tfmt.Printf(\"priv:%s\\n\", priv.D.Text(16))\n\tfmt.Printf(\"x:%s\\n\", pub.X.Text(16))\n\tfmt.Printf(\"y:%s\\n\", pub.Y.Text(16))\n\n\tcurve := GetSm2P256V1()\n\tif !curve.IsOnCurve(pub.X, pub.Y) {\n\t\tt.Error(\"x,y is not on Curve\")\n\t\treturn\n\t}\n\tfmt.Println(\"x,y is on sm2 Curve\")\n}\n\nfunc TestEncryptDecrypt_C1C2C3(t *testing.T) {\n\tsrc := []byte{1, 2, 3, 4, 5, 6, 7, 8, 9, 10}\n\tpriv, pub, err := GenerateKey(rand.Reader)\n\tif err != nil {\n\t\tt.Error(err.Error())\n\t\treturn\n\t}\n\n\tfmt.Printf(\"d:%s\\n\", hex.EncodeToString(priv.D.Bytes()))\n\tfmt.Printf(\"x:%s\\n\", hex.EncodeToString(pub.X.Bytes()))\n\tfmt.Printf(\"y:%s\\n\", hex.EncodeToString(pub.Y.Bytes()))\n\n\tcipherText, err := Encrypt(pub, src, C1C2C3)\n\tif err != nil {\n\t\tt.Error(err.Error())\n\t\treturn\n\t}\n\tfmt.Printf(\"cipher text:%s\\n\", hex.EncodeToString(cipherText))\n\n\tplainText, err := Decrypt(priv, cipherText, C1C2C3)\n\tif err != nil {\n\t\tt.Error(err.Error())\n\t\treturn\n\t}\n\tfmt.Printf(\"plain text:%s\\n\", hex.EncodeToString(plainText))\n\n\tif !bytes.Equal(plainText, src) {\n\t\tt.Error(\"decrypt result not equal expected\")\n\t\treturn\n\t}\n}\n\nfunc TestEncryptDecrypt_C1C3C2(t *testing.T) {\n\tsrc := []byte{1, 2, 3, 4, 5, 6, 7, 8, 9, 10}\n\tpriv, pub, err := GenerateKey(rand.Reader)\n\tif err != nil {\n\t\tt.Error(err.Error())\n\t\treturn\n\t}\n\n\tfmt.Printf(\"d:%s\\n\", hex.EncodeToString(priv.D.Bytes()))\n\tfmt.Printf(\"x:%s\\n\", hex.EncodeToString(pub.X.Bytes()))\n\tfmt.Printf(\"y:%s\\n\", hex.EncodeToString(pub.Y.Bytes()))\n\n\tcipherText, err := Encrypt(pub, src, C1C3C2)\n\tif err != nil {\n\t\tt.Error(err.Error())\n\t\treturn\n\t}\n\tfmt.Printf(\"cipher text:%s\\n\", hex.EncodeToString(cipherText))\n\n\tplainText, err := Decrypt(priv, cipherText, C1C3C2)\n\tif err != nil {\n\t\tt.Error(err.Error())\n\t\treturn\n\t}\n\tfmt.Printf(\"plain text:%s\\n\", hex.EncodeToString(plainText))\n\n\tif !bytes.Equal(plainText, src) {\n\t\tt.Error(\"decrypt result not equal expected\")\n\t\treturn\n\t}\n}\n\nfunc TestCipherDerEncode_C1C2C3(t *testing.T) {\n\tsrc := []byte{1, 2, 3, 4, 5, 6, 7, 8, 9, 10}\n\tpriv, pub, err := GenerateKey(rand.Reader)\n\tif err != nil {\n\t\tt.Error(err.Error())\n\t\treturn\n\t}\n\n\tcipherText, err := Encrypt(pub, src, C1C2C3)\n\tif err != nil {\n\t\tt.Error(err.Error())\n\t\treturn\n\t}\n\tfmt.Printf(\"before DER encode, cipher text:%s\\n\", hex.EncodeToString(cipherText))\n\n\tderCipher, err := MarshalCipher(cipherText, C1C2C3)\n\tif err != nil {\n\t\tt.Error(err.Error())\n\t\treturn\n\t}\n\t//err = ioutil.WriteFile(\"derCipher.dat\", derCipher, 0644)\n\t//if err != nil {\n\t//\tt.Error(err.Error())\n\t//\treturn\n\t//}\n\tcipherText, err = UnmarshalCipher(derCipher, C1C2C3)\n\tif err != nil {\n\t\tt.Error(err.Error())\n\t\treturn\n\t}\n\tfmt.Printf(\"after DER decode, cipher text:%s\\n\", hex.EncodeToString(cipherText))\n\n\tplainText, err := Decrypt(priv, cipherText, C1C2C3)\n\tif err != nil {\n\t\tt.Error(err.Error())\n\t\treturn\n\t}\n\tfmt.Printf(\"plain text:%s\\n\", hex.EncodeToString(plainText))\n\n\tif !bytes.Equal(plainText, src) {\n\t\tt.Error(\"decrypt result not equal expected\")\n\t\treturn\n\t}\n}\n\nfunc TestCipherDerEncode_C1C3C2(t *testing.T) {\n\tsrc := []byte{1, 2, 3, 4, 5, 6, 7, 8, 9, 10}\n\tpriv, pub, err := GenerateKey(rand.Reader)\n\tif err != nil {\n\t\tt.Error(err.Error())\n\t\treturn\n\t}\n\n\tcipherText, err := Encrypt(pub, src, C1C3C2)\n\tif err != nil {\n\t\tt.Error(err.Error())\n\t\treturn\n\t}\n\tfmt.Printf(\"before DER encode, cipher text:%s\\n\", hex.EncodeToString(cipherText))\n\n\tderCipher, err := MarshalCipher(cipherText, C1C3C2)\n\tif err != nil {\n\t\tt.Error(err.Error())\n\t\treturn\n\t}\n\t//err = ioutil.WriteFile(\"derCipher.dat\", derCipher, 0644)\n\t//if err != nil {\n\t//\tt.Error(err.Error())\n\t//\treturn\n\t//}\n\tcipherText, err = UnmarshalCipher(derCipher, C1C3C2)\n\tif err != nil {\n\t\tt.Error(err.Error())\n\t\treturn\n\t}\n\tfmt.Printf(\"after DER decode, cipher text:%s\\n\", hex.EncodeToString(cipherText))\n\n\tplainText, err := Decrypt(priv, cipherText, C1C3C2)\n\tif err != nil {\n\t\tt.Error(err.Error())\n\t\treturn\n\t}\n\tfmt.Printf(\"plain text:%s\\n\", hex.EncodeToString(plainText))\n\n\tif !bytes.Equal(plainText, src) {\n\t\tt.Error(\"decrypt result not equal expected\")\n\t\treturn\n\t}\n}\n\ntype testSm2SignData struct {\n\td    string\n\tx    string\n\ty    string\n\tin   string\n\tsign string\n}\n\nvar testSignData = []testSm2SignData{\n\t{\n\t\td:    \"5DD701828C424B84C5D56770ECF7C4FE882E654CAC53C7CC89A66B1709068B9D\",\n\t\tx:    \"FF6712D3A7FC0D1B9E01FF471A87EA87525E47C7775039D19304E554DEFE0913\",\n\t\ty:    \"F632025F692776D4C13470ECA36AC85D560E794E1BCCF53D82C015988E0EB956\",\n\t\tin:   \"0102030405060708010203040506070801020304050607080102030405060708\",\n\t\tsign: \"30450220213C6CD6EBD6A4D5C2D0AB38E29D441836D1457A8118D34864C247D727831962022100D9248480342AC8513CCDF0F89A2250DC8F6EB4F2471E144E9A812E0AF497F801\",\n\t},\n}\n\nfunc TestSign(t *testing.T) {\n\tfor _, data := range testSignData {\n\t\tpriv := new(PrivateKey)\n\t\tpriv.Curve = GetSm2P256V1()\n\t\tdBytes, _ := hex.DecodeString(data.d)\n\t\tpriv.D = new(big.Int).SetBytes(dBytes)\n\t\tinBytes, _ := hex.DecodeString(data.in)\n\t\tsign, err := Sign(priv, nil, inBytes)\n\t\tif err != nil {\n\t\t\tt.Error(err.Error())\n\t\t\treturn\n\t\t}\n\t\tfmt.Printf(\"sign:%s\\n\", hex.EncodeToString(sign))\n\n\t\tpub := new(PublicKey)\n\t\tpub.Curve = GetSm2P256V1()\n\t\txBytes, _ := hex.DecodeString(data.x)\n\t\tyBytes, _ := hex.DecodeString(data.y)\n\t\tpub.X = new(big.Int).SetBytes(xBytes)\n\t\tpub.Y = new(big.Int).SetBytes(yBytes)\n\t\tresult := Verify(pub, nil, inBytes, sign)\n\t\tif !result {\n\t\t\tt.Error(\"verify failed\")\n\t\t\treturn\n\t\t}\n\t}\n}\n\nfunc TestVerify(t *testing.T) {\n\tfor _, data := range testSignData {\n\t\tpub := new(PublicKey)\n\t\tpub.Curve = GetSm2P256V1()\n\t\txBytes, _ := hex.DecodeString(data.x)\n\t\tyBytes, _ := hex.DecodeString(data.y)\n\t\tpub.X = new(big.Int).SetBytes(xBytes)\n\t\tpub.Y = new(big.Int).SetBytes(yBytes)\n\t\tinBytes, _ := hex.DecodeString(data.in)\n\t\tsign, _ := hex.DecodeString(data.sign)\n\t\tresult := Verify(pub, nil, inBytes, sign)\n\t\tif !result {\n\t\t\tt.Error(\"verify failed\")\n\t\t\treturn\n\t\t}\n\t}\n}\n"
  },
  {
    "path": "sm3/sm3.go",
    "content": "package sm3\n\nimport (\n\t\"encoding/binary\"\n\t\"fmt\"\n\t\"hash\"\n\t\"math/bits\"\n)\n\nconst (\n\tDigestLength = 32\n\tBlockSize    = 16\n)\n\nvar gT = []uint32{\n\t0x79CC4519, 0xF3988A32, 0xE7311465, 0xCE6228CB, 0x9CC45197, 0x3988A32F, 0x7311465E, 0xE6228CBC,\n\t0xCC451979, 0x988A32F3, 0x311465E7, 0x6228CBCE, 0xC451979C, 0x88A32F39, 0x11465E73, 0x228CBCE6,\n\t0x9D8A7A87, 0x3B14F50F, 0x7629EA1E, 0xEC53D43C, 0xD8A7A879, 0xB14F50F3, 0x629EA1E7, 0xC53D43CE,\n\t0x8A7A879D, 0x14F50F3B, 0x29EA1E76, 0x53D43CEC, 0xA7A879D8, 0x4F50F3B1, 0x9EA1E762, 0x3D43CEC5,\n\t0x7A879D8A, 0xF50F3B14, 0xEA1E7629, 0xD43CEC53, 0xA879D8A7, 0x50F3B14F, 0xA1E7629E, 0x43CEC53D,\n\t0x879D8A7A, 0x0F3B14F5, 0x1E7629EA, 0x3CEC53D4, 0x79D8A7A8, 0xF3B14F50, 0xE7629EA1, 0xCEC53D43,\n\t0x9D8A7A87, 0x3B14F50F, 0x7629EA1E, 0xEC53D43C, 0xD8A7A879, 0xB14F50F3, 0x629EA1E7, 0xC53D43CE,\n\t0x8A7A879D, 0x14F50F3B, 0x29EA1E76, 0x53D43CEC, 0xA7A879D8, 0x4F50F3B1, 0x9EA1E762, 0x3D43CEC5}\n\ntype sm3Digest struct {\n\tv         [DigestLength / 4]uint32\n\tinWords   [BlockSize]uint32\n\txOff      int32\n\tw         [68]uint32\n\txBuf      [4]byte\n\txBufOff   int32\n\tbyteCount int64\n}\n\nfunc New() hash.Hash {\n\tdigest := new(sm3Digest)\n\tdigest.Reset()\n\treturn digest\n}\n\nfunc (digest *sm3Digest) Sum(b []byte) []byte {\n\td1 := digest\n\th := d1.checkSum()\n\treturn append(b, h[:]...)\n}\n\n// Size returns the number of bytes Sum will return.\nfunc (digest *sm3Digest) Size() int {\n\treturn DigestLength\n}\n\n// BlockSize returns the hash's underlying block size.\n// The Write method must be able to accept any amount\n// of data, but it may operate more efficiently if all writes\n// are a multiple of the block size.\nfunc (digest *sm3Digest) BlockSize() int {\n\treturn BlockSize\n}\n\nfunc (digest *sm3Digest) Reset() {\n\tdigest.byteCount = 0\n\n\tdigest.xBufOff = 0\n\tfor i := 0; i < len(digest.xBuf); i++ {\n\t\tdigest.xBuf[i] = 0\n\t}\n\n\tfor i := 0; i < len(digest.inWords); i++ {\n\t\tdigest.inWords[i] = 0\n\t}\n\n\tfor i := 0; i < len(digest.w); i++ {\n\t\tdigest.w[i] = 0\n\t}\n\n\tdigest.v[0] = 0x7380166F\n\tdigest.v[1] = 0x4914B2B9\n\tdigest.v[2] = 0x172442D7\n\tdigest.v[3] = 0xDA8A0600\n\tdigest.v[4] = 0xA96F30BC\n\tdigest.v[5] = 0x163138AA\n\tdigest.v[6] = 0xE38DEE4D\n\tdigest.v[7] = 0xB0FB0E4E\n\n\tdigest.xOff = 0\n}\n\nfunc (digest *sm3Digest) Write(p []byte) (n int, err error) {\n\t_ = p[0]\n\tinLen := len(p)\n\n\ti := 0\n\tif digest.xBufOff != 0 {\n\t\tfor i < inLen {\n\t\t\tdigest.xBuf[digest.xBufOff] = p[i]\n\t\t\tdigest.xBufOff++\n\t\t\ti++\n\t\t\tif digest.xBufOff == 4 {\n\t\t\t\tdigest.processWord(digest.xBuf[:], 0)\n\t\t\t\tdigest.xBufOff = 0\n\t\t\t\tbreak\n\t\t\t}\n\t\t}\n\t}\n\n\tlimit := ((inLen - i) & ^3) + i\n\tfor ; i < limit; i += 4 {\n\t\tdigest.processWord(p, int32(i))\n\t}\n\n\tfor i < inLen {\n\t\tdigest.xBuf[digest.xBufOff] = p[i]\n\t\tdigest.xBufOff++\n\t\ti++\n\t}\n\n\tdigest.byteCount += int64(inLen)\n\n\tn = inLen\n\treturn\n}\n\nfunc (digest *sm3Digest) finish() {\n\tbitLength := digest.byteCount << 3\n\n\tdigest.Write([]byte{128})\n\n\tfor digest.xBufOff != 0 {\n\t\tdigest.Write([]byte{0})\n\t}\n\n\tdigest.processLength(bitLength)\n\n\tdigest.processBlock()\n}\n\nfunc (digest *sm3Digest) checkSum() [DigestLength]byte {\n\tdigest.finish()\n\tvlen := len(digest.v)\n\tvar out [DigestLength]byte\n\tfor i := 0; i < vlen; i++ {\n\t\tbinary.BigEndian.PutUint32(out[i*4:(i+1)*4], digest.v[i])\n\t}\n\treturn out\n}\n\nfunc (digest *sm3Digest) processBlock() {\n\tfor j := 0; j < 16; j++ {\n\t\tdigest.w[j] = digest.inWords[j]\n\t}\n\tfor j := 16; j < 68; j++ {\n\t\twj3 := digest.w[j-3]\n\t\tr15 := (wj3 << 15) | (wj3 >> (32 - 15))\n\t\twj13 := digest.w[j-13]\n\t\tr7 := (wj13 << 7) | (wj13 >> (32 - 7))\n\t\tdigest.w[j] = p1(digest.w[j-16]^digest.w[j-9]^r15) ^ r7 ^ digest.w[j-6]\n\t}\n\n\tA := digest.v[0]\n\tB := digest.v[1]\n\tC := digest.v[2]\n\tD := digest.v[3]\n\tE := digest.v[4]\n\tF := digest.v[5]\n\tG := digest.v[6]\n\tH := digest.v[7]\n\n\tfor j := 0; j < 16; j++ {\n\t\ta12 := (A << 12) | (A >> (32 - 12))\n\t\ts1 := a12 + E + gT[j]\n\t\tSS1 := (s1 << 7) | (s1 >> (32 - 7))\n\t\tSS2 := SS1 ^ a12\n\t\tWj := digest.w[j]\n\t\tW1j := Wj ^ digest.w[j+4]\n\t\tTT1 := ff0(A, B, C) + D + SS2 + W1j\n\t\tTT2 := gg0(E, F, G) + H + SS1 + Wj\n\t\tD = C\n\t\tC = (B << 9) | (B >> (32 - 9))\n\t\tB = A\n\t\tA = TT1\n\t\tH = G\n\t\tG = (F << 19) | (F >> (32 - 19))\n\t\tF = E\n\t\tE = p0(TT2)\n\t}\n\n\tfor j := 16; j < 64; j++ {\n\t\ta12 := (A << 12) | (A >> (32 - 12))\n\t\ts1 := a12 + E + gT[j]\n\t\tSS1 := (s1 << 7) | (s1 >> (32 - 7))\n\t\tSS2 := SS1 ^ a12\n\t\tWj := digest.w[j]\n\t\tW1j := Wj ^ digest.w[j+4]\n\t\tTT1 := ff1(A, B, C) + D + SS2 + W1j\n\t\tTT2 := gg1(E, F, G) + H + SS1 + Wj\n\t\tD = C\n\t\tC = (B << 9) | (B >> (32 - 9))\n\t\tB = A\n\t\tA = TT1\n\t\tH = G\n\t\tG = (F << 19) | (F >> (32 - 19))\n\t\tF = E\n\t\tE = p0(TT2)\n\t}\n\n\tdigest.v[0] ^= A\n\tdigest.v[1] ^= B\n\tdigest.v[2] ^= C\n\tdigest.v[3] ^= D\n\tdigest.v[4] ^= E\n\tdigest.v[5] ^= F\n\tdigest.v[6] ^= G\n\tdigest.v[7] ^= H\n\n\tdigest.xOff = 0\n}\n\nfunc (digest *sm3Digest) processWord(in []byte, inOff int32) {\n\tn := binary.BigEndian.Uint32(in[inOff : inOff+4])\n\n\tdigest.inWords[digest.xOff] = n\n\tdigest.xOff++\n\n\tif digest.xOff >= 16 {\n\t\tdigest.processBlock()\n\t}\n}\n\nfunc (digest *sm3Digest) processLength(bitLength int64) {\n\tif digest.xOff > (BlockSize - 2) {\n\t\tdigest.inWords[digest.xOff] = 0\n\t\tdigest.xOff++\n\n\t\tdigest.processBlock()\n\t}\n\n\tfor ; digest.xOff < (BlockSize - 2); digest.xOff++ {\n\t\tdigest.inWords[digest.xOff] = 0\n\t}\n\n\tdigest.inWords[digest.xOff] = uint32(bitLength >> 32)\n\tdigest.xOff++\n\tdigest.inWords[digest.xOff] = uint32(bitLength)\n\tdigest.xOff++\n}\n\nfunc p0(x uint32) uint32 {\n\tr9 := bits.RotateLeft32(x, 9)\n\tr17 := bits.RotateLeft32(x, 17)\n\treturn x ^ r9 ^ r17\n}\n\nfunc p1(x uint32) uint32 {\n\tr15 := bits.RotateLeft32(x, 15)\n\tr23 := bits.RotateLeft32(x, 23)\n\treturn x ^ r15 ^ r23\n}\n\nfunc ff0(x uint32, y uint32, z uint32) uint32 {\n\treturn x ^ y ^ z\n}\n\nfunc ff1(x uint32, y uint32, z uint32) uint32 {\n\treturn (x & y) | (x & z) | (y & z)\n}\n\nfunc gg0(x uint32, y uint32, z uint32) uint32 {\n\treturn x ^ y ^ z\n}\n\nfunc gg1(x uint32, y uint32, z uint32) uint32 {\n\treturn (x & y) | ((^x) & z)\n}\n\nfunc Sum(data []byte) [DigestLength]byte {\n\tvar d sm3Digest\n\td.Reset()\n\td.Write(data)\n\treturn d.checkSum()\n}\n\nfunc PrintT() {\n\tvar T [64]uint32\n\tfmt.Print(\"{\")\n\tfor j := 0; j < 16; j++ {\n\t\tT[j] = 0x79CC4519\n\t\tTj := (T[j] << uint32(j)) | (T[j] >> (32 - uint32(j)))\n\t\tfmt.Printf(\"0x%08X, \", Tj)\n\t}\n\n\tfor j := 16; j < 64; j++ {\n\t\tn := j % 32\n\t\tT[j] = 0x7A879D8A\n\t\tTj := (T[j] << uint32(n)) | (T[j] >> (32 - uint32(n)))\n\t\tif j == 63 {\n\t\t\tfmt.Printf(\"0x%08X}\\n\", Tj)\n\t\t} else {\n\t\t\tfmt.Printf(\"0x%08X, \", Tj)\n\t\t}\n\t}\n}\n"
  },
  {
    "path": "sm3/sm3_test.go",
    "content": "package sm3\n\nimport (\n\t\"bytes\"\n\t\"encoding/hex\"\n\t\"fmt\"\n\t\"testing\"\n)\n\nvar testData = map[string]string{\n\t\"abc\": \"66c7f0f462eeedd9d1f2d46bdc10e4e24167c4875cf2f7a2297da02b8f4ba8e0\",\n\t\"abcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcd\": \"debe9ff92275b8a138604889c18e5a4d6fdb70e5387e5765293dcba39c0c5732\"}\n\nfunc TestPrintT(t *testing.T) {\n\tPrintT()\n}\n\nfunc TestSum(t *testing.T) {\n\tfor src, expected := range testData {\n\t\ttestSum(t, src, expected)\n\t}\n}\n\nfunc TestSm3Digest_Sum(t *testing.T) {\n\tfor src, expected := range testData {\n\t\ttestSm3DigestSum(t, src, expected)\n\t}\n}\n\nfunc testSum(t *testing.T, src string, expected string) {\n\thash := Sum([]byte(src))\n\thashHex := hex.EncodeToString(hash[:])\n\tif hashHex != expected {\n\t\tt.Errorf(\"result:%s , not equal expected\\n\", hashHex)\n\t\treturn\n\t}\n}\n\nfunc testSm3DigestSum(t *testing.T, src string, expected string) {\n\td := New()\n\td.Write([]byte(src))\n\thash := d.Sum(nil)\n\thashHex := hex.EncodeToString(hash[:])\n\tif hashHex != expected {\n\t\tt.Errorf(\"result:%s , not equal expected\\n\", hashHex)\n\t\treturn\n\t}\n}\n\nfunc TestSm3Digest_Write(t *testing.T) {\n\tsrc1 := []byte{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10}\n\tsrc2 := []byte{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10}\n\tsrc3 := []byte{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10}\n\n\td := New()\n\td.Write(src1)\n\td.Write(src2)\n\td.Write(src3)\n\tdigest1 := d.Sum(nil)\n\tfmt.Printf(\"1 : %s\\n\", hex.EncodeToString(digest1))\n\n\td.Reset()\n\td.Write(src1)\n\td.Write(src2)\n\td.Write(src3)\n\tdigest2 := d.Sum(nil)\n\tfmt.Printf(\"2 : %s\\n\", hex.EncodeToString(digest2))\n\n\tif !bytes.Equal(digest1, digest2) {\n\t\tt.Error(\"\")\n\t\treturn\n\t}\n}\n"
  },
  {
    "path": "sm4/sm4.go",
    "content": "package sm4\n\nimport (\n\t\"crypto/cipher\"\n\t\"encoding/binary\"\n\t\"errors\"\n\t\"math/bits\"\n\t\"strconv\"\n)\n\nconst (\n\tBlockSize = 16\n\tKeySize   = 16\n)\n\nvar sBox = [256]byte{\n\t0xd6, 0x90, 0xe9, 0xfe, 0xcc, 0xe1, 0x3d, 0xb7,\n\t0x16, 0xb6, 0x14, 0xc2, 0x28, 0xfb, 0x2c, 0x05,\n\t0x2b, 0x67, 0x9a, 0x76, 0x2a, 0xbe, 0x04, 0xc3,\n\t0xaa, 0x44, 0x13, 0x26, 0x49, 0x86, 0x06, 0x99,\n\t0x9c, 0x42, 0x50, 0xf4, 0x91, 0xef, 0x98, 0x7a,\n\t0x33, 0x54, 0x0b, 0x43, 0xed, 0xcf, 0xac, 0x62,\n\t0xe4, 0xb3, 0x1c, 0xa9, 0xc9, 0x08, 0xe8, 0x95,\n\t0x80, 0xdf, 0x94, 0xfa, 0x75, 0x8f, 0x3f, 0xa6,\n\t0x47, 0x07, 0xa7, 0xfc, 0xf3, 0x73, 0x17, 0xba,\n\t0x83, 0x59, 0x3c, 0x19, 0xe6, 0x85, 0x4f, 0xa8,\n\t0x68, 0x6b, 0x81, 0xb2, 0x71, 0x64, 0xda, 0x8b,\n\t0xf8, 0xeb, 0x0f, 0x4b, 0x70, 0x56, 0x9d, 0x35,\n\t0x1e, 0x24, 0x0e, 0x5e, 0x63, 0x58, 0xd1, 0xa2,\n\t0x25, 0x22, 0x7c, 0x3b, 0x01, 0x21, 0x78, 0x87,\n\t0xd4, 0x00, 0x46, 0x57, 0x9f, 0xd3, 0x27, 0x52,\n\t0x4c, 0x36, 0x02, 0xe7, 0xa0, 0xc4, 0xc8, 0x9e,\n\t0xea, 0xbf, 0x8a, 0xd2, 0x40, 0xc7, 0x38, 0xb5,\n\t0xa3, 0xf7, 0xf2, 0xce, 0xf9, 0x61, 0x15, 0xa1,\n\t0xe0, 0xae, 0x5d, 0xa4, 0x9b, 0x34, 0x1a, 0x55,\n\t0xad, 0x93, 0x32, 0x30, 0xf5, 0x8c, 0xb1, 0xe3,\n\t0x1d, 0xf6, 0xe2, 0x2e, 0x82, 0x66, 0xca, 0x60,\n\t0xc0, 0x29, 0x23, 0xab, 0x0d, 0x53, 0x4e, 0x6f,\n\t0xd5, 0xdb, 0x37, 0x45, 0xde, 0xfd, 0x8e, 0x2f,\n\t0x03, 0xff, 0x6a, 0x72, 0x6d, 0x6c, 0x5b, 0x51,\n\t0x8d, 0x1b, 0xaf, 0x92, 0xbb, 0xdd, 0xbc, 0x7f,\n\t0x11, 0xd9, 0x5c, 0x41, 0x1f, 0x10, 0x5a, 0xd8,\n\t0x0a, 0xc1, 0x31, 0x88, 0xa5, 0xcd, 0x7b, 0xbd,\n\t0x2d, 0x74, 0xd0, 0x12, 0xb8, 0xe5, 0xb4, 0xb0,\n\t0x89, 0x69, 0x97, 0x4a, 0x0c, 0x96, 0x77, 0x7e,\n\t0x65, 0xb9, 0xf1, 0x09, 0xc5, 0x6e, 0xc6, 0x84,\n\t0x18, 0xf0, 0x7d, 0xec, 0x3a, 0xdc, 0x4d, 0x20,\n\t0x79, 0xee, 0x5f, 0x3e, 0xd7, 0xcb, 0x39, 0x48,\n}\n\nvar cK = [32]uint32{\n\t0x00070e15, 0x1c232a31, 0x383f464d, 0x545b6269,\n\t0x70777e85, 0x8c939aa1, 0xa8afb6bd, 0xc4cbd2d9,\n\t0xe0e7eef5, 0xfc030a11, 0x181f262d, 0x343b4249,\n\t0x50575e65, 0x6c737a81, 0x888f969d, 0xa4abb2b9,\n\t0xc0c7ced5, 0xdce3eaf1, 0xf8ff060d, 0x141b2229,\n\t0x30373e45, 0x4c535a61, 0x686f767d, 0x848b9299,\n\t0xa0a7aeb5, 0xbcc3cad1, 0xd8dfe6ed, 0xf4fb0209,\n\t0x10171e25, 0x2c333a41, 0x484f565d, 0x646b7279,\n}\n\nvar fK = [4]uint32{\n\t0xa3b1bac6, 0x56aa3350, 0x677d9197, 0xb27022dc,\n}\n\ntype KeySizeError int\n\nfunc (k KeySizeError) Error() string {\n\treturn \"sm4: invalid key size \" + strconv.Itoa(int(k))\n}\n\ntype sm4Cipher struct {\n\tenc []uint32\n\tdec []uint32\n}\n\nfunc NewCipher(key []byte) (cipher.Block, error) {\n\tn := len(key)\n\tif n != KeySize {\n\t\treturn nil, KeySizeError(n)\n\t}\n\tc := new(sm4Cipher)\n\tc.enc = expandKey(key, true)\n\tc.dec = expandKey(key, false)\n\treturn c, nil\n}\n\nfunc (c *sm4Cipher) BlockSize() int {\n\treturn BlockSize\n}\n\nfunc (c *sm4Cipher) Encrypt(dst, src []byte) {\n\tif len(src) < BlockSize {\n\t\tpanic(\"sm4: input not full block\")\n\t}\n\tif len(dst) < BlockSize {\n\t\tpanic(\"sm4: output not full block\")\n\t}\n\tprocessBlock(c.enc, src, dst)\n}\n\nfunc (c *sm4Cipher) Decrypt(dst, src []byte) {\n\tif len(src) < BlockSize {\n\t\tpanic(\"sm4: input not full block\")\n\t}\n\tif len(dst) < BlockSize {\n\t\tpanic(\"sm4: output not full block\")\n\t}\n\tprocessBlock(c.dec, src, dst)\n}\n\nfunc expandKey(key []byte, forEnc bool) []uint32 {\n\tvar mK [4]uint32\n\tmK[0] = binary.BigEndian.Uint32(key[0:4])\n\tmK[1] = binary.BigEndian.Uint32(key[4:8])\n\tmK[2] = binary.BigEndian.Uint32(key[8:12])\n\tmK[3] = binary.BigEndian.Uint32(key[12:16])\n\n\tvar x [5]uint32\n\tx[0] = mK[0] ^ fK[0]\n\tx[1] = mK[1] ^ fK[1]\n\tx[2] = mK[2] ^ fK[2]\n\tx[3] = mK[3] ^ fK[3]\n\n\tvar rk [32]uint32\n\tif forEnc {\n\t\tfor i := 0; i < 32; i++ {\n\t\t\tx[(i+4)%5] = encRound(x[i%5], x[(i+1)%5], x[(i+2)%5], x[(i+3)%5], x[(i+4)%5], rk[:], i)\n\t\t}\n\t} else {\n\t\tfor i := 0; i < 32; i++ {\n\t\t\tx[(i+4)%5] = decRound(x[i%5], x[(i+1)%5], x[(i+2)%5], x[(i+3)%5], x[(i+4)%5], rk[:], i)\n\t\t}\n\t}\n\treturn rk[:]\n}\n\nfunc tau(a uint32) uint32 {\n\tvar aArr [4]byte\n\tvar bArr [4]byte\n\tbinary.BigEndian.PutUint32(aArr[:], a)\n\tbArr[0] = sBox[aArr[0]]\n\tbArr[1] = sBox[aArr[1]]\n\tbArr[2] = sBox[aArr[2]]\n\tbArr[3] = sBox[aArr[3]]\n\treturn binary.BigEndian.Uint32(bArr[:])\n}\n\nfunc lAp(b uint32) uint32 {\n\treturn b ^ bits.RotateLeft32(b, 13) ^ bits.RotateLeft32(b, 23)\n}\n\nfunc tAp(z uint32) uint32 {\n\treturn lAp(tau(z))\n}\n\nfunc encRound(x0 uint32, x1 uint32, x2 uint32, x3 uint32, x4 uint32, rk []uint32, i int) uint32 {\n\tx4 = x0 ^ tAp(x1^x2^x3^cK[i])\n\trk[i] = x4\n\treturn x4\n}\n\nfunc decRound(x0 uint32, x1 uint32, x2 uint32, x3 uint32, x4 uint32, rk []uint32, i int) uint32 {\n\tx4 = x0 ^ tAp(x1^x2^x3^cK[i])\n\trk[31-i] = x4\n\treturn x4\n}\n\nfunc processBlock(rk []uint32, in []byte, out []byte) {\n\tvar x [BlockSize / 4]uint32\n\tx[0] = binary.BigEndian.Uint32(in[0:4])\n\tx[1] = binary.BigEndian.Uint32(in[4:8])\n\tx[2] = binary.BigEndian.Uint32(in[8:12])\n\tx[3] = binary.BigEndian.Uint32(in[12:16])\n\n\tfor i := 0; i < 32; i += 4 {\n\t\tx[0] = f0(x[:], rk[i])\n\t\tx[1] = f1(x[:], rk[i+1])\n\t\tx[2] = f2(x[:], rk[i+2])\n\t\tx[3] = f3(x[:], rk[i+3])\n\t}\n\tr(x[:])\n\n\tbinary.BigEndian.PutUint32(out[0:4], x[0])\n\tbinary.BigEndian.PutUint32(out[4:8], x[1])\n\tbinary.BigEndian.PutUint32(out[8:12], x[2])\n\tbinary.BigEndian.PutUint32(out[12:16], x[3])\n}\n\nfunc l(b uint32) uint32 {\n\treturn b ^ bits.RotateLeft32(b, 2) ^ bits.RotateLeft32(b, 10) ^\n\t\tbits.RotateLeft32(b, 18) ^ bits.RotateLeft32(b, 24)\n}\n\nfunc t(z uint32) uint32 {\n\treturn l(tau(z))\n}\n\nfunc r(a []uint32) {\n\ta[0] = a[0] ^ a[3]\n\ta[3] = a[0] ^ a[3]\n\ta[0] = a[0] ^ a[3]\n\ta[1] = a[1] ^ a[2]\n\ta[2] = a[1] ^ a[2]\n\ta[1] = a[1] ^ a[2]\n}\n\nfunc f0(x []uint32, rk uint32) uint32 {\n\treturn x[0] ^ t(x[1]^x[2]^x[3]^rk)\n}\n\nfunc f1(x []uint32, rk uint32) uint32 {\n\treturn x[1] ^ t(x[2]^x[3]^x[0]^rk)\n}\n\nfunc f2(x []uint32, rk uint32) uint32 {\n\treturn x[2] ^ t(x[3]^x[0]^x[1]^rk)\n}\n\nfunc f3(x []uint32, rk uint32) uint32 {\n\treturn x[3] ^ t(x[0]^x[1]^x[2]^rk)\n}\n\n// 输入的plainText长度必须是BlockSize(16)的整数倍，也就是调用该方法前调用方需先加好padding，\n// 可调用util.PKCS5Padding()方法进行加padding操作\nfunc ECBEncrypt(key, plainText []byte) (cipherText []byte, err error) {\n\tplainTextLen := len(plainText)\n\tif plainTextLen%BlockSize != 0 {\n\t\treturn nil, errors.New(\"input not full blocks\")\n\t}\n\n\tc, err := NewCipher(key)\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\tcipherText = make([]byte, plainTextLen)\n\tfor i := 0; i < plainTextLen; i += BlockSize {\n\t\tc.Encrypt(cipherText[i:i+BlockSize], plainText[i:i+BlockSize])\n\t}\n\treturn cipherText, nil\n}\n\n// 输出的plainText是加padding的明文，调用方需要自己去padding，\n// 可调用util.PKCS5UnPadding()方法进行去padding操作\nfunc ECBDecrypt(key, cipherText []byte) (plainText []byte, err error) {\n\tcipherTextLen := len(cipherText)\n\tif cipherTextLen%BlockSize != 0 {\n\t\treturn nil, errors.New(\"input not full blocks\")\n\t}\n\n\tc, err := NewCipher(key)\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\tplainText = make([]byte, cipherTextLen)\n\tfor i := 0; i < cipherTextLen; i += BlockSize {\n\t\tc.Decrypt(plainText[i:i+BlockSize], cipherText[i:i+BlockSize])\n\t}\n\treturn plainText, nil\n}\n\n// 输入的plainText长度必须是BlockSize(16)的整数倍，也就是调用该方法前调用方需先加好padding，\n// 可调用util.PKCS5Padding()方法进行加padding操作\nfunc CBCEncrypt(key, iv, plainText []byte) (cipherText []byte, err error) {\n\tplainTextLen := len(plainText)\n\tif plainTextLen%BlockSize != 0 {\n\t\treturn nil, errors.New(\"input not full blocks\")\n\t}\n\n\tc, err := NewCipher(key)\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\tencrypter := cipher.NewCBCEncrypter(c, iv)\n\tcipherText = make([]byte, plainTextLen)\n\tencrypter.CryptBlocks(cipherText, plainText)\n\treturn cipherText, nil\n}\n\n// 输出的plainText是加padding的明文，调用方需要自己去padding，\n// 可调用util.PKCS5UnPadding()方法进行去padding操作\nfunc CBCDecrypt(key, iv, cipherText []byte) (plainText []byte, err error) {\n\tcipherTextLen := len(cipherText)\n\tif cipherTextLen%BlockSize != 0 {\n\t\treturn nil, errors.New(\"input not full blocks\")\n\t}\n\n\tc, err := NewCipher(key)\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\tdecrypter := cipher.NewCBCDecrypter(c, iv)\n\tplainText = make([]byte, len(cipherText))\n\tdecrypter.CryptBlocks(plainText, cipherText)\n\treturn plainText, nil\n}\n"
  },
  {
    "path": "sm4/sm4_test.go",
    "content": "package sm4\n\nimport (\n\t\"bytes\"\n\t\"encoding/hex\"\n\t\"fmt\"\n\t\"github.com/ZZMarquis/gm/util\"\n\t\"testing\"\n)\n\ntype sm4CbcTestData struct {\n\tkey []byte\n\tiv  []byte\n\tin  []byte\n\tout []byte\n}\n\nvar cbcTestData = []sm4CbcTestData{\n\t{\n\t\tkey: []byte{0x7b, 0xea, 0x0a, 0xa5, 0x45, 0x8e, 0xd1, 0xa3, 0x7d, 0xb1, 0x65, 0x2e, 0xfb, 0xc5, 0x95, 0x05},\n\t\tiv:  []byte{0x70, 0xb6, 0xe0, 0x8d, 0x46, 0xee, 0x82, 0x24, 0x45, 0x60, 0x0b, 0x25, 0xc4, 0x71, 0xfa, 0xba},\n\t\tin:  []byte{0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08},\n\t\tout: []byte{0xca, 0x55, 0xc5, 0x15, 0x0b, 0xf7, 0xf4, 0x6f, 0xc9, 0x89, 0x2a, 0xce, 0x49, 0x78, 0x93, 0x03},\n\t},\n\t{\n\t\tkey: []byte{0x7b, 0xea, 0x0a, 0xa5, 0x45, 0x8e, 0xd1, 0xa3, 0x7d, 0xb1, 0x65, 0x2e, 0xfb, 0xc5, 0x95, 0x05},\n\t\tiv:  []byte{0x70, 0xb6, 0xe0, 0x8d, 0x46, 0xee, 0x82, 0x24, 0x45, 0x60, 0x0b, 0x25, 0xc4, 0x71, 0xfa, 0xba},\n\t\tin:  []byte{0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08},\n\t\tout: []byte{0x95, 0xe1, 0xec, 0x3b, 0x56, 0x4a, 0x46, 0x71, 0xe7, 0xd6, 0xb1, 0x10, 0xe9, 0x09, 0x0b, 0x1b, 0xb7, 0xb5, 0x9e, 0x8d, 0x74, 0x47, 0x1e, 0x70, 0x86, 0x04, 0x6b, 0xe8, 0x78, 0x00, 0x45, 0x32},\n\t},\n}\n\nfunc TestSm4_CBC_Encrypt(t *testing.T) {\n\tfor _, data := range cbcTestData {\n\t\tfmt.Printf(\"Key:%s\\n\", hex.EncodeToString(data.key))\n\t\tfmt.Printf(\"IV:%s\\n\", hex.EncodeToString(data.iv))\n\n\t\tcipherText, err := CBCEncrypt(data.key, data.iv, util.PKCS5Padding(data.in, BlockSize))\n\t\tif err != nil {\n\t\t\tt.Error(err.Error())\n\t\t\treturn\n\t\t}\n\t\tfmt.Printf(\"encrypt cipherText:%s\\n\", hex.EncodeToString(cipherText))\n\t\tif !bytes.Equal(cipherText, data.out) {\n\t\t\tt.Error(\"encrypt cipherText not equal expected\")\n\t\t\treturn\n\t\t}\n\n\t\tplainTextWithPadding, err := CBCDecrypt(data.key, data.iv, cipherText)\n\t\tif err != nil {\n\t\t\tt.Error(err.Error())\n\t\t\treturn\n\t\t}\n\t\tfmt.Printf(\"decrypt cipherText:%s\\n\", hex.EncodeToString(plainTextWithPadding))\n\t\tplainText := util.PKCS5UnPadding(plainTextWithPadding)\n\t\tif !bytes.Equal(plainText, data.in) {\n\t\t\tt.Error(\"decrypt cipherText not equal expected\")\n\t\t\treturn\n\t\t}\n\t}\n}\n\ntype sm4EcbTestData struct {\n\tkey []byte\n\tin  []byte\n}\n\nvar ecbTestData = []sm4EcbTestData{\n\t{\n\t\tkey: []byte(\"1234567890123456\"),\n\t\tin:  []byte(\"ssssssss\"),\n\t}, {\n\t\tkey: []byte(\"1234567890123456\"),\n\t\tin:  []byte(\"ssssssssssssssss\"),\n\t}, {\n\t\tkey: []byte(\"1234567890123456\"),\n\t\tin:  []byte(\"ssssssssssssssssssssssss\"),\n\t},\n}\n\nfunc TestSm4_ECB_Encrypt_PKCS5Padding(t *testing.T) {\n\tfor _, testData := range ecbTestData {\n\t\tplainTextWithPadding := util.PKCS5Padding(testData.in, BlockSize)\n\t\tcipherText, err := ECBEncrypt(testData.key, plainTextWithPadding)\n\t\tif err != nil {\n\t\t\tt.Error(err.Error())\n\t\t\treturn\n\t\t}\n\t\tfmt.Printf(\"%x\\n\", cipherText)\n\n\t\tplainTextWithPadding, err = ECBDecrypt(testData.key, cipherText)\n\t\tif err != nil {\n\t\t\tt.Error(err.Error())\n\t\t\treturn\n\t\t}\n\t\tplainText := util.PKCS5UnPadding(plainTextWithPadding)\n\t\tfmt.Println(string(plainText))\n\t\tif !bytes.Equal(testData.in, plainText) {\n\t\t\tt.Error(\"decrypt result not equal expected\")\n\t\t\treturn\n\t\t}\n\t}\n}\n\nfunc TestSm4_ECB_Encrypt_ZeroPadding(t *testing.T) {\n\tfor _, testData := range ecbTestData {\n\t\tplainTextWithPadding := util.ZeroPadding(testData.in, BlockSize)\n\t\tpaddingLen := len(plainTextWithPadding) - len(testData.in)\n\t\tcipherText, err := ECBEncrypt(testData.key, plainTextWithPadding)\n\t\tif err != nil {\n\t\t\tt.Error(err.Error())\n\t\t\treturn\n\t\t}\n\t\tfmt.Printf(\"%x\\n\", cipherText)\n\n\t\tplainTextWithPadding, err = ECBDecrypt(testData.key, cipherText)\n\t\tif err != nil {\n\t\t\tt.Error(err.Error())\n\t\t\treturn\n\t\t}\n\t\tplainText := util.UnZeroPadding(plainTextWithPadding, paddingLen)\n\t\tfmt.Println(string(plainText))\n\t\tif !bytes.Equal(testData.in, plainText) {\n\t\t\tt.Error(\"decrypt result not equal expected\")\n\t\t\treturn\n\t\t}\n\t}\n}\n"
  },
  {
    "path": "util/bigint.go",
    "content": "package util\n\nimport \"math/big\"\n\nfunc Add(x, y *big.Int) *big.Int {\n\tvar z big.Int\n\tz.Add(x, y)\n\treturn &z\n}\n\nfunc Sub(x, y *big.Int) *big.Int {\n\tvar z big.Int\n\tz.Sub(x, y)\n\treturn &z\n}\n\nfunc Mod(x, y *big.Int) *big.Int {\n\tvar z big.Int\n\tz.Mod(x, y)\n\treturn &z\n}\n\nfunc ModInverse(x, y *big.Int) *big.Int {\n\tvar z big.Int\n\tz.ModInverse(x, y)\n\treturn &z\n}\n\nfunc Mul(x, y *big.Int) *big.Int {\n\tvar z big.Int\n\tz.Mul(x, y)\n\treturn &z\n}\n\nfunc Lsh(x *big.Int, n uint) *big.Int {\n\tvar z big.Int\n\tz.Lsh(x, n)\n\treturn &z\n}\n\nfunc SetBit(x *big.Int, i int, b uint) *big.Int {\n\tvar z big.Int\n\tz.SetBit(x, i, b)\n\treturn &z\n}\n\nfunc And(x, y *big.Int) *big.Int {\n\tvar z big.Int\n\tz.And(x, y)\n\treturn &z\n}\n"
  },
  {
    "path": "util/bigint_test.go",
    "content": "package util\n\nimport (\n\t\"fmt\"\n\t\"math/big\"\n\t\"testing\"\n)\n\nfunc TestAdd(t *testing.T) {\n\ta := new(big.Int).SetInt64(1)\n\tb := new(big.Int).SetInt64(1)\n\ta.Add(a, b)\n\tfmt.Printf(\"a:%s\\n\", a.Text(10))\n\tfmt.Printf(\"b:%s\\n\", b.Text(10))\n}\n\nfunc TestAdd2(t *testing.T) {\n\ta := new(big.Int).SetInt64(1)\n\tb := new(big.Int).SetInt64(1)\n\tz := Add(a, b)\n\tfmt.Printf(\"a:%s\\n\", a.Text(10))\n\tfmt.Printf(\"b:%s\\n\", b.Text(10))\n\tfmt.Printf(\"z:%s\\n\", z.Text(10))\n}\n"
  },
  {
    "path": "util/ec.go",
    "content": "package util\n\nimport \"math/big\"\n\nfunc IsEcPointInfinity(x, y *big.Int) bool {\n\tif x.Sign() == 0 && y.Sign() == 0 {\n\t\treturn true\n\t}\n\treturn false\n}\n\nfunc ZForAffine(x, y *big.Int) *big.Int {\n\tz := new(big.Int)\n\tif x.Sign() != 0 || y.Sign() != 0 {\n\t\tz.SetInt64(1)\n\t}\n\treturn z\n}\n"
  },
  {
    "path": "util/padding.go",
    "content": "package util\n\nimport \"bytes\"\n\nfunc PKCS5Padding(src []byte, blockSize int) []byte {\n\tpadding := blockSize - len(src)%blockSize\n\tpadtext := bytes.Repeat([]byte{byte(padding)}, padding)\n\treturn append(src, padtext...)\n}\n\nfunc PKCS5UnPadding(src []byte) []byte {\n\tlength := len(src)\n\tunpadding := int(src[length-1])\n\treturn src[:(length - unpadding)]\n}\n\nfunc ZeroPadding(src []byte, blockSize int) []byte {\n\tpadding := blockSize - len(src)%blockSize\n\tpadtext := bytes.Repeat([]byte{0}, padding)\n\treturn append(src, padtext...)\n}\n\n// UnZeroPadding\n// 由于原文最后一个或若干个字节就有可能为0，所以大多情况下不能简单粗暴地后面有几个0就去掉几个0，除非可以确定最后一个字节肯定不为0.\n// 所以需要用户自己去指定具体要去掉末尾几个字节，具体要看用户的自己的数据协议怎么设计。\nfunc UnZeroPadding(src []byte, paddingLen int) []byte {\n\treturn src[:len(src)-paddingLen]\n}\n"
  }
]