SignaturePacket.cs 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466
  1. #if !BESTHTTP_DISABLE_ALTERNATE_SSL && (!UNITY_WEBGL || UNITY_EDITOR)
  2. #pragma warning disable
  3. using System;
  4. using System.Collections.Generic;
  5. using System.IO;
  6. using Best.HTTP.SecureProtocol.Org.BouncyCastle.Bcpg.Sig;
  7. using Best.HTTP.SecureProtocol.Org.BouncyCastle.Utilities.Date;
  8. using Best.HTTP.SecureProtocol.Org.BouncyCastle.Utilities.IO;
  9. namespace Best.HTTP.SecureProtocol.Org.BouncyCastle.Bcpg
  10. {
  11. /// <remarks>Generic signature packet.</remarks>
  12. public class SignaturePacket
  13. : ContainedPacket
  14. {
  15. private int version;
  16. private int signatureType;
  17. private long creationTime;
  18. private long keyId;
  19. private PublicKeyAlgorithmTag keyAlgorithm;
  20. private HashAlgorithmTag hashAlgorithm;
  21. private MPInteger[] signature;
  22. private byte[] fingerprint;
  23. private SignatureSubpacket[] hashedData;
  24. private SignatureSubpacket[] unhashedData;
  25. private byte[] signatureEncoding;
  26. internal SignaturePacket(
  27. BcpgInputStream bcpgIn)
  28. {
  29. version = bcpgIn.ReadByte();
  30. if (version == 3 || version == 2)
  31. {
  32. // int l =
  33. bcpgIn.ReadByte();
  34. signatureType = bcpgIn.ReadByte();
  35. creationTime = (((long)bcpgIn.ReadByte() << 24) | ((long)bcpgIn.ReadByte() << 16)
  36. | ((long)bcpgIn.ReadByte() << 8) | (uint)bcpgIn.ReadByte()) * 1000L;
  37. keyId |= (long)bcpgIn.ReadByte() << 56;
  38. keyId |= (long)bcpgIn.ReadByte() << 48;
  39. keyId |= (long)bcpgIn.ReadByte() << 40;
  40. keyId |= (long)bcpgIn.ReadByte() << 32;
  41. keyId |= (long)bcpgIn.ReadByte() << 24;
  42. keyId |= (long)bcpgIn.ReadByte() << 16;
  43. keyId |= (long)bcpgIn.ReadByte() << 8;
  44. keyId |= (uint)bcpgIn.ReadByte();
  45. keyAlgorithm = (PublicKeyAlgorithmTag) bcpgIn.ReadByte();
  46. hashAlgorithm = (HashAlgorithmTag) bcpgIn.ReadByte();
  47. }
  48. else if (version == 4)
  49. {
  50. signatureType = bcpgIn.ReadByte();
  51. keyAlgorithm = (PublicKeyAlgorithmTag) bcpgIn.ReadByte();
  52. hashAlgorithm = (HashAlgorithmTag) bcpgIn.ReadByte();
  53. int hashedLength = (bcpgIn.ReadByte() << 8) | bcpgIn.ReadByte();
  54. byte[] hashed = new byte[hashedLength];
  55. bcpgIn.ReadFully(hashed);
  56. //
  57. // read the signature sub packet data.
  58. //
  59. SignatureSubpacketsParser sIn = new SignatureSubpacketsParser(
  60. new MemoryStream(hashed, false));
  61. var v = new List<SignatureSubpacket>();
  62. SignatureSubpacket sub;
  63. while ((sub = sIn.ReadPacket()) != null)
  64. {
  65. v.Add(sub);
  66. }
  67. hashedData = v.ToArray();
  68. foreach (var p in hashedData)
  69. {
  70. if (p is IssuerKeyId issuerKeyId)
  71. {
  72. keyId = issuerKeyId.KeyId;
  73. }
  74. else if (p is SignatureCreationTime sigCreationTime)
  75. {
  76. creationTime = DateTimeUtilities.DateTimeToUnixMs(sigCreationTime.GetTime());
  77. }
  78. }
  79. int unhashedLength = (bcpgIn.ReadByte() << 8) | bcpgIn.ReadByte();
  80. byte[] unhashed = new byte[unhashedLength];
  81. bcpgIn.ReadFully(unhashed);
  82. sIn = new SignatureSubpacketsParser(new MemoryStream(unhashed, false));
  83. v.Clear();
  84. while ((sub = sIn.ReadPacket()) != null)
  85. {
  86. v.Add(sub);
  87. }
  88. unhashedData = v.ToArray();
  89. foreach (var p in unhashedData)
  90. {
  91. if (p is IssuerKeyId issuerKeyId)
  92. {
  93. keyId = issuerKeyId.KeyId;
  94. }
  95. }
  96. }
  97. else
  98. {
  99. Streams.Drain(bcpgIn);
  100. throw new UnsupportedPacketVersionException("unsupported version: " + version);
  101. }
  102. fingerprint = new byte[2];
  103. bcpgIn.ReadFully(fingerprint);
  104. switch (keyAlgorithm)
  105. {
  106. case PublicKeyAlgorithmTag.RsaGeneral:
  107. case PublicKeyAlgorithmTag.RsaSign:
  108. MPInteger v = new MPInteger(bcpgIn);
  109. signature = new MPInteger[1]{ v };
  110. break;
  111. case PublicKeyAlgorithmTag.Dsa:
  112. MPInteger r = new MPInteger(bcpgIn);
  113. MPInteger s = new MPInteger(bcpgIn);
  114. signature = new MPInteger[2]{ r, s };
  115. break;
  116. case PublicKeyAlgorithmTag.ElGamalEncrypt: // yep, this really does happen sometimes.
  117. case PublicKeyAlgorithmTag.ElGamalGeneral:
  118. MPInteger p = new MPInteger(bcpgIn);
  119. MPInteger g = new MPInteger(bcpgIn);
  120. MPInteger y = new MPInteger(bcpgIn);
  121. signature = new MPInteger[3]{ p, g, y };
  122. break;
  123. case PublicKeyAlgorithmTag.ECDsa:
  124. case PublicKeyAlgorithmTag.EdDsa:
  125. MPInteger ecR = new MPInteger(bcpgIn);
  126. MPInteger ecS = new MPInteger(bcpgIn);
  127. signature = new MPInteger[2]{ ecR, ecS };
  128. break;
  129. default:
  130. if (keyAlgorithm < PublicKeyAlgorithmTag.Experimental_1 || keyAlgorithm > PublicKeyAlgorithmTag.Experimental_11)
  131. throw new IOException("unknown signature key algorithm: " + keyAlgorithm);
  132. signature = null;
  133. MemoryStream bOut = new MemoryStream();
  134. int ch;
  135. while ((ch = bcpgIn.ReadByte()) >= 0)
  136. {
  137. bOut.WriteByte((byte) ch);
  138. }
  139. signatureEncoding = bOut.ToArray();
  140. break;
  141. }
  142. }
  143. /**
  144. * Generate a version 4 signature packet.
  145. *
  146. * @param signatureType
  147. * @param keyAlgorithm
  148. * @param hashAlgorithm
  149. * @param hashedData
  150. * @param unhashedData
  151. * @param fingerprint
  152. * @param signature
  153. */
  154. public SignaturePacket(
  155. int signatureType,
  156. long keyId,
  157. PublicKeyAlgorithmTag keyAlgorithm,
  158. HashAlgorithmTag hashAlgorithm,
  159. SignatureSubpacket[] hashedData,
  160. SignatureSubpacket[] unhashedData,
  161. byte[] fingerprint,
  162. MPInteger[] signature)
  163. : this(4, signatureType, keyId, keyAlgorithm, hashAlgorithm, hashedData, unhashedData, fingerprint, signature)
  164. {
  165. }
  166. /**
  167. * Generate a version 2/3 signature packet.
  168. *
  169. * @param signatureType
  170. * @param keyAlgorithm
  171. * @param hashAlgorithm
  172. * @param fingerprint
  173. * @param signature
  174. */
  175. public SignaturePacket(
  176. int version,
  177. int signatureType,
  178. long keyId,
  179. PublicKeyAlgorithmTag keyAlgorithm,
  180. HashAlgorithmTag hashAlgorithm,
  181. long creationTime,
  182. byte[] fingerprint,
  183. MPInteger[] signature)
  184. : this(version, signatureType, keyId, keyAlgorithm, hashAlgorithm, null, null, fingerprint, signature)
  185. {
  186. this.creationTime = creationTime;
  187. }
  188. public SignaturePacket(
  189. int version,
  190. int signatureType,
  191. long keyId,
  192. PublicKeyAlgorithmTag keyAlgorithm,
  193. HashAlgorithmTag hashAlgorithm,
  194. SignatureSubpacket[] hashedData,
  195. SignatureSubpacket[] unhashedData,
  196. byte[] fingerprint,
  197. MPInteger[] signature)
  198. {
  199. this.version = version;
  200. this.signatureType = signatureType;
  201. this.keyId = keyId;
  202. this.keyAlgorithm = keyAlgorithm;
  203. this.hashAlgorithm = hashAlgorithm;
  204. this.hashedData = hashedData;
  205. this.unhashedData = unhashedData;
  206. this.fingerprint = fingerprint;
  207. this.signature = signature;
  208. if (hashedData != null)
  209. {
  210. SetCreationTime();
  211. }
  212. }
  213. public int Version
  214. {
  215. get { return version; }
  216. }
  217. public int SignatureType
  218. {
  219. get { return signatureType; }
  220. }
  221. /**
  222. * return the keyId
  223. * @return the keyId that created the signature.
  224. */
  225. public long KeyId
  226. {
  227. get { return keyId; }
  228. }
  229. /**
  230. * return the signature trailer that must be included with the data
  231. * to reconstruct the signature
  232. *
  233. * @return byte[]
  234. */
  235. public byte[] GetSignatureTrailer()
  236. {
  237. if (version == 3)
  238. {
  239. long time = creationTime / 1000L;
  240. byte[] trailer = new byte[5];
  241. trailer[0] = (byte)signatureType;
  242. trailer[1] = (byte)(time >> 24);
  243. trailer[2] = (byte)(time >> 16);
  244. trailer[3] = (byte)(time >> 8);
  245. trailer[4] = (byte)(time );
  246. return trailer;
  247. }
  248. MemoryStream sOut = new MemoryStream();
  249. sOut.WriteByte((byte)Version);
  250. sOut.WriteByte((byte)SignatureType);
  251. sOut.WriteByte((byte)KeyAlgorithm);
  252. sOut.WriteByte((byte)HashAlgorithm);
  253. // Mark position an reserve two bytes for length
  254. long lengthPosition = sOut.Position;
  255. sOut.WriteByte(0x00);
  256. sOut.WriteByte(0x00);
  257. SignatureSubpacket[] hashed = GetHashedSubPackets();
  258. for (int i = 0; i != hashed.Length; i++)
  259. {
  260. hashed[i].Encode(sOut);
  261. }
  262. ushort dataLength = Convert.ToUInt16(sOut.Position - lengthPosition - 2);
  263. uint hDataLength = Convert.ToUInt32(sOut.Position);
  264. sOut.WriteByte((byte)Version);
  265. sOut.WriteByte(0xff);
  266. sOut.WriteByte((byte)(hDataLength >> 24));
  267. sOut.WriteByte((byte)(hDataLength >> 16));
  268. sOut.WriteByte((byte)(hDataLength >> 8));
  269. sOut.WriteByte((byte)(hDataLength ));
  270. // Reset position and fill in length
  271. sOut.Position = lengthPosition;
  272. sOut.WriteByte((byte)(dataLength >> 8));
  273. sOut.WriteByte((byte)(dataLength ));
  274. return sOut.ToArray();
  275. }
  276. public PublicKeyAlgorithmTag KeyAlgorithm
  277. {
  278. get { return keyAlgorithm; }
  279. }
  280. public HashAlgorithmTag HashAlgorithm
  281. {
  282. get { return hashAlgorithm; }
  283. }
  284. /**
  285. * return the signature as a set of integers - note this is normalised to be the
  286. * ASN.1 encoding of what appears in the signature packet.
  287. */
  288. public MPInteger[] GetSignature()
  289. {
  290. return signature;
  291. }
  292. /**
  293. * Return the byte encoding of the signature section.
  294. * @return uninterpreted signature bytes.
  295. */
  296. public byte[] GetSignatureBytes()
  297. {
  298. if (signatureEncoding != null)
  299. {
  300. return (byte[]) signatureEncoding.Clone();
  301. }
  302. MemoryStream bOut = new MemoryStream();
  303. BcpgOutputStream bcOut = new BcpgOutputStream(bOut);
  304. foreach (MPInteger sigObj in signature)
  305. {
  306. try
  307. {
  308. bcOut.WriteObject(sigObj);
  309. }
  310. catch (IOException e)
  311. {
  312. throw new Exception("internal error: " + e);
  313. }
  314. }
  315. return bOut.ToArray();
  316. }
  317. public SignatureSubpacket[] GetHashedSubPackets()
  318. {
  319. return hashedData;
  320. }
  321. public SignatureSubpacket[] GetUnhashedSubPackets()
  322. {
  323. return unhashedData;
  324. }
  325. /// <summary>Return the creation time in milliseconds since 1 Jan., 1970 UTC.</summary>
  326. public long CreationTime
  327. {
  328. get { return creationTime; }
  329. }
  330. public override void Encode(BcpgOutputStream bcpgOut)
  331. {
  332. MemoryStream bOut = new MemoryStream();
  333. using (var pOut = new BcpgOutputStream(bOut))
  334. {
  335. pOut.WriteByte((byte)version);
  336. if (version == 3 || version == 2)
  337. {
  338. byte nextBlockLength = 5;
  339. pOut.Write(nextBlockLength, (byte)signatureType);
  340. pOut.WriteInt((int)(creationTime / 1000L));
  341. pOut.WriteLong(keyId);
  342. pOut.Write((byte)keyAlgorithm, (byte)hashAlgorithm);
  343. }
  344. else if (version == 4)
  345. {
  346. pOut.Write((byte)signatureType, (byte)keyAlgorithm, (byte)hashAlgorithm);
  347. EncodeLengthAndData(pOut, GetEncodedSubpackets(hashedData));
  348. EncodeLengthAndData(pOut, GetEncodedSubpackets(unhashedData));
  349. }
  350. else
  351. {
  352. throw new IOException("unknown version: " + version);
  353. }
  354. pOut.Write(fingerprint);
  355. if (signature != null)
  356. {
  357. pOut.WriteObjects(signature);
  358. }
  359. else
  360. {
  361. pOut.Write(signatureEncoding);
  362. }
  363. }
  364. bcpgOut.WritePacket(PacketTag.Signature, bOut.ToArray(), true);
  365. }
  366. private static void EncodeLengthAndData(
  367. BcpgOutputStream pOut,
  368. byte[] data)
  369. {
  370. pOut.WriteShort((short) data.Length);
  371. pOut.Write(data);
  372. }
  373. private static byte[] GetEncodedSubpackets(
  374. SignatureSubpacket[] ps)
  375. {
  376. MemoryStream sOut = new MemoryStream();
  377. foreach (SignatureSubpacket p in ps)
  378. {
  379. p.Encode(sOut);
  380. }
  381. return sOut.ToArray();
  382. }
  383. private void SetCreationTime()
  384. {
  385. foreach (SignatureSubpacket p in hashedData)
  386. {
  387. if (p is SignatureCreationTime signatureCreationTime)
  388. {
  389. creationTime = DateTimeUtilities.DateTimeToUnixMs(signatureCreationTime.GetTime());
  390. break;
  391. }
  392. }
  393. }
  394. public static SignaturePacket FromByteArray(byte[] data)
  395. {
  396. BcpgInputStream input = BcpgInputStream.Wrap(new MemoryStream(data));
  397. return new SignaturePacket(input);
  398. }
  399. }
  400. }
  401. #pragma warning restore
  402. #endif