DEV Community

Cover image for How AI Can Help You Recover Your Bitcoin
David Au Yeung
David Au Yeung

Posted on

How AI Can Help You Recover Your Bitcoin

Introduction

When people talk about Artificial Intelligence today, the conversation usually revolves around chatbots, image generators, coding assistants, or office productivity.

But a recent news shared by Yahoo!Tech caught my attention for a very different reason.

According to the report, an X user known as cprkrn claimed that after being locked out of his Bitcoin wallet for 11 years, he finally recovered access with the help of Claude AI.

The wallet reportedly contained 5 BTC. Based on the approximate market price mentioned in the report, that was worth more than HKD 3 million.

The interesting part was not that AI "hacked Bitcoin".

It did not.

Instead, the user reportedly had:

  • An old computer
  • Old wallet files
  • Some forgotten notes
  • A seed phrase
  • A long-forgotten password pattern
  • Many years of messy digital history

AI helped connect the dots.

This is not a story about breaking cryptography.

It is a story about AI-assisted memory reconstruction.

And that opens up a powerful idea:

AI may not break encryption, but it can help us rediscover the human context around things we forgot.

This article explores:

  • How AI can reduce password search space
  • Why this is different from brute force cracking
  • How old notes can become useful signals
  • How to build a safe educational C# demo
  • How to use Ollama and Kimi as the LLM engine
  • Why privacy and ethics matter

Important:

This project is for education and simulation only.

It does not recover real Bitcoin wallets.

It does not parse real wallet.dat files.

It does not crack encryption.

It must not be used against anyone else’s accounts, wallets, devices, or data.

What Actually Happened Conceptually

The reported Bitcoin recovery story can be understood like this:

Old computer files
    ↓
Old wallet file discovered
    ↓
Old notes and memory fragments analyzed
    ↓
Possible password patterns reconstructed
    ↓
Seed phrase / wallet artifacts matched
    ↓
Wallet access recovered
Enter fullscreen mode Exit fullscreen mode

The important distinction is this:

AI did not defeat Bitcoin cryptography.
AI helped organize messy human memory.
Enter fullscreen mode Exit fullscreen mode

Bitcoin itself relies on strong cryptographic systems.

But humans often create passwords based on:

  • Emotions
  • Old events
  • Favorite words
  • Personal habits
  • Dates
  • Naming formats
  • Repeated patterns

That is where AI becomes useful.

Brute Force vs AI-Assisted Reasoning

A brute force approach looks like this:

Try every possible combination.
Try millions, billions, or trillions of passwords.
Hope one works.
Enter fullscreen mode Exit fullscreen mode

This is expensive, slow, and usually unrealistic.

AI-assisted reasoning works differently.

Instead of attacking the encryption directly, it attacks the uncertainty around the human-created password.

It looks for clues such as:

  • Old notes
  • Diary fragments
  • File names
  • Repeated words
  • Emotional context
  • Important years
  • Formatting habits
  • Common personal patterns

So the workflow becomes:

Messy notes
    ↓
LLM analysis
    ↓
Ranked password candidates
    ↓
Local verification
Enter fullscreen mode Exit fullscreen mode

That last step is important.

The LLM should generate candidates.

The actual verification should happen locally.

The Sample Exercise

For this article, we will create a safe simulation.

We will pretend that we found two old text files from an old computer:

old_notes.txt
diary_fragment.txt
Enter fullscreen mode Exit fullscreen mode

These files contain clues.

The hidden mock password will be:

memory_police_2014
Enter fullscreen mode Exit fullscreen mode

But in a real recovery situation, we would not know that.

The goal of the demo is to see whether an LLM can infer likely candidates from the notes.

Sample File 1: old_notes.txt

2014 - bought BTC when it was around 230 USD
Used police story as password theme before
Memory + river + sunset were words I liked back then
Laptop password had underscore format
Sometimes I append the year to important accounts
Enter fullscreen mode Exit fullscreen mode

Sample File 2: diary_fragment.txt

Can't believe I finally bought Bitcoin.
Police documentary inspired me that week.
Maybe I should combine memory and police somehow.
Don't forget 2014 was important.
Enter fullscreen mode Exit fullscreen mode

These notes are simple, but they contain strong human signals:

Clue Possible Meaning
memory likely password word
police likely password word
2014 likely suffix
underscore format likely separator
"combine memory and police" likely word order
BTC price 230 possible alternative suffix

A human might miss the pattern.

An LLM can rank it immediately.

The Prompt We Give to the LLM

Here is the kind of prompt we will send to the model:

You are assisting in a password reconstruction exercise for a simulated wallet recovery.

This is an educational exercise using fake data.
The wallet is a local mock wallet owned by the user.

Your task:
1. Read the recovered historical notes.
2. Identify recurring words, themes, years, and formatting habits.
3. Generate 15 structured password candidates ranked by likelihood.
4. Prefer underscore separators if the notes suggest that style.
5. Consider important years or numbers as suffixes.
6. Do not brute force.
7. Do not generate random unrelated strings.
8. Return JSON only.

Recovered notes:

[old_notes.txt and diary_fragment.txt content here]
Enter fullscreen mode Exit fullscreen mode

The key idea is:

Do not ask the model to crack anything.
Ask the model to reason from context.
Enter fullscreen mode Exit fullscreen mode

Example LLM Result

In my test using Kimi through Ollama, the model generated a ranked candidate list similar to this:

Rank Password Candidate Rationale
1 memory_police_2014 Direct use of "combine memory and police" + underscore + year
2 police_memory_2014 Reverse order variation
3 memory_river_sunset Uses three liked words
4 police_story_2014 Police story theme + year
5 river_sunset_memory Alternative ordering of liked words
6 memory_documentary_2014 Memory + documentary clue
7 memory_river_2014 Liked word + year
8 sunset_memory_2014 Liked word + year
9 police_river_2014 Cross-combination
10 river_memory_2014 Alternative pair
11 police_sunset_2014 Cross-combination
12 memory_2014 Minimal pattern
13 police_memory_230 Uses BTC price clue
14 memory_police_230 Price-based variation
15 sunset_river_2014 Nature-themed pair + year

The important thing is not the exact output.

The important thing is that the model did not generate random strings like:

xJ9#qPz882!
Enter fullscreen mode Exit fullscreen mode

Instead, it generated human-plausible candidates from the notes.

That is the value of AI here.

Demo Architecture

Our safe simulation looks like this:

old_notes.txt
diary_fragment.txt
        ↓
Ollama + Kimi model
        ↓
JSON password candidates
        ↓
Local mock wallet verifier
        ↓
Success / failure result
Enter fullscreen mode Exit fullscreen mode

The LLM only sees the notes.

It does not receive:

  • A real wallet file
  • A private key
  • A seed phrase
  • A real password hash
  • A real Bitcoin address

The verification happens locally inside our C# program.

This is safer and cleaner

Technical Setup

This demo uses OllamaApiClient from OllamaSharp. OllamaSharp documents GenerateAsync for single-turn completions and the Chat class for conversational workflows; Ollama’s own API documentation also describes /api/generate and /api/chat streaming endpoints. (awaescher.github.io)

Create a new console app:

dotnet new console -n AiWalletRecoveryDemo
cd AiWalletRecoveryDemo
dotnet add package OllamaSharp
Enter fullscreen mode Exit fullscreen mode

Make sure your Ollama endpoint is running at:

http://localhost:11434
Enter fullscreen mode Exit fullscreen mode

The sample code defaults to:

string modelName = "kimi-k2.6:cloud";
Enter fullscreen mode Exit fullscreen mode

If you used another model, such as kimi-k2.5, pass it as an argument:

dotnet run -- kimi-k2.5
Enter fullscreen mode Exit fullscreen mode

Project Structure

AiWalletRecoveryDemo/
│
├── AiWalletRecoveryDemo.csproj
├── Program.cs
│
└── sample-data/
    ├── old_notes.txt
    ├── diary_fragment.txt
    └── mock_wallet.json
Enter fullscreen mode Exit fullscreen mode

The program will create the sample files automatically if they do not exist.

Full Educational C# Example

Program.cs

using OllamaSharp;
using System.Security.Cryptography;
using System.Text;
using System.Text.Json;
using System.Text.Json.Serialization;
using System.Text.RegularExpressions;

internal static class Program
{
    // Educational only:
    // In a real recovery situation, you would NOT know this value.
    // We use it only to create a local mock wallet verifier.
    private const string DemoPassword = "memory_police_2014";

    public static async Task Main(string[] args)
    {
        Console.OutputEncoding = Encoding.UTF8;

        string modelName = args.Length > 0 ? args[0] : "kimi-k2.6:cloud";
        string ollamaApiUrl = args.Length > 1 ? args[1] : "http://localhost:11434";

        string dataDirectory = Path.Combine(Directory.GetCurrentDirectory(), "sample-data");
        string mockWalletPath = Path.Combine(dataDirectory, "mock_wallet.json");

        Console.WriteLine("AI-Assisted Wallet Recovery Simulation");
        Console.WriteLine("---------------------------------------");
        Console.WriteLine($"Ollama URL : {ollamaApiUrl}");
        Console.WriteLine($"Model      : {modelName}");
        Console.WriteLine();

        DemoData.EnsureCreated(dataDirectory, DemoPassword);

        string recoveredNotes = DemoData.ReadAllNotes(dataDirectory);
        var mockWallet = MockWalletVault.Load(mockWalletPath);

        var generator = new OllamaCandidateGenerator(
            ollamaApiUrl: ollamaApiUrl,
            modelName: modelName,
            wikiRootDirectory: dataDirectory);

        IReadOnlyList<PasswordCandidate> candidates;

        try
        {
            candidates = await generator.GenerateCandidatesAsync(recoveredNotes);
        }
        catch (Exception ex)
        {
            Console.WriteLine("LLM generation failed.");
            Console.WriteLine($"Reason: {ex.Message}");
            Console.WriteLine();
            Console.WriteLine("Using deterministic fallback candidates for demo continuity.");
            Console.WriteLine();

            candidates = FallbackCandidateGenerator.Generate();
        }

        var uniqueCandidates = candidates
            .Where(c => !string.IsNullOrWhiteSpace(c.Password))
            .Select(c => c with { Password = c.Password.Trim() })
            .GroupBy(c => c.Password, StringComparer.Ordinal)
            .Select((g, index) => g.First() with { Rank = index + 1 })
            .Take(25)
            .ToList();

        Console.WriteLine("Ranked Password Candidates");
        Console.WriteLine("--------------------------");

        foreach (var candidate in uniqueCandidates)
        {
            Console.WriteLine($"#{candidate.Rank}: {candidate.Password}");
            Console.WriteLine($"    Reason: {candidate.Rationale}");
        }

        Console.WriteLine();
        Console.WriteLine("Testing candidates against local mock wallet...");
        Console.WriteLine();

        PasswordCandidate? successfulCandidate = null;

        foreach (var candidate in uniqueCandidates)
        {
            bool isMatch = mockWallet.Verify(candidate.Password);

            if (isMatch)
            {
                successfulCandidate = candidate;
                break;
            }
        }

        if (successfulCandidate is not null)
        {
            Console.WriteLine($"✅ Mock wallet unlocked with candidate #{successfulCandidate.Rank}:");
            Console.WriteLine(successfulCandidate.Password);
        }
        else
        {
            Console.WriteLine("❌ No candidate unlocked the mock wallet.");
            Console.WriteLine("Try adding more historical notes or stronger clues.");
        }

        Console.WriteLine();
        Console.WriteLine("Simulation complete.");
    }
}

public sealed class OllamaCandidateGenerator
{
    private readonly OllamaApiClient _ollamaClient;
    private readonly string _wikiRootDirectory;

    public OllamaCandidateGenerator(
        string ollamaApiUrl = "http://localhost:11434",
        string modelName = "kimi-k2.6:cloud",
        string? wikiRootDirectory = null)
    {
        _ollamaClient = new OllamaApiClient(new Uri(ollamaApiUrl))
        {
            SelectedModel = modelName
        };

        _wikiRootDirectory = wikiRootDirectory ?? Directory.GetCurrentDirectory();
    }

    public async Task<IReadOnlyList<PasswordCandidate>> GenerateCandidatesAsync(
        string recoveredNotes,
        CancellationToken cancellationToken = default)
    {
        string prompt = BuildPrompt(recoveredNotes);

        var responseBuilder = new StringBuilder();

        await foreach (var stream in _ollamaClient.GenerateAsync(
            prompt,
            context: null,
            cancellationToken: cancellationToken))
        {
            if (!string.IsNullOrEmpty(stream?.Response))
            {
                responseBuilder.Append(stream.Response);
            }
        }

        string rawResponse = responseBuilder.ToString();

        var candidates = ParseCandidates(rawResponse);

        if (candidates.Count == 0)
        {
            throw new InvalidOperationException(
                "The model did not return valid password candidates.");
        }

        return candidates;
    }

    private string BuildPrompt(string recoveredNotes)
    {
        return $$"""
            You are assisting in a password reconstruction exercise for a simulated wallet recovery.

            This is an educational exercise using fake data.
            The mock wallet belongs to the user.
            Do not provide hacking instructions.
            Do not suggest brute force tools.
            Do not suggest unauthorized access.
            Do not generate random unrelated strings.

            Your task:
            1. Read the recovered historical notes.
            2. Identify recurring words, themes, dates, numbers, and formatting habits.
            3. Generate exactly 15 structured password candidates ranked by likelihood.
            4. Prefer underscore separators if the notes suggest that style.
            5. Consider important years or numbers as suffixes.
            6. Prefer candidates that follow explicit diary wording.
            7. Return valid JSON only.
            8. Do not wrap the JSON in Markdown.

            Return this JSON shape:

            {
              "candidates": [
                {
                  "rank": 1,
                  "password": "example_candidate",
                  "rationale": "Short explanation"
                }
              ]
            }

            Recovered notes:

            {{recoveredNotes}}
        """;
    }

    private static IReadOnlyList<PasswordCandidate> ParseCandidates(string rawResponse)
    {
        string json = ExtractJsonObject(rawResponse);

        var options = new JsonSerializerOptions
        {
            PropertyNameCaseInsensitive = true
        };

        var parsed = JsonSerializer.Deserialize<CandidateResponse>(json, options);

        return parsed?.Candidates?
            .OrderBy(c => c.Rank)
            .ToList()
            ?? new List<PasswordCandidate>();
    }

    private static string ExtractJsonObject(string text)
    {
        string cleaned = text.Trim();

        cleaned = Regex.Replace(
            cleaned,
            "^```
{% endraw %}
(?:json)?\\s*",
            "",
            RegexOptions.IgnoreCase);

        cleaned = Regex.Replace(
            cleaned,
            "\\s*
{% raw %}
```$",
            "",
            RegexOptions.IgnoreCase);

        int start = cleaned.IndexOf('{');
        int end = cleaned.LastIndexOf('}');

        if (start < 0 || end <= start)
        {
            throw new FormatException("No JSON object found in model response.");
        }

        return cleaned.Substring(start, end - start + 1);
    }
}

public sealed record PasswordCandidate
{
    [JsonPropertyName("rank")]
    public int Rank { get; init; }

    [JsonPropertyName("password")]
    public string Password { get; init; } = "";

    [JsonPropertyName("rationale")]
    public string Rationale { get; init; } = "";
}

public sealed class CandidateResponse
{
    [JsonPropertyName("candidates")]
    public List<PasswordCandidate> Candidates { get; set; } = new();
}

public sealed class MockWalletVault
{
    private static readonly JsonSerializerOptions JsonOptions = new()
    {
        WriteIndented = true,
        PropertyNameCaseInsensitive = true
    };

    [JsonPropertyName("description")]
    public string Description { get; set; } = "Educational mock wallet. This is not a real Bitcoin wallet.";

    [JsonPropertyName("saltBase64")]
    public string SaltBase64 { get; set; } = "";

    [JsonPropertyName("passwordHashBase64")]
    public string PasswordHashBase64 { get; set; } = "";

    public static MockWalletVault CreateFromPassword(string password)
    {
        byte[] salt = RandomNumberGenerator.GetBytes(16);
        byte[] hash = HashPassword(password, salt);

        return new MockWalletVault
        {
            SaltBase64 = Convert.ToBase64String(salt),
            PasswordHashBase64 = Convert.ToBase64String(hash)
        };
    }

    public static MockWalletVault Load(string path)
    {
        string json = File.ReadAllText(path);

        return JsonSerializer.Deserialize<MockWalletVault>(json, JsonOptions)
            ?? throw new InvalidOperationException("Unable to load mock wallet.");
    }

    public void Save(string path)
    {
        string json = JsonSerializer.Serialize(this, JsonOptions);
        File.WriteAllText(path, json);
    }

    public bool Verify(string candidatePassword)
    {
        byte[] salt = Convert.FromBase64String(SaltBase64);
        byte[] expectedHash = Convert.FromBase64String(PasswordHashBase64);
        byte[] actualHash = HashPassword(candidatePassword, salt);

        return CryptographicOperations.FixedTimeEquals(actualHash, expectedHash);
    }

    private static byte[] HashPassword(string password, byte[] salt)
    {
        // Educational local verifier.
        // This is not Bitcoin Core wallet encryption.
        using var pbkdf2 = new Rfc2898DeriveBytes(
            password,
            salt,
            iterations: 100_000,
            hashAlgorithm: HashAlgorithmName.SHA256);

        return pbkdf2.GetBytes(32);
    }
}

public static class DemoData
{
    private const string OldNotesFileName = "old_notes.txt";
    private const string DiaryFileName = "diary_fragment.txt";
    private const string MockWalletFileName = "mock_wallet.json";

    private const string OldNotesText = """
    2014 - bought BTC when it was around 230 USD
    Used police story as password theme before
    Memory + river + sunset were words I liked back then
    Laptop password had underscore format
    Sometimes I append the year to important accounts
    """;

    private const string DiaryFragmentText = """
    Can't believe I finally bought Bitcoin.
    Police documentary inspired me that week.
    Maybe I should combine memory and police somehow.
    Don't forget 2014 was important.
    """;

    public static void EnsureCreated(string dataDirectory, string demoPassword)
    {
        Directory.CreateDirectory(dataDirectory);

        string oldNotesPath = Path.Combine(dataDirectory, OldNotesFileName);
        string diaryPath = Path.Combine(dataDirectory, DiaryFileName);
        string mockWalletPath = Path.Combine(dataDirectory, MockWalletFileName);

        if (!File.Exists(oldNotesPath))
        {
            File.WriteAllText(oldNotesPath, OldNotesText);
        }

        if (!File.Exists(diaryPath))
        {
            File.WriteAllText(diaryPath, DiaryFragmentText);
        }

        if (!File.Exists(mockWalletPath))
        {
            var wallet = MockWalletVault.CreateFromPassword(demoPassword);
            wallet.Save(mockWalletPath);
        }
    }

    public static string ReadAllNotes(string dataDirectory)
    {
        var builder = new StringBuilder();

        foreach (string file in Directory
            .EnumerateFiles(dataDirectory, "*.txt", SearchOption.AllDirectories)
            .OrderBy(f => f))
        {
            builder.AppendLine($"--- {Path.GetFileName(file)} ---");
            builder.AppendLine(File.ReadAllText(file));
            builder.AppendLine();
        }

        return builder.ToString();
    }
}

public static class FallbackCandidateGenerator
{
    public static IReadOnlyList<PasswordCandidate> Generate()
    {
        return new List<PasswordCandidate>
        {
            new()
            {
                Rank = 1,
                Password = "memory_police_2014",
                Rationale = "Direct implementation of diary note: combine memory and police, underscore format, year suffix."
            },
            new()
            {
                Rank = 2,
                Password = "police_memory_2014",
                Rationale = "Reverse order variation using the same strong clues."
            },
            new()
            {
                Rank = 3,
                Password = "memory_river_sunset",
                Rationale = "Uses three liked words with underscore formatting."
            },
            new()
            {
                Rank = 4,
                Password = "police_story_2014",
                Rationale = "References previous police story theme and important year."
            },
            new()
            {
                Rank = 5,
                Password = "river_sunset_memory",
                Rationale = "Alternative ordering of liked words."
            },
            new()
            {
                Rank = 6,
                Password = "memory_documentary_2014",
                Rationale = "Combines memory with police documentary clue and year."
            },
            new()
            {
                Rank = 7,
                Password = "memory_river_2014",
                Rationale = "Liked word pair plus year suffix."
            },
            new()
            {
                Rank = 8,
                Password = "sunset_memory_2014",
                Rationale = "Liked word combination plus year."
            },
            new()
            {
                Rank = 9,
                Password = "police_river_2014",
                Rationale = "Cross-combination of police theme, liked word, and year."
            },
            new()
            {
                Rank = 10,
                Password = "river_memory_2014",
                Rationale = "Alternative liked word pair plus year."
            },
            new()
            {
                Rank = 11,
                Password = "police_sunset_2014",
                Rationale = "Cross-combination of police theme, liked word, and year."
            },
            new()
            {
                Rank = 12,
                Password = "memory_2014",
                Rationale = "Minimal pattern using important word and year."
            },
            new()
            {
                Rank = 13,
                Password = "police_memory_230",
                Rationale = "Uses BTC price clue instead of year."
            },
            new()
            {
                Rank = 14,
                Password = "memory_police_230",
                Rationale = "Price-based variation of the strongest phrase."
            },
            new()
            {
                Rank = 15,
                Password = "sunset_river_2014",
                Rationale = "Nature-themed pair plus year suffix."
            }
        };
    }
}
Enter fullscreen mode Exit fullscreen mode

Example Output

Your result may vary depending on the model, but a successful run may look like this:

This is exactly the concept we want to demonstrate.

The model does not break encryption.

It simply turns messy personal history into a ranked list of likely hypotheses.

What AI Actually Contributes

The difference between brute force and AI reasoning is not magic.

It is context.

Brute force says:

Try everything.
Enter fullscreen mode Exit fullscreen mode

AI-assisted reasoning says:

Try what the human was most likely to create.
Enter fullscreen mode Exit fullscreen mode

In this exercise, the LLM extracted:

Signal Extracted Insight
memory important word
police important theme
combine memory and police likely word pairing
underscore format separator style
2014 likely suffix
BTC price 230 alternative numeric suffix
diary wording word order clue

This changes the search problem from:

Trillions of random guesses
Enter fullscreen mode Exit fullscreen mode

to:

15 structured candidates
Enter fullscreen mode Exit fullscreen mode

That is the power.

AI reduces chaos.

Why This Is Not "AI Cracking Bitcoin"

This point is very important.

Bitcoin was not broken.

Cryptography was not defeated.

The AI did not discover a private key from the blockchain.

The AI did not reverse SHA-256.

The AI did not bypass wallet encryption.

Instead, the AI helped with:

  • Pattern recognition
  • File interpretation
  • Note summarization
  • Candidate ranking
  • Human memory reconstruction

That is a completely different category.

A good analogy is this:

Encryption is the locked safe.
AI helps you search your old notebooks for the combination.
Enter fullscreen mode Exit fullscreen mode

The safe is still strong.

The weakness is human memory.

Privacy Warning

This is where we need to be careful.

If you use a cloud model, do not upload:

  • Real seed phrases
  • Private keys
  • Real wallet files
  • Password databases
  • Full disk images
  • Sensitive personal documents

Even if your intention is legitimate, sending secrets to a cloud model can create serious privacy risk.

A safer workflow is:

Sensitive file stays local
    ↓
You extract non-secret clues
    ↓
LLM generates candidate ideas
    ↓
Verification happens locally
Enter fullscreen mode Exit fullscreen mode

For example, instead of sending this:

seed phrase: apple apple apple ...
wallet.dat file attached
Enter fullscreen mode Exit fullscreen mode

Send only sanitized hints like:

I often used words related to memory, police, river, and 2014.
I used underscores in passwords at that time.
Enter fullscreen mode Exit fullscreen mode

The LLM should help with reasoning.

It should not become a place where secrets are stored.

How This Pattern Applies Beyond Bitcoin

This same AI-assisted recovery pattern can apply to many areas:

  • Old encrypted ZIP archives
  • Forgotten developer keystores
  • Legacy configuration files
  • Personal knowledge archives
  • Digital estate planning
  • Old project recovery
  • Family photo backup restoration
  • Enterprise documentation reconstruction

The common pattern is:

Messy historical data
    ↓
AI-assisted organization
    ↓
Ranked hypotheses
    ↓
Local verification
Enter fullscreen mode Exit fullscreen mode

This is why I find the story so interesting.

It shows AI being used not as a chatbot, but as a digital archaeologist.

Security Lessons

There is also a defensive lesson here.

If AI can infer human password patterns from old notes, then we should avoid creating passwords from personal context.

Better practices:

  • Use a password manager
  • Use long random passwords
  • Avoid emotional or memorable phrases
  • Avoid years, birthdays, and repeated themes
  • Do not store seed phrases digitally
  • Use hardware wallets for serious crypto storage
  • Keep offline backups in physically secure locations
  • Separate password hints from actual recovery material

Human-style passwords are easy to remember.

That is exactly why they can be guessed.

Conclusion

The reported Bitcoin recovery story is not about AI defeating cryptography.

It is about AI helping a person reconstruct forgotten context.

That may become one of AI's most underrated uses.

Not replacing humans.

Not magically solving everything.

But helping us search, organize, and reason through the complexity we created over years of digital life.

In this demo, we used:

  • Old notes
  • A diary fragment
  • Ollama
  • Kimi
  • C#
  • A local mock wallet verifier

And we simulated the same core idea safely:

Forgotten memory → AI reasoning → candidate ranking → local verification
Enter fullscreen mode Exit fullscreen mode

The future of AI may not only be automation.

It may also be recovery.

Recovering old knowledge.

Recovering lost context.

Recovering forgotten work.

Recovering what we once knew but could no longer find.

AI did not break the lock.

It helped us remember where we left the key.

References

  • OllamaSharp documentation for GenerateAsync, Chat, and OllamaApiClient. (awaescher.github.io)
  • Ollama API documentation for /api/generate and /api/chat. (github.com)

Love C# & AI!

Top comments (0)