SignaturePacket.cs 14 KB

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