public string crypt(string str, PasswordSecure pwd = null) { if (pwd == null) { pwd = key; } var sha = new SHA3(str.Length); if (random == null) { var inits = str + DateTime.Now.ToString("r"); var t = new UTF32Encoding().GetBytes(inits); var bbi = new BytesBuilder(); bbi.add(t); bbi.add(sha.CreateInitVector(0, 64, 40)); var init = bbi.getBytes(); random = new SHA3.SHA3Random(init); bbi.clear(); BytesBuilder.ClearString(inits); BytesBuilder.ToNull(init); } var bytes = new UTF32Encoding().GetBytes(str); var openKey = pwd.getObjectValue(); var crypted = sha.multiCryptLZMA(bytes, openKey, null, 22, false); BytesBuilder.BytesToNull(openKey); BytesBuilder.BytesToNull(bytes); BytesBuilder.ClearString(str); return(Convert.ToBase64String(crypted)); }
// GOST5 = GostRegime - 21 public unsafe byte[] getGamma(long gammaLength, int GOST5 = 0) { if (workingKey == null) { throw new Exception("GOST 28147 mod. gamma not prepared"); } if (gammaLength <= 0) { throw new ArgumentOutOfRangeException("GOST 28147 mod. gammaLenght is incorrect"); } var bb = new BytesBuilder(); int SL = snc.Length & 0x7FFFFFF8; int BL = SL; if (SL > 72) { BL = 64; } bool BL72 = false; byte[] S = null; byte[] SA = null; int tmp72 = 0; int kl = 0; byte[] tmpp = null; keccak.SHA3 sha = null, shaR = null; if (GOST5 > 0) { BL72 = (SL % 72 > 0) && (SL > 71); if (GOST5 < 13) { tmp72 = (SL / 72) * (GOST5 == 1 ? 64 : 16); } else { tmp72 = (SL / 72) * 8; // Хеш возвращает только 8 байтов } S = BytesBuilder.CloneBytes(snc, 0, SL); SA = new byte[SL]; tmpp = new byte[SL + 72]; sha = new SHA3(SL); shaP = new SHA3.SHA3Random(snc); // это не лишнее, получает ключ для инициализирующих перестановок if (GOST5 >= 13) { shaPP = new SHA3.SHA3Random(shaP.nextBytes64()); shaR = new SHA3(SL); } if (SL < 64) { throw new ArgumentException("GOST 28147 mod. sync lenght is incorrect"); } } snc = null; fixed(byte *S1 = currentSBox, S2 = currentSBox2, S3 = currentSBox3, S4 = currentSBox4, S5 = currentSBox5, S6 = currentSBox6) { BytesBuilder.CopyTo(N1, _N3); BytesBuilder.CopyTo(N2, _N3, 4); byte[] k = { 0, 1, 2, 3, 4 }; byte *[] b = { S1, S2, S3, S4, S5, S6 }; if (GOST5 > 0) { if (GOST5 <= 2) { processBlocksForGamma(SL, S, SA, k, b); processBlocksForGamma(SL, SA, S, k, b, true); processBlocksForGamma(SL, S, SA, k, b, true); processBlocksForGamma(SL, SA, S, k, b, true); } else { processBlocksForGamma2(SL, S, SA, k, b, false, GOST5); processBlocksForGamma2(SL, SA, S, k, b, true, GOST5); processBlocksForGamma2(SL, S, SA, k, b, true, GOST5); processBlocksForGamma2(SL, SA, S, k, b, true, GOST5); } sha.getDuplex(S, false, -1, false); if (GOST5 >= 13) { shaR.getDuplex(S, false, -1, false); } } else { // Делаем несколько раз шифрование, на всяк пожарный, хотя это и не по ГОСТу ProcessBlock(_N3, 0, _N4, 0, workingKey[0], S2); ProcessBlock(_N4, 0, _N3, 0, workingKey[1], S3); ProcessBlock(_N3, 0, _N4, 0, workingKey[2], S4); ProcessBlock(_N4, 0, _N3, 0, workingKey[3], S1); ProcessBlock(_N3, 0, _N4, 0, workingKey[2], S3); ProcessBlock(_N4, 0, _N3, 0, workingKey[1], S1); ProcessBlock(_N3, 0, _N4, 0, workingKey[3], S2); ProcessBlock(_N4, 0, _N3, 0, workingKey[0], S4); } BytesBuilder.CopyTo(_N3, N1); BytesBuilder.CopyTo(_N3, N2, 0, 4, 4); long n1 = bytesToint(N1, 0), n2 = bytesToint(N2, 0); int _n1, _n2; int ik = 0; do { if (GOST5 > 0) { byte[] tmp1, tmp2, tmp3; fixed(byte *s = S, sa = SA, tmpp_ = tmpp) { if (GOST5 <= 2) { processBlocksForGamma(SL, S, SA, k, b); } else { processBlocksForGamma2(SL, S, SA, k, b, false, GOST5); } if (GOST5 < 13) { tmp1 = sha.getDuplex(SA, true); } else { tmp1 = shaR.getDuplex(SA, true); } addConstant(s, S.Length); tmp3 = BytesBuilder.CloneBytes(sa, 0, SA.Length); if (GOST5 <= 2) { processBlocksForGamma(SL, S, SA, k, b); } else { processBlocksForGamma2(SL, S, SA, k, b, false, GOST5); } if (GOST5 < 13) fixed(byte *tmp1_ = tmp1, tmp3_ = tmp3) { if (GOST5 > 1) { MergePermutation.permutationMergeBytes(tmp3_, tmp3.Length, sa, tmpp_, SL, ref kl, true); } SHA3.xorBytesWithGamma(SA, tmp1); MergePermutation.permutationMergeBytes(tmp1_, tmp1.Length, sa, tmpp_, SL, ref kl, true); BytesBuilder.ToNull(tmp1.Length, tmp1_); BytesBuilder.ToNull(tmp3.Length, tmp3_); } if (GOST5 < 13) { tmp2 = sha.getDuplex(SA, true, GOST5 == 1 ? 64 : 16); } else { tmp2 = sha.getDuplexMod(SA, tmp1, true, 8, 0); BytesBuilder.ToNull(tmp1); BytesBuilder.ToNull(tmp3); } addConstant(s, S.Length); } if (BL72) { bb.add(BytesBuilder.CloneBytes(tmp2, tmp2.Length - tmp72, tmp72)); BytesBuilder.ToNull(tmp2); } else { bb.add(tmp2); } } else { n1 += 0x1010101; n2 += 0x1010104; if (n2 >= 0x100000000L) { n2 -= 0xFFFFFFFFL; } if (n1 >= 0x100000000L) { n1 -= 0x100000000L; } _n1 = (int)n1; _n2 = (int)n2; intTobytes(_n1, _N3, 0); intTobytes(_n2, _N3, 4); // Получаем новые значения N1; опять не по ГОСТу - 4 преобразования вместо одного ProcessBlock(_N3, 0, _N4, 0, workingKey[2], S1); ProcessBlock(_N4, 0, _N3, 0, workingKey[(ik + 1) & 1], S3); ProcessBlock(_N3, 0, _N4, 0, workingKey[ik & 1], S4); ProcessBlock(_N4, 0, _N3, 0, workingKey[3], S2); bb.addCopy(_N3); } ik++; }while (bb.Count < gammaLength); n1 = 0; n2 = 0; _n1 = 0; _n2 = 0; } for (int i = 0; i < workingKey.Length; i++) { for (int j = 0; j < workingKey[i].Length; j++) { workingKey[i][j] = 0; } } workingKey = null; if (workingKeyA != null) { BytesBuilder.ToNull(workingKeyA); workingKeyA = null; } BytesBuilder.ToNull(N1); BytesBuilder.ToNull(N2); BytesBuilder.ToNull(_N3); BytesBuilder.ToNull(_N4); var result = bb.getBytes(gammaLength); bb.clear(); if (S != null) { BytesBuilder.ToNull(S); BytesBuilder.ToNull(SA); BytesBuilder.ToNull(tmpp); } if (sha != null) { sha.Clear(true); shaP.Clear(); sha = null; shaP = null; if (shaPP != null) { shaPP.Clear(); shaPP = null; } } return(result); }