private static AsnWriter RewriteEncryptedPkcs8PrivateKey( AsymmetricAlgorithm key, ReadOnlySpan <char> password, PbeParameters pbeParameters) { Debug.Assert(pbeParameters != null); byte[] rented = CryptoPool.Rent(key.KeySize); int rentWritten = 0; try { while (!key.TryExportEncryptedPkcs8PrivateKey( password, s_platformParameters, rented, out rentWritten)) { int size = rented.Length; byte[] current = rented; rented = CryptoPool.Rent(checked (size * 2)); CryptoPool.Return(current, rentWritten); } return(KeyFormatHelper.ReencryptPkcs8( password, rented.AsMemory(0, rentWritten), password, pbeParameters)); } finally { CryptoPool.Return(rented, rentWritten); } }
private static AsnWriter RewriteEncryptedPkcs8PrivateKey( AsymmetricAlgorithm key, ReadOnlySpan <byte> passwordBytes, PbeParameters pbeParameters) { Debug.Assert(pbeParameters != null); // For RSA: // * 512-bit key needs ~400 bytes // * 16384-bit key needs ~10k bytes. // * KeySize (bits) should avoid re-rent. // // For DSA: // * 512-bit key needs ~300 bytes. // * 1024-bit key needs ~400 bytes. // * 2048-bit key needs ~700 bytes. // * KeySize (bits) should avoid re-rent. // // For ECC: // * secp256r1 needs ~200 bytes (named) or ~450 (explicit) // * secp384r1 needs ~250 bytes (named) or ~600 (explicit) // * secp521r1 needs ~300 bytes (named) or ~730 (explicit) // * KeySize (bits) should avoid re-rent for named, and probably // gets one re-rent for explicit. byte[] rented = ArrayPool <byte> .Shared.Rent(key.KeySize); int rentWritten = 0; // If we use 6 bits from each byte, that's 22 * 6 = 132 Span <char> randomString = stackalloc char[22]; try { FillRandomAsciiString(randomString); while (!key.TryExportEncryptedPkcs8PrivateKey( randomString, s_platformParameters, rented, out rentWritten)) { int size = rented.Length; ArrayPool <byte> .Shared.Return(rented); rented = ArrayPool <byte> .Shared.Rent(checked (size * 2)); } return(KeyFormatHelper.ReencryptPkcs8( randomString, rented.AsMemory(0, rentWritten), passwordBytes, pbeParameters)); } finally { randomString.Clear(); CryptographicOperations.ZeroMemory(rented.AsSpan(0, rentWritten)); ArrayPool <byte> .Shared.Return(rented); } }