Stufe 4c (#764): Bezeichner auf Englisch - Typen, Methoden, Felder, Parameter, Locals, Testnamen

Mit Roslyn umbenannt (Verweise folgen, Zeichenketten bleiben unberuehrt).
Nicht umbenannt, weil gespeichert oder ueber die API gebunden (Stufe 4e):
Properties, Record-Parameter, Enum-Member sowie die Parameter der
Endpunkt-Handler (Routen-/Query-Bindung ueber den Namen). Die JSON-Felder
anonymer Objekte bleiben ausdruecklich benannt (JsonFilter: pfad).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
Richard
2026-10-04 13:18:43 +02:00
co-authored by Claude Opus 5.5
parent 837a634a22
commit 77062facc9
190 changed files with 4813 additions and 4813 deletions
@@ -29,7 +29,7 @@ public sealed class SecretKeyRingTests : IDisposable
catch { /* A leftover test folder does not turn a run red. */ }
}
private static SecretKeyRing Bund(params ISecretProvider[] anbieter) => new(anbieter);
private static SecretKeyRing Ring(params ISecretProvider[] provider) => new(provider);
/// <summary>
/// The heart of the matter: two slots, one key.
@@ -38,18 +38,18 @@ public sealed class SecretKeyRingTests : IDisposable
/// recovery path would then open something, but not the existing values.</para>
/// </summary>
[Fact]
public void Zwei_Faecher_fuehren_zu_demselben_Schluessel()
public void Two_slots_lead_to_the_same_key()
{
var maschine = new PlainFileSecretProvider();
var bund = Bund(maschine, PassphraseSecretProvider.With("geheim"));
var machine = new PlainFileSecretProvider();
var ring = Ring(machine, PassphraseSecretProvider.With("geheim"));
var schluessel = bund.Load(Pfad);
bund.SetRecoveryPassphrase(Pfad, schluessel, "geheim");
var key = ring.Load(Pfad);
ring.SetRecoveryPassphrase(Pfad, key, "geheim");
// Only with the passphrase, without the machine slot - the move.
var nachUmzug = Bund(PassphraseSecretProvider.With("geheim")).Load(Pfad);
var afterMove = Ring(PassphraseSecretProvider.With("geheim")).Load(Pfad);
nachUmzug.ShouldBe(schluessel);
afterMove.ShouldBe(key);
}
/// <summary>
@@ -59,15 +59,15 @@ public sealed class SecretKeyRingTests : IDisposable
/// all credentials would be lost here.</para>
/// </summary>
[Fact]
public void Nach_einem_Maschinenwechsel_oeffnet_die_Passphrase()
public void After_a_machine_change_the_passphrase_opens()
{
var bund = Bund(new NieOeffnendesFach(), PassphraseSecretProvider.With("umzug"));
var schluessel = bund.Load(Pfad);
var ring = Ring(new NeverOpeningSlot(), PassphraseSecretProvider.With("umzug"));
var key = ring.Load(Pfad);
bund.SetRecoveryPassphrase(Pfad, schluessel, "umzug");
ring.SetRecoveryPassphrase(Pfad, key, "umzug");
var neueMaschine = Bund(new NieOeffnendesFach(), PassphraseSecretProvider.With("umzug"));
neueMaschine.Load(Pfad).ShouldBe(schluessel);
var newMachine = Ring(new NeverOpeningSlot(), PassphraseSecretProvider.With("umzug"));
newMachine.Load(Pfad).ShouldBe(key);
}
/// <summary>
@@ -79,19 +79,19 @@ public sealed class SecretKeyRingTests : IDisposable
/// <em>not</em> happen — see <see cref="Ein_Umzug_legt_den_Schluessel_nicht_im_Klartext_ab"/>.</para>
/// </summary>
[Fact]
public void Nach_dem_Umzug_entsteht_das_Maschinenfach_neu()
public void After_the_move_the_machine_slot_is_created_anew()
{
var bund = Bund(new NieOeffnendesFach(), PassphraseSecretProvider.With("umzug"));
var schluessel = bund.Load(Pfad);
bund.SetRecoveryPassphrase(Pfad, schluessel, "umzug");
var ring = Ring(new NeverOpeningSlot(), PassphraseSecretProvider.With("umzug"));
var key = ring.Load(Pfad);
ring.SetRecoveryPassphrase(Pfad, key, "umzug");
// New machine with a working machine slot: it does not open yet,
// but the passphrase does - and afterwards the slot is created.
var neueMaschine = Bund(new MaschinenFach(), PassphraseSecretProvider.With("umzug"));
neueMaschine.Load(Pfad).ShouldBe(schluessel);
var newMachine = Ring(new MachineSlot(), PassphraseSecretProvider.With("umzug"));
newMachine.Load(Pfad).ShouldBe(key);
// From now on the machine slot alone suffices, without a passphrase.
Bund(new MaschinenFach()).Load(Pfad).ShouldBe(schluessel);
Ring(new MachineSlot()).Load(Pfad).ShouldBe(key);
}
/// <summary>
@@ -105,15 +105,15 @@ public sealed class SecretKeyRingTests : IDisposable
[Fact]
public void Ein_Umzug_legt_den_Schluessel_nicht_im_Klartext_ab()
{
var bund = Bund(new NieOeffnendesFach(), PassphraseSecretProvider.With("umzug"));
var schluessel = bund.Load(Pfad);
bund.SetRecoveryPassphrase(Pfad, schluessel, "umzug");
var ring = Ring(new NeverOpeningSlot(), PassphraseSecretProvider.With("umzug"));
var key = ring.Load(Pfad);
ring.SetRecoveryPassphrase(Pfad, key, "umzug");
var ohneMaschinenfach = Bund(
var withoutMachineSlot = Ring(
new PlainFileSecretProvider(), PassphraseSecretProvider.With("umzug"));
ohneMaschinenfach.Load(Pfad).ShouldBe(schluessel);
ohneMaschinenfach.Slots.ShouldNotContain(s => s.Provider == "file");
withoutMachineSlot.Load(Pfad).ShouldBe(key);
withoutMachineSlot.Slots.ShouldNotContain(s => s.Provider == "file");
}
/// <summary>
@@ -121,15 +121,15 @@ public sealed class SecretKeyRingTests : IDisposable
/// key.
/// </summary>
[Fact]
public void Eine_falsche_Passphrase_oeffnet_nichts()
public void A_wrong_passphrase_opens_nothing()
{
var bund = Bund(new NieOeffnendesFach(), PassphraseSecretProvider.With("richtig"));
var schluessel = bund.Load(Pfad);
bund.SetRecoveryPassphrase(Pfad, schluessel, "richtig");
var ring = Ring(new NeverOpeningSlot(), PassphraseSecretProvider.With("richtig"));
var key = ring.Load(Pfad);
ring.SetRecoveryPassphrase(Pfad, key, "richtig");
var falsch = Bund(new NieOeffnendesFach(), PassphraseSecretProvider.With("falsch"));
var wrong = Ring(new NeverOpeningSlot(), PassphraseSecretProvider.With("falsch"));
Should.Throw<CryptographicException>(() => falsch.Load(Pfad));
Should.Throw<CryptographicException>(() => wrong.Load(Pfad));
}
/// <summary>
@@ -141,14 +141,14 @@ public sealed class SecretKeyRingTests : IDisposable
/// credentials without anyone seeing the connection.</para>
/// </summary>
[Fact]
public void Wenn_kein_Fach_aufgeht_wird_abgebrochen_statt_neu_erzeugt()
public void If_no_slot_opens_it_aborts_instead_of_regenerating()
{
Bund(new PlainFileSecretProvider()).Load(Pfad);
var vorher = File.ReadAllBytes(Pfad);
Ring(new PlainFileSecretProvider()).Load(Pfad);
var before = File.ReadAllBytes(Pfad);
Should.Throw<CryptographicException>(() => Bund(new NieOeffnendesFach()).Load(Pfad));
Should.Throw<CryptographicException>(() => Ring(new NeverOpeningSlot()).Load(Pfad));
File.ReadAllBytes(Pfad).ShouldBe(vorher, "Die Datei darf dabei nicht angefasst werden.");
File.ReadAllBytes(Pfad).ShouldBe(before, "Die Datei darf dabei nicht angefasst werden.");
}
/// <summary>
@@ -156,23 +156,23 @@ public sealed class SecretKeyRingTests : IDisposable
/// it fit for backups.
/// </summary>
[Fact]
public void Mit_Passphrase_steht_der_Schluessel_nirgends_im_Klartext()
public void With_passphrase_the_key_is_nowhere_in_plaintext()
{
var bund = Bund(new DpapiSecretProvider(), PassphraseSecretProvider.With("geheim"),
var ring = Ring(new DpapiSecretProvider(), PassphraseSecretProvider.With("geheim"),
new PlainFileSecretProvider());
var schluessel = bund.Load(Pfad);
bund.SetRecoveryPassphrase(Pfad, schluessel, "geheim");
var key = ring.Load(Pfad);
ring.SetRecoveryPassphrase(Pfad, key, "geheim");
var inhalt = File.ReadAllText(Pfad);
var klartext = Convert.ToBase64String(schluessel);
var content = File.ReadAllText(Pfad);
var plaintext = Convert.ToBase64String(key);
inhalt.ShouldNotContain(klartext);
content.ShouldNotContain(plaintext);
if (OperatingSystem.IsWindows())
{
// With a machine slot the unprotected one drops away.
inhalt.ShouldNotContain("\"file\"");
content.ShouldNotContain("\"file\"");
}
}
@@ -181,39 +181,39 @@ public sealed class SecretKeyRingTests : IDisposable
/// one day. That's why it is named beforehand.
/// </summary>
[Fact]
public void Ein_Bund_ohne_Wiederherstellung_meldet_das()
public void A_ring_without_recovery_reports_it()
{
var bund = Bund(new PlainFileSecretProvider());
bund.Load(Pfad);
var ring = Ring(new PlainFileSecretProvider());
ring.Load(Pfad);
bund.Problems.ShouldNotBeEmpty();
bund.Problems.ShouldContain(p => p.Contains("Wiederherstellungsfach"));
bund.Problems.ShouldContain(p => p.Contains("ungeschützt"));
ring.Problems.ShouldNotBeEmpty();
ring.Problems.ShouldContain(p => p.Contains("Wiederherstellungsfach"));
ring.Problems.ShouldContain(p => p.Contains("ungeschützt"));
}
[Fact]
public void Mit_Passphrase_ist_der_Bund_in_Ordnung()
public void With_passphrase_the_ring_is_fine()
{
var bund = Bund(new DpapiSecretProvider(), PassphraseSecretProvider.With("geheim"),
var ring = Ring(new DpapiSecretProvider(), PassphraseSecretProvider.With("geheim"),
new PlainFileSecretProvider());
var schluessel = bund.Load(Pfad);
bund.SetRecoveryPassphrase(Pfad, schluessel, "geheim");
var key = ring.Load(Pfad);
ring.SetRecoveryPassphrase(Pfad, key, "geheim");
bund.Problems.ShouldNotContain(p => p.Contains("Wiederherstellungsfach"));
ring.Problems.ShouldNotContain(p => p.Contains("Wiederherstellungsfach"));
}
/// <summary>
/// Without a passphrase no recovery slot comes about — there is nothing to make it with.
/// </summary>
[Fact]
public void Ohne_Passphrase_gibt_es_kein_Wiederherstellungsfach()
public void Without_passphrase_there_is_no_recovery_slot()
{
var bund = Bund(new PlainFileSecretProvider(), new PassphraseSecretProvider(() => null));
bund.Load(Pfad);
var ring = Ring(new PlainFileSecretProvider(), new PassphraseSecretProvider(() => null));
ring.Load(Pfad);
bund.Slots.ShouldNotContain(s => s.Provider == "passphrase");
bund.Slots.ShouldContain(s => s.Provider == "file");
ring.Slots.ShouldNotContain(s => s.Provider == "passphrase");
ring.Slots.ShouldContain(s => s.Provider == "file");
}
/// <summary>
@@ -225,25 +225,25 @@ public sealed class SecretKeyRingTests : IDisposable
/// should please store a passphrase.</para>
/// </summary>
[Fact]
public void Eine_bereitstehende_Passphrase_wird_nachtraeglich_uebernommen()
public void A_ready_passphrase_is_adopted_afterwards()
{
// First without: only the unprotected slot comes about.
Bund(new PlainFileSecretProvider(), new PassphraseSecretProvider(() => null)).Load(Pfad);
Ring(new PlainFileSecretProvider(), new PassphraseSecretProvider(() => null)).Load(Pfad);
// Then with: the recovery slot is added, the unprotected one drops away.
var mit = Bund(new PlainFileSecretProvider(), PassphraseSecretProvider.With("spaeter"));
var schluessel = mit.Load(Pfad);
var withValue = Ring(new PlainFileSecretProvider(), PassphraseSecretProvider.With("spaeter"));
var key = withValue.Load(Pfad);
mit.Slots.ShouldContain(s => s.Provider == "passphrase");
withValue.Slots.ShouldContain(s => s.Provider == "passphrase");
// The unprotected slot stays: the automatic path takes nothing away. Removing
// it because an environment variable happens to be set would be an
// irreversible change nobody asked for.
mit.Slots.ShouldContain(s => s.Provider == "file");
mit.Problems.ShouldContain(p => p.Contains("ungeschützt"));
withValue.Slots.ShouldContain(s => s.Provider == "file");
withValue.Problems.ShouldContain(p => p.Contains("ungeschützt"));
// And it is the same key as before.
Bund(PassphraseSecretProvider.With("spaeter")).Load(Pfad).ShouldBe(schluessel);
Ring(PassphraseSecretProvider.With("spaeter")).Load(Pfad).ShouldBe(key);
}
// ─── Taking over the legacy formats ───
@@ -253,12 +253,12 @@ public sealed class SecretKeyRingTests : IDisposable
/// nothing — the same key, just wrapped differently.
/// </summary>
[Fact]
public void Ein_roher_Altschluessel_wird_uebernommen()
public void A_raw_legacy_key_is_adopted()
{
var alt = RandomNumberGenerator.GetBytes(32);
File.WriteAllBytes(Pfad, alt);
var old = RandomNumberGenerator.GetBytes(32);
File.WriteAllBytes(Pfad, old);
Bund(new PlainFileSecretProvider()).Load(Pfad).ShouldBe(alt);
Ring(new PlainFileSecretProvider()).Load(Pfad).ShouldBe(old);
}
/// <summary>
@@ -266,21 +266,21 @@ public sealed class SecretKeyRingTests : IDisposable
/// is gone, the value the same.
/// </summary>
[Fact]
public void Nach_der_Uebernahme_steht_das_Faecherformat_in_der_Datei()
public void After_adoption_the_slot_format_is_in_the_file()
{
var alt = RandomNumberGenerator.GetBytes(32);
File.WriteAllBytes(Pfad, alt);
var old = RandomNumberGenerator.GetBytes(32);
File.WriteAllBytes(Pfad, old);
var bund = Bund(new PlainFileSecretProvider(), PassphraseSecretProvider.With("neu"));
var schluessel = bund.Load(Pfad);
bund.SetRecoveryPassphrase(Pfad, schluessel, "neu");
var ring = Ring(new PlainFileSecretProvider(), PassphraseSecretProvider.With("neu"));
var key = ring.Load(Pfad);
ring.SetRecoveryPassphrase(Pfad, key, "neu");
var datei = JsonSerializer.Deserialize<SecretKeyRingFile>(File.ReadAllText(Pfad))!;
datei.Version.ShouldBe(3);
datei.Slots.ShouldContain(s => s.Provider == "passphrase");
// And the value has not changed - otherwise all enc:v2 values would be lost.
Bund(PassphraseSecretProvider.With("neu")).Load(Pfad).ShouldBe(alt);
Ring(PassphraseSecretProvider.With("neu")).Load(Pfad).ShouldBe(old);
}
/// <summary>
@@ -288,15 +288,15 @@ public sealed class SecretKeyRingTests : IDisposable
/// encrypted values unreadable without anyone finding out why.
/// </summary>
[Fact]
public void Eine_beschaedigte_Datei_wird_nicht_stillschweigend_ersetzt()
public void A_damaged_file_is_not_replaced_silently()
{
File.WriteAllBytes(Pfad, RandomNumberGenerator.GetBytes(17));
Should.Throw<CryptographicException>(() => Bund(new PlainFileSecretProvider()).Load(Pfad));
Should.Throw<CryptographicException>(() => Ring(new PlainFileSecretProvider()).Load(Pfad));
}
/// <summary>A machine slot that works here — the substitute for DPAPI in the test.</summary>
private sealed class MaschinenFach : ISecretProvider
private sealed class MachineSlot : ISecretProvider
{
public string Name => "dpapi";
public string Description => "Maschinenfach (Test)";
@@ -311,7 +311,7 @@ public sealed class SecretKeyRingTests : IDisposable
}
/// <summary>A slot that never opens — the new machine, the foreign user account.</summary>
private sealed class NieOeffnendesFach : ISecretProvider
private sealed class NeverOpeningSlot : ISecretProvider
{
public string Name => "dpapi";
public string Description => "Maschinenfach (Test: geht nie auf)";