AlipaySignature.cs 24 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635
  1. using System;
  2. using System.Collections.Generic;
  3. using System.Text;
  4. using System.Security.Cryptography;
  5. using System.IO;
  6. namespace Aop.Api.Util
  7. {
  8. public class AlipaySignature
  9. {
  10. /** 默认编码字符集 */
  11. private static string DEFAULT_CHARSET = "GBK";
  12. public static string GetSignContent(IDictionary<string, string> parameters)
  13. {
  14. // 第一步:把字典按Key的字母顺序排序
  15. IDictionary<string, string> sortedParams = new SortedDictionary<string, string>(parameters);
  16. IEnumerator<KeyValuePair<string, string>> dem = sortedParams.GetEnumerator();
  17. // 第二步:把所有参数名和参数值串在一起
  18. StringBuilder query = new StringBuilder("");
  19. while (dem.MoveNext())
  20. {
  21. string key = dem.Current.Key;
  22. string value = dem.Current.Value;
  23. if (!string.IsNullOrEmpty(key) && !string.IsNullOrEmpty(value))
  24. {
  25. query.Append(key).Append("=").Append(value).Append("&");
  26. }
  27. }
  28. string content = query.ToString().Substring(0, query.Length - 1);
  29. return content;
  30. }
  31. public static string RSASign(IDictionary<string, string> parameters, string privateKeyPem, string charset, string signType)
  32. {
  33. string signContent = GetSignContent(parameters);
  34. return RSASignCharSet(signContent, privateKeyPem, charset, signType);
  35. }
  36. public static string RSASign(string data, string privateKeyPem, string charset, string signType)
  37. {
  38. return RSASignCharSet(data, privateKeyPem, charset, signType);
  39. }
  40. ///*
  41. public static string RSASign(IDictionary<string, string> parameters, string privateKeyPem, string charset, bool keyFromFile, string signType)
  42. {
  43. string signContent = GetSignContent(parameters);
  44. return RSASignCharSet(signContent, privateKeyPem, charset, keyFromFile, signType);
  45. }
  46. //*/
  47. public static string RSASignCharSet(string data, string privateKeyPem, string charset, string signType)
  48. {
  49. RSACryptoServiceProvider rsaCsp = LoadCertificateFile(privateKeyPem, signType);
  50. byte[] dataBytes = null;
  51. if (string.IsNullOrEmpty(charset))
  52. {
  53. dataBytes = Encoding.UTF8.GetBytes(data);
  54. }
  55. else
  56. {
  57. dataBytes = Encoding.GetEncoding(charset).GetBytes(data);
  58. }
  59. if ("RSA2".Equals(signType))
  60. {
  61. byte[] signatureBytes = rsaCsp.SignData(dataBytes, "SHA256");
  62. return Convert.ToBase64String(signatureBytes);
  63. }
  64. else
  65. {
  66. byte[] signatureBytes = rsaCsp.SignData(dataBytes, "SHA1");
  67. return Convert.ToBase64String(signatureBytes);
  68. }
  69. }
  70. public static string RSASignCharSet(string data, string privateKeyPem, string charset, bool keyFromFile, string signType)
  71. {
  72. byte[] signatureBytes = null;
  73. try
  74. {
  75. RSACryptoServiceProvider rsaCsp = null;
  76. if (keyFromFile)
  77. {//文件读取
  78. rsaCsp = LoadCertificateFile(privateKeyPem, signType);
  79. }
  80. else
  81. {
  82. //字符串获取
  83. rsaCsp = LoadCertificateString(privateKeyPem, signType);
  84. }
  85. byte[] dataBytes = null;
  86. if (string.IsNullOrEmpty(charset))
  87. {
  88. dataBytes = Encoding.UTF8.GetBytes(data);
  89. }
  90. else
  91. {
  92. dataBytes = Encoding.GetEncoding(charset).GetBytes(data);
  93. }
  94. if (null == rsaCsp)
  95. {
  96. throw new AopException("您使用的私钥格式错误,请检查RSA私钥配置" + ",charset = " + charset);
  97. }
  98. if ("RSA2".Equals(signType))
  99. {
  100. signatureBytes = rsaCsp.SignData(dataBytes, "SHA256");
  101. }
  102. else
  103. {
  104. signatureBytes = rsaCsp.SignData(dataBytes, "SHA1");
  105. }
  106. }
  107. catch (Exception ex)
  108. {
  109. throw new AopException("您使用的私钥格式错误,请检查RSA私钥配置" + ",charset = " + charset);
  110. }
  111. return Convert.ToBase64String(signatureBytes);
  112. }
  113. public static bool RSACheckV1(IDictionary<string, string> parameters, string publicKeyPem, string charset)
  114. {
  115. string sign = parameters["sign"];
  116. parameters.Remove("sign");
  117. parameters.Remove("sign_type");
  118. string signContent = GetSignContent(parameters);
  119. return RSACheckContent(signContent, sign, publicKeyPem, charset, "RSA");
  120. }
  121. public static bool RSACheckV1(IDictionary<string, string> parameters, string publicKeyPem)
  122. {
  123. string sign = parameters["sign"];
  124. parameters.Remove("sign");
  125. parameters.Remove("sign_type");
  126. string signContent = GetSignContent(parameters);
  127. return RSACheckContent(signContent, sign, publicKeyPem, DEFAULT_CHARSET, "RSA");
  128. }
  129. public static bool RSACheckV1(IDictionary<string, string> parameters, string publicKeyPem, string charset, string signType, bool keyFromFile)
  130. {
  131. string sign = parameters["sign"];
  132. parameters.Remove("sign");
  133. parameters.Remove("sign_type");
  134. string signContent = GetSignContent(parameters);
  135. return RSACheckContent(signContent, sign, publicKeyPem, charset, signType, keyFromFile);
  136. }
  137. public static bool RSACheckV2(IDictionary<string, string> parameters, string publicKeyPem)
  138. {
  139. string sign = parameters["sign"];
  140. parameters.Remove("sign");
  141. string signContent = GetSignContent(parameters);
  142. return RSACheckContent(signContent, sign, publicKeyPem, DEFAULT_CHARSET, "RSA");
  143. }
  144. public static bool RSACheckV2(IDictionary<string, string> parameters, string publicKeyPem, string charset)
  145. {
  146. string sign = parameters["sign"];
  147. parameters.Remove("sign");
  148. string signContent = GetSignContent(parameters);
  149. return RSACheckContent(signContent, sign, publicKeyPem, charset, "RSA");
  150. }
  151. public static bool RSACheckV2(IDictionary<string, string> parameters, string publicKeyPem, string charset, string signType, bool keyFromFile)
  152. {
  153. string sign = parameters["sign"];
  154. parameters.Remove("sign");
  155. string signContent = GetSignContent(parameters);
  156. return RSACheckContent(signContent, sign, publicKeyPem, charset, signType, keyFromFile);
  157. }
  158. public static bool RSACheckContent(string signContent, string sign, string publicKeyPem, string charset, string signType)
  159. {
  160. try
  161. {
  162. if (string.IsNullOrEmpty(charset))
  163. {
  164. charset = DEFAULT_CHARSET;
  165. }
  166. if ("RSA2".Equals(signType))
  167. {
  168. string sPublicKeyPEM = File.ReadAllText(publicKeyPem);
  169. RSACryptoServiceProvider rsa = new RSACryptoServiceProvider();
  170. rsa.PersistKeyInCsp = false;
  171. RSACryptoServiceProviderExtension.LoadPublicKeyPEM(rsa, sPublicKeyPEM);
  172. bool bVerifyResultOriginal = rsa.VerifyData(Encoding.GetEncoding(charset).GetBytes(signContent), "SHA256", Convert.FromBase64String(sign));
  173. return bVerifyResultOriginal;
  174. }
  175. else
  176. {
  177. string sPublicKeyPEM = File.ReadAllText(publicKeyPem);
  178. RSACryptoServiceProvider rsa = new RSACryptoServiceProvider();
  179. rsa.PersistKeyInCsp = false;
  180. RSACryptoServiceProviderExtension.LoadPublicKeyPEM(rsa, sPublicKeyPEM);
  181. SHA1CryptoServiceProvider sha1 = new SHA1CryptoServiceProvider();
  182. bool bVerifyResultOriginal = rsa.VerifyData(Encoding.GetEncoding(charset).GetBytes(signContent), sha1, Convert.FromBase64String(sign));
  183. return bVerifyResultOriginal;
  184. }
  185. }
  186. catch
  187. {
  188. return false;
  189. }
  190. }
  191. public static bool RSACheckContent(string signContent, string sign, string publicKeyPem, string charset, string signType, bool keyFromFile)
  192. {
  193. try
  194. {
  195. if (string.IsNullOrEmpty(charset))
  196. {
  197. charset = DEFAULT_CHARSET;
  198. }
  199. string sPublicKeyPEM;
  200. if (keyFromFile)
  201. {
  202. sPublicKeyPEM = File.ReadAllText(publicKeyPem);
  203. }
  204. else
  205. {
  206. sPublicKeyPEM = "-----BEGIN PUBLIC KEY-----\r\n";
  207. sPublicKeyPEM += publicKeyPem;
  208. sPublicKeyPEM += "-----END PUBLIC KEY-----\r\n\r\n";
  209. }
  210. if ("RSA2".Equals(signType))
  211. {
  212. RSACryptoServiceProvider rsa = new RSACryptoServiceProvider();
  213. rsa.PersistKeyInCsp = false;
  214. RSACryptoServiceProviderExtension.LoadPublicKeyPEM(rsa, sPublicKeyPEM);
  215. bool bVerifyResultOriginal = rsa.VerifyData(Encoding.GetEncoding(charset).GetBytes(signContent), "SHA256", Convert.FromBase64String(sign));
  216. return bVerifyResultOriginal;
  217. }
  218. else
  219. {
  220. RSACryptoServiceProvider rsa = new RSACryptoServiceProvider();
  221. rsa.PersistKeyInCsp = false;
  222. RSACryptoServiceProviderExtension.LoadPublicKeyPEM(rsa, sPublicKeyPEM);
  223. SHA1CryptoServiceProvider sha1 = new SHA1CryptoServiceProvider();
  224. bool bVerifyResultOriginal = rsa.VerifyData(Encoding.GetEncoding(charset).GetBytes(signContent), sha1, Convert.FromBase64String(sign));
  225. return bVerifyResultOriginal;
  226. }
  227. }
  228. catch
  229. {
  230. return false;
  231. }
  232. }
  233. public static bool RSACheckContent(string signContent, string sign, string publicKeyPem, string charset, bool keyFromFile)
  234. {
  235. try
  236. {
  237. string sPublicKeyPEM;
  238. if (keyFromFile)
  239. {
  240. sPublicKeyPEM = File.ReadAllText(publicKeyPem);
  241. }
  242. else
  243. {
  244. sPublicKeyPEM = "-----BEGIN PUBLIC KEY-----\r\n";
  245. sPublicKeyPEM = sPublicKeyPEM + publicKeyPem;
  246. sPublicKeyPEM = sPublicKeyPEM + "-----END PUBLIC KEY-----\r\n\r\n";
  247. }
  248. RSACryptoServiceProvider rsa = new RSACryptoServiceProvider();
  249. rsa.PersistKeyInCsp = false;
  250. RSACryptoServiceProviderExtension.LoadPublicKeyPEM(rsa, sPublicKeyPEM);
  251. SHA1CryptoServiceProvider sha1 = new SHA1CryptoServiceProvider();
  252. if (string.IsNullOrEmpty(charset))
  253. {
  254. charset = DEFAULT_CHARSET;
  255. }
  256. bool bVerifyResultOriginal = rsa.VerifyData(Encoding.GetEncoding(charset).GetBytes(signContent), sha1, Convert.FromBase64String(sign));
  257. return bVerifyResultOriginal;
  258. }
  259. catch (Exception ex)
  260. {
  261. string s = ex.Message.ToString();
  262. return false;
  263. }
  264. }
  265. public static string CheckSignAndDecrypt(IDictionary<string, string> parameters, string alipayPublicKey,
  266. string cusPrivateKey, bool isCheckSign,
  267. bool isDecrypt)
  268. {
  269. string charset = parameters["charset"];
  270. string bizContent = parameters["biz_content"];
  271. if (isCheckSign)
  272. {
  273. if (!RSACheckV2(parameters, alipayPublicKey, charset))
  274. {
  275. throw new AopException("rsaCheck failure:rsaParams=" + parameters);
  276. }
  277. }
  278. if (isDecrypt)
  279. {
  280. return RSADecrypt(bizContent, cusPrivateKey, charset, "RSA");
  281. }
  282. return bizContent;
  283. }
  284. public static string encryptAndSign(string bizContent, string alipayPublicKey,
  285. string cusPrivateKey, string charset, bool isEncrypt,
  286. bool isSign)
  287. {
  288. StringBuilder sb = new StringBuilder();
  289. if (string.IsNullOrEmpty(charset))
  290. {
  291. charset = DEFAULT_CHARSET;
  292. }
  293. sb.Append("<?xml version=\"1.0\" encoding=\"" + charset + "\"?>");
  294. if (isEncrypt)
  295. {// 加密
  296. sb.Append("<alipay>");
  297. String encrypted = RSAEncrypt(bizContent, alipayPublicKey, charset);
  298. sb.Append("<response>" + encrypted + "</response>");
  299. sb.Append("<encryption_type>RSA</encryption_type>");
  300. if (isSign)
  301. {
  302. String sign = RSASign(encrypted, cusPrivateKey, charset, "RSA");
  303. sb.Append("<sign>" + sign + "</sign>");
  304. sb.Append("<sign_type>RSA</sign_type>");
  305. }
  306. sb.Append("</alipay>");
  307. }
  308. else if (isSign)
  309. {// 不加密,但需要签名
  310. sb.Append("<alipay>");
  311. sb.Append("<response>" + bizContent + "</response>");
  312. String sign = RSASign(bizContent, cusPrivateKey, charset, "RSA");
  313. sb.Append("<sign>" + sign + "</sign>");
  314. sb.Append("<sign_type>RSA</sign_type>");
  315. sb.Append("</alipay>");
  316. }
  317. else
  318. {// 不加密,不加签
  319. sb.Append(bizContent);
  320. }
  321. return sb.ToString();
  322. }
  323. public static string RSAEncrypt(string content, string publicKeyPem, string charset)
  324. {
  325. try
  326. {
  327. string sPublicKeyPEM = File.ReadAllText(publicKeyPem);
  328. RSACryptoServiceProvider rsa = new RSACryptoServiceProvider();
  329. rsa.PersistKeyInCsp = false;
  330. RSACryptoServiceProviderExtension.LoadPublicKeyPEM(rsa, sPublicKeyPEM);
  331. if (string.IsNullOrEmpty(charset))
  332. {
  333. charset = DEFAULT_CHARSET;
  334. }
  335. byte[] data = Encoding.GetEncoding(charset).GetBytes(content);
  336. int maxBlockSize = rsa.KeySize / 8 - 11; //加密块最大长度限制
  337. if (data.Length <= maxBlockSize)
  338. {
  339. byte[] cipherbytes = rsa.Encrypt(data, false);
  340. return Convert.ToBase64String(cipherbytes);
  341. }
  342. MemoryStream plaiStream = new MemoryStream(data);
  343. MemoryStream crypStream = new MemoryStream();
  344. Byte[] buffer = new Byte[maxBlockSize];
  345. int blockSize = plaiStream.Read(buffer, 0, maxBlockSize);
  346. while (blockSize > 0)
  347. {
  348. Byte[] toEncrypt = new Byte[blockSize];
  349. Array.Copy(buffer, 0, toEncrypt, 0, blockSize);
  350. Byte[] cryptograph = rsa.Encrypt(toEncrypt, false);
  351. crypStream.Write(cryptograph, 0, cryptograph.Length);
  352. blockSize = plaiStream.Read(buffer, 0, maxBlockSize);
  353. }
  354. return Convert.ToBase64String(crypStream.ToArray(), Base64FormattingOptions.None);
  355. }
  356. catch (Exception ex)
  357. {
  358. throw new AopException("EncryptContent = " + content + ",charset = " + charset, ex);
  359. }
  360. }
  361. public static string RSADecrypt(string content, string privateKeyPem, string charset, string signType)
  362. {
  363. try
  364. {
  365. RSACryptoServiceProvider rsaCsp = LoadCertificateFile(privateKeyPem, signType);
  366. if (string.IsNullOrEmpty(charset))
  367. {
  368. charset = DEFAULT_CHARSET;
  369. }
  370. byte[] data = Convert.FromBase64String(content);
  371. int maxBlockSize = rsaCsp.KeySize / 8; //解密块最大长度限制
  372. if (data.Length <= maxBlockSize)
  373. {
  374. byte[] cipherbytes = rsaCsp.Decrypt(data, false);
  375. return Encoding.GetEncoding(charset).GetString(cipherbytes);
  376. }
  377. MemoryStream crypStream = new MemoryStream(data);
  378. MemoryStream plaiStream = new MemoryStream();
  379. Byte[] buffer = new Byte[maxBlockSize];
  380. int blockSize = crypStream.Read(buffer, 0, maxBlockSize);
  381. while (blockSize > 0)
  382. {
  383. Byte[] toDecrypt = new Byte[blockSize];
  384. Array.Copy(buffer, 0, toDecrypt, 0, blockSize);
  385. Byte[] cryptograph = rsaCsp.Decrypt(toDecrypt, false);
  386. plaiStream.Write(cryptograph, 0, cryptograph.Length);
  387. blockSize = crypStream.Read(buffer, 0, maxBlockSize);
  388. }
  389. return Encoding.GetEncoding(charset).GetString(plaiStream.ToArray());
  390. }
  391. catch (Exception ex)
  392. {
  393. throw new AopException("DecryptContent = " + content + ",charset = " + charset, ex);
  394. }
  395. }
  396. private static byte[] GetPem(string type, byte[] data)
  397. {
  398. string pem = Encoding.UTF8.GetString(data);
  399. string header = String.Format("-----BEGIN {0}-----\\n", type);
  400. string footer = String.Format("-----END {0}-----", type);
  401. int start = pem.IndexOf(header) + header.Length;
  402. int end = pem.IndexOf(footer, start);
  403. string base64 = pem.Substring(start, (end - start));
  404. return Convert.FromBase64String(base64);
  405. }
  406. private static RSACryptoServiceProvider LoadCertificateFile(string filename, string signType)
  407. {
  408. using (System.IO.FileStream fs = System.IO.File.OpenRead(filename))
  409. {
  410. byte[] data = new byte[fs.Length];
  411. byte[] res = null;
  412. fs.Read(data, 0, data.Length);
  413. if (data[0] != 0x30)
  414. {
  415. res = GetPem("RSA PRIVATE KEY", data);
  416. }
  417. try
  418. {
  419. RSACryptoServiceProvider rsa = DecodeRSAPrivateKey(res, signType);
  420. return rsa;
  421. }
  422. catch (Exception ex)
  423. {
  424. }
  425. return null;
  426. }
  427. }
  428. private static RSACryptoServiceProvider LoadCertificateString(string strKey, string signType)
  429. {
  430. byte[] data = null;
  431. //读取带
  432. //ata = Encoding.Default.GetBytes(strKey);
  433. data = Convert.FromBase64String(strKey);
  434. //data = GetPem("RSA PRIVATE KEY", data);
  435. try
  436. {
  437. RSACryptoServiceProvider rsa = DecodeRSAPrivateKey(data, signType);
  438. return rsa;
  439. }
  440. catch (Exception ex)
  441. {
  442. // throw new AopException("EncryptContent = woshihaoren,zheshiyigeceshi,wanerde", ex);
  443. }
  444. return null;
  445. }
  446. private static RSACryptoServiceProvider DecodeRSAPrivateKey(byte[] privkey, string signType)
  447. {
  448. byte[] MODULUS, E, D, P, Q, DP, DQ, IQ;
  449. // --------- Set up stream to decode the asn.1 encoded RSA private key ------
  450. MemoryStream mem = new MemoryStream(privkey);
  451. BinaryReader binr = new BinaryReader(mem); //wrap Memory Stream with BinaryReader for easy reading
  452. byte bt = 0;
  453. ushort twobytes = 0;
  454. int elems = 0;
  455. try
  456. {
  457. twobytes = binr.ReadUInt16();
  458. if (twobytes == 0x8130) //data read as little endian order (actual data order for Sequence is 30 81)
  459. binr.ReadByte(); //advance 1 byte
  460. else if (twobytes == 0x8230)
  461. binr.ReadInt16(); //advance 2 bytes
  462. else
  463. return null;
  464. twobytes = binr.ReadUInt16();
  465. if (twobytes != 0x0102) //version number
  466. return null;
  467. bt = binr.ReadByte();
  468. if (bt != 0x00)
  469. return null;
  470. //------ all private key components are Integer sequences ----
  471. elems = GetIntegerSize(binr);
  472. MODULUS = binr.ReadBytes(elems);
  473. elems = GetIntegerSize(binr);
  474. E = binr.ReadBytes(elems);
  475. elems = GetIntegerSize(binr);
  476. D = binr.ReadBytes(elems);
  477. elems = GetIntegerSize(binr);
  478. P = binr.ReadBytes(elems);
  479. elems = GetIntegerSize(binr);
  480. Q = binr.ReadBytes(elems);
  481. elems = GetIntegerSize(binr);
  482. DP = binr.ReadBytes(elems);
  483. elems = GetIntegerSize(binr);
  484. DQ = binr.ReadBytes(elems);
  485. elems = GetIntegerSize(binr);
  486. IQ = binr.ReadBytes(elems);
  487. // ------- create RSACryptoServiceProvider instance and initialize with public key -----
  488. CspParameters CspParameters = new CspParameters();
  489. CspParameters.Flags = CspProviderFlags.UseMachineKeyStore;
  490. int bitLen = 1024;
  491. if ("RSA2".Equals(signType))
  492. {
  493. bitLen = 2048;
  494. }
  495. RSACryptoServiceProvider RSA = new RSACryptoServiceProvider(bitLen, CspParameters);
  496. RSAParameters RSAparams = new RSAParameters();
  497. RSAparams.Modulus = MODULUS;
  498. RSAparams.Exponent = E;
  499. RSAparams.D = D;
  500. RSAparams.P = P;
  501. RSAparams.Q = Q;
  502. RSAparams.DP = DP;
  503. RSAparams.DQ = DQ;
  504. RSAparams.InverseQ = IQ;
  505. RSA.ImportParameters(RSAparams);
  506. return RSA;
  507. }
  508. catch (Exception ex)
  509. {
  510. return null;
  511. }
  512. finally
  513. {
  514. binr.Close();
  515. }
  516. }
  517. private static int GetIntegerSize(BinaryReader binr)
  518. {
  519. byte bt = 0;
  520. byte lowbyte = 0x00;
  521. byte highbyte = 0x00;
  522. int count = 0;
  523. bt = binr.ReadByte();
  524. if (bt != 0x02) //expect integer
  525. return 0;
  526. bt = binr.ReadByte();
  527. if (bt == 0x81)
  528. count = binr.ReadByte(); // data size in next byte
  529. else
  530. if (bt == 0x82)
  531. {
  532. highbyte = binr.ReadByte(); // data size in next 2 bytes
  533. lowbyte = binr.ReadByte();
  534. byte[] modint = { lowbyte, highbyte, 0x00, 0x00 };
  535. count = BitConverter.ToInt32(modint, 0);
  536. }
  537. else
  538. {
  539. count = bt; // we already have the data size
  540. }
  541. while (binr.ReadByte() == 0x00)
  542. { //remove high order zeros in data
  543. count -= 1;
  544. }
  545. binr.BaseStream.Seek(-1, SeekOrigin.Current); //last ReadByte wasn't a removed zero, so back up a byte
  546. return count;
  547. }
  548. }
  549. }