Connect with us

Künstliche Intelligenz

Start-up S.A.M: Innovative 3D-Druck-Lösungen für mehr Datensicherheit


Samuel Kenzari (CNRS) und Sylvain Lefebvre (INRIA) gründeten Ende 2022 das Unternehmen S.A.M. Basis waren die Ergebnisse der gemeinsamen Forschung im Bereich Authentifizierung. Das Start-up S.A.M (Signature & Authentification des Matériaux) soll neue Ansätze für den Datenschutz bieten, indem es die Möglichkeiten der 3D-Druck-Technologie nutzt. Das Kernstück der neuen Lösungen sind 3D-gedruckte physische Token, die als Schlüssel sensible Daten wie Eigentumsnachweise, Seriennummern oder sichere Zugangscodes speichern. Mit diesem Ansatz soll es möglich sein, individuellen Schutz einfach, unabhängig und offline anzubieten.

Die Forscher bezeichnen das, was S.A.M. bietet, als „phygitale“ Lösung, die physische und digitale Elemente vereint, um einzigartige 3D-gedruckte Token zu schaffen. Diese Token fungieren als physische Schlüssel, mit denen Nutzer vertrauliche Echtheitszertifikate, Eigentumsnachweise oder sichere Zugangsberechtigungen erstellen. Die Technologie arbeitet offline ohne Datenbank, wodurch sie höchste Sicherheit für sensible Informationen wie Seriennummern, URL-Links oder Eigentumsbestätigungen bieten soll. So verifizieren die Token den Besitz eines Originalprodukts oder gewähren Zugang zu geschützten Bereichen und Funktionen.

Dabei kodieren Nutzer Daten, Befehle oder Funktionen zunächst und wandeln sie in G-Code um, der den 3D-Druck eines Tokens steuert. Dieser G-Code enthält die Anweisungen, um einen 3D-gedruckten Token zu erzeugen, der die vertraulichen Informationen direkt über sein Volumen und die Oberfläche speichert. Der fertige Token enthält dann die vertraulichen Informationen in der individuellen Struktur. Diese zweigeteilte Speicherform über Volumen und Oberfläche ermöglicht die sichere Authentifizierung und Datenverwaltung. Mit der mobilen App von S.A.M entschlüsseln Nutzer den Oberflächencode flexibel mit einem privaten oder öffentlichen Schlüssel, vergleichbar mit anderen asymmetrischen Kryptografieverfahren.

Sylvain Lefebvre als Leiter des Projektteams ist von der neuen Technologie überzeugt. „Dieser Token, der als Fälschungsschutz, Sicherheitsschlüssel oder Echtheitszertifikat verwendet werden kann, sieht aus wie ein Plastikquadrat mit einem geprägten Labyrinth auf einer Seite. Alles, was Sie tun müssen, ist, es auf das von uns entworfene Lesegerät zu legen, um an die enthaltenen Informationen beziehungsweise die Signatur zu kommen. Da der Entschlüsselungskey vollständig passiv im Token gespeichert wird, sendet er kein Signal aus, was bedeutet, dass er resistent gegen Cyberangriffe ist. Darüber hinaus verfügt die Lösung, die wir auf dieser Grundlage entwickelt haben, über eine astronomische Anzahl möglicher Labyrinthe, bei denen das Risiko einer Entschlüsselung praktisch gleich Null ist“, so Lefebvre.

„Einer der Vorteile dieser Technologie ist die einfache Handhabung. Alles, was du brauchst, ist ein 3D-Drucker, eine S.A.M.-Kodierspule, eine spezielle Anwendung zur Generierung der G-Codes und ein physischer Decoder für 3D-Token. Das Verfahren lässt sich einfach für unterschiedliche Kundenbedürfnisse anpassen und individuell in Herstellungs- und Serviceprozesse integrieren. Dies gilt auch für die Kunden, die bei der Produktion von Token völlig autonom sein möchten“, meinen die Forscher. Dabei lassen sich derartige Token auch in Alltagsgegenstände wie Armbänder integrieren. Weiterführende Infos bietet die Webseite von S.A.M.


(usz)



Source link

Weiterlesen
Kommentar schreiben

Leave a Reply

Deine E-Mail-Adresse wird nicht veröffentlicht. Erforderliche Felder sind mit * markiert

Künstliche Intelligenz

Core Java: Parallel, aber richtig – Wie Java-Collectors unter Last bestehen


Manchmal reicht es nicht aus, dass Code funktioniert – er muss auch unter Last funktionieren. In modernen Anwendungen, die große Datenmengen verarbeiten, steht Entwicklerinnen und Entwicklern mit der Streams-API in Java ein elegantes, deklaratives Werkzeug zur Verfügung, um Daten in Pipelines zu transformieren, zu filtern und schließlich zu aggregieren. Die Vorstellung, mit wenigen Zeilen komplexe Datenoperationen zu beschreiben, ist nicht nur verführerisch, sondern tatsächlich realistisch. Doch was passiert, wenn diese Operationen auf Millionen von Einträgen treffen? Wenn die Ausführung in mehreren Threads parallel erfolgen soll, um Zeit zu sparen und Mehrkernsysteme effektiv zu nutzen?


Sven Ruppert

Sven Ruppert

Seit 1996 programmiert Sven Java in Industrieprojekten und seit über 15 Jahren weltweit in Branchen wie Automobil, Raumfahrt, Versicherungen, Banken, UN und Weltbank. Seit über 10 Jahren ist er von Amerika bis nach Neuseeland als Speaker auf Konferenzen und Community Events, arbeitete als Developer Advocate für JFrog und Vaadin und schreibt regelmäßig Beiträge für IT-Zeitschriften und Technologieportale.
Neben seinem Hauptthema Core Java beschäftigt er sich mit TDD und Secure Coding Practices.

Genau an dieser Stelle rückt ein Konzept in den Vordergrund, das oft zu wenig Beachtung findet: der Collector. Er ist das Element am Ende einer Stream-Pipeline, das bestimmt, was mit den verarbeiteten Daten geschehen soll. Und obwohl die API einfach erscheint – collect(Collectors.toList()) – verbirgt sich dahinter eine Architektur, die in paralleler Ausführung ganz eigene Herausforderungen mit sich bringt.

Im Folgenden geht es daher nicht nur um die Syntax oder die Mechanik von Collectoren, sondern um ein tiefes Verständnis für die Bedingungen, unter denen sie korrekt und effizient zum Einsatz kommen. Wir schauen auf Standardlösungen des JDK (Java Development Kit), diskutieren individuelle Implementierungen, zeigen typische Fehler – und kommen letztlich zu der Frage: Wie viel Parallelisierung verträgt ein Collector, ohne dass es gefährlich wird?

Die Streams-API von Java vermittelt auf den ersten Blick den Eindruck, dass sich das Sammeln von Ergebnissen – das sogenannte terminale Aggregieren – problemlos parallelisieren lässt. Doch hinter der Methode collect(...) verbirgt sich mehr als nur syntaktische Bequemlichkeit. Sie ist eine koordinierte Zusammenarbeit zwischen einem Datenstrom und einem Collector – einem Objekt, das aus Einzelteilen ein Ganzes formt.

Ein Collector besteht im Kern aus vier funktionalen Komponenten: dem supplier, der für jeden Teilprozess einen neuen Zwischenspeicher bereitstellt; dem accumulator, der Elemente in diesen Zwischenspeicher einspeist; dem combiner, der mehrere Zwischenspeicher zu einem zusammenführt; und schließlich dem finisher, der das Endergebnis produziert. Während supplier und accumulator auch in sequenziellen Streams essenziell sind, tritt der combiner erst dann in Aktion, wenn mehrere Threads unabhängig voneinander gesammelt haben – also bei einem parallelStream().

Hier liegt der erste fundamentale Unterschied zwischen sequenzieller und paralleler Verarbeitung: In einem sequenziellen Stream genügt es, schrittweise in einen einzigen Speicher zu akkumulieren. In der parallelen Variante hingegen entstehen mehrere voneinander isolierte Zwischenspeicher, deren Inhalte später konfliktfrei zu einem Endergebnis verschmolzen werden müssen. Dieses Verschmelzen geschieht durch den combiner – und genau an dieser Stelle entscheidet sich, ob ein Collector für parallele Verarbeitung tauglich ist oder nicht.

Die Tauglichkeit hängt von mehreren Eigenschaften ab: Die Operationen müssen assoziativ sein, also unabhängig von der Kombination der Zwischenergebnisse dasselbe Resultat liefern. Zudem darf kein geteilter Zustand ohne Synchronisierung vorliegen. Und nicht zuletzt müssen die einzelnen Schritte deterministisch und frei von Seiteneffekten bleiben – andernfalls wird aus einer Parallelisierung schnell eine Quelle subtiler Fehler.

Das Wissen um diese strukturellen Anforderungen ist der erste Schritt zu einem bewussten Einsatz paralleler Verarbeitung. Denn nur wer verstanden hat, wie Collector und Stream im Zusammenspiel funktionieren, kann abschätzen, wann ein Performancegewinn möglich ist – und wann man sich stattdessen instabile oder schlicht falsche Ergebnisse einhandelt.

Stellen wir uns vor, ein Stream wird parallel ausgeführt – etwa über ein großes Dataset, das in mehrere Segmente aufgeteilt ist. Jedes dieser Segmente wird nun unabhängig verarbeitet. Was trivial klingt, hat tiefgreifende Implikationen: Sobald mehrere Threads gleichzeitig sammeln, dürfen sich deren Zwischenergebnisse nicht in die Quere kommen. Die Verantwortung für die Korrektheit liegt beim Collector – genauer: bei seiner strukturellen und funktionalen Ausgestaltung.

Die erste grundlegende Eigenschaft ist Assoziativität. Ein combiner-Aufruf muss unabhängig von der Reihenfolge konsistente Ergebnisse liefern. combine(a, b) und combine(b, a) müssen äquivalente Resultate erzeugen. Das ist notwendig, weil die Reihenfolge der Kombination in einem parallelen Kontext vom Scheduler abhängt – und somit unvorhersagbar ist.

Der zweite Punkt betrifft den Zugriff auf Speicherstrukturen. Sobald ein Collector während der Akkumulation einen gemeinsamen, veränderbaren Zustand nutzt – etwa eine nicht synchronisierte Liste oder Map – entsteht ein potenzieller Hotspot für Race Conditions. Der Collector muss entweder ausschließlich mit lokalen, thread-isolierten Zwischenspeichern arbeiten oder sich auf nebenläufige Datenstrukturen stützen, wie etwa ConcurrentHashMap, LongAdder oder explizit synchronisierte Wrapper.

Darüber hinaus ist auch Determinismus ein wesentliches Kriterium: Eine parallele Ausführung darf nicht zu unterschiedlichen Ergebnissen führen – weder inhaltlich noch strukturell. Insbesondere bei ungeordneten Strukturen wie HashSet oder HashMap ist Vorsicht geboten, da die Iterationsreihenfolge variieren kann – was bei Collectors.joining() oder Collectors.toMap() problematisch wird, wenn die Anwendung auf Ordnung angewiesen ist.

Die drei Anforderungen Assoziativität, isolierter Zustand und Determinismus bilden den technischen Prüfstein für parallele Collectoren. Sie sind nicht optional, sondern grundlegend. Wer sie ignoriert, riskiert schwer zu reproduzierende Fehler, unvollständige Ergebnisse oder performante, aber semantisch falsche Ausgaben.

Beispiele aus der Java-Standardbibliothek: Ein naheliegender Weg, um das abstrakte Konzept paralleler Collectoren greifbar zu machen, führt über die bereits in der Java-Standardbibliothek enthaltenen Collectors. Viele Entwickler nutzen Collectors.toList(), toSet() oder joining() nahezu täglich – selten jedoch im Wissen darum, ob und wie sich diese Collectoren in einem parallelen Kontext verhalten.

Ein einfaches Beispiel: Der Collector Collectors.toList() nutzt intern eine ArrayList. Diese ist nicht thread-sicher. Folglich ist das Ergebnis bei paralleler Verwendung potenziell inkonsistent, sofern nicht intern für Isolation der Zwischenspeicher gesorgt ist.


public static 
Collector> toList() {
   return new CollectorImpl<>(ArrayList::new, List::add,
                              (left, right) -> { left.addAll(right); return left; },
                              CH_ID);
}


Tatsächlich funktioniert dieser Collector in parallelen Streams dennoch korrekt, weil die Streams-API jedem Thread seinen eigenen Akkumulationsbereich zuteilt und erst am Ende über einen kombinierten Merge-Prozess zusammenführt. Der entscheidende Punkt liegt also nicht in der Datenstruktur selbst, sondern in ihrer kontrollierten Isolierung.

Weniger robust zeigt sich Collectors.groupingBy(...). Diese Variante basiert auf einer HashMap, die nicht für gleichzeitigen Zugriff ausgelegt ist. Wird dieser Collector ohne Schutzmaßnahmen in einem parallelStream() eingesetzt, drohen Race Conditions. Die Standardlösung dafür lautet Collectors.groupingByConcurrent(...), die intern auf ConcurrentHashMap setzt und somit für gleichzeitigen Zugriff konzipiert ist.


public static 
Collector>>
groupingByConcurrent(Function super T, ? extends K> classifier) {
   return groupingByConcurrent(classifier, ConcurrentHashMap::new, toList());
}


Ein Blick auf die Signatur dieser Methode zeigt bereits die Intention:


Map> result = namen.parallelStream()
    .collect(Collectors.groupingByConcurrent(String::length));


In diesem Beispiel werden Strings nach ihrer Länge gruppiert – in einer parallel verarbeitbaren Weise. Entscheidend ist, dass sowohl die Map-Implementierung als auch der Akkumulationsprozess thread-safe sind.

Ebenso interessant ist Collectors.toConcurrentMap(...), der explizit dafür vorgesehen ist, große Mengen von Key-Value-Paaren parallel zu aggregieren. Hier ist die Kombination von Schlüsselkonflikten und der richtige Umgang mit Merge-Funktionen von besonderem Interesse.

Die Erkenntnis aus diesen Beispielen lautet: Nicht jeder Standard-Collector ist per se für Parallelität geeignet. Nur weil eine Methode aus dem Collectors-Baukasten stammt, bedeutet das nicht, dass sie in jeder Ausführungskonfiguration korrekt funktioniert. Der Kontext entscheidet – und mit ihm die verwendete Datenstruktur, das Verhalten des combiner und die Art der Akkumulation.

Wer also aus einem Stream nicht nur ein beliebiges Ergebnis, sondern ein korrektes und performantes Ergebnis ziehen will, sollte die Wahl seines Collectors ebenso sorgfältig treffen wie das Filterkriterium am Anfang der Pipeline.

So mächtig die vorgefertigten Collectors der Java-Standardbibliothek auch sein mögen, manchmal reichen sie für spezifische Anforderungen nicht aus. Besonders wenn domänenspezifische Aggregationen, spezialisierte Datenstrukturen oder nicht-triviale Reduktionslogik benötigt werden, lohnt sich ein Blick auf die Möglichkeit, eigene Collector-Implementierungen zu erstellen.

In der Regel lässt sich ein eigener Collector mit der statischen Methode Collector.of(...) erstellen. Diese Methode erwartet fünf Parameter: einen Supplier, der einen neuen Akkumulator erzeugt; einen BiConsumer, der ein Element in den Akkumulator einfügt; einen BinaryOperator zum Kombinieren zweier Akkumulatoren; optional eine Function zur Konvertierung des Ergebnisses; und schließlich ein Array Collector.Characteristics..., das Metainformationen wie CONCURRENT oder UNORDERED bereitstellt.

Ein einfacher, aber aussagekräftiger Collector könnte etwa Zeichenketten parallel zu einer ConcurrentLinkedQueue sammeln:


Collector> toConcurrentQueue() {
    return Collector.of(
        ConcurrentLinkedQueue::new,
        Queue::add,
        (left, right) -> { left.addAll(right); return left; },
        Collector.Characteristics.CONCURRENT, Collector.Characteristics.UNORDERED
    );
}


Dieser Collector ist sowohl CONCURRENT als auch UNORDERED, das bedeutet: Er kann von mehreren Threads gleichzeitig beschrieben werden, ohne dass die Einfügereihenfolge garantiert werden muss. Wichtig ist dabei, dass ConcurrentLinkedQueue als thread-sichere Datenstruktur fungiert und die Operation addAll ebenfalls nebenläufig unkritisch ist.

Doch auch komplexere Szenarien sind denkbar, etwa das parallele Ermitteln von statistischen Kennzahlen (Minimum, Maximum, Durchschnitt) über eine Datenmenge. In solchen Fällen kann ein record als Akkumulatorstruktur dienen, der in sich bereits alle benötigten Teilzustände kapselt. Der combiner muss dann lediglich diese Strukturen feldweise konsolidieren.

Eigene Collector-Implementierungen zwingen dazu, sich mit der Parallelisierbarkeit der genutzten Datenstrukturen und der Kombinierbarkeit der Aggregationslogik intensiv auseinanderzusetzen. Das ist kein Nachteil, sondern ein wertvoller Lerneffekt. Denn nur wer versteht, was ein Collector im Inneren macht, kann ihn bewusst und sicher einsetzen.

Wer Collectoren im Parallelisierungskontext produktiv einsetzen möchte, sollte einige bewährte Strategien berücksichtigen – nicht als starre Regeln, sondern als Orientierungsrahmen für robuste und effiziente Implementierungen.

Ein erster Grundsatz lautet: Nur parallelisieren, wenn ein echter Nutzen zu erwarten ist. Kleine Datenmengen, triviale Transformationen oder IO-gebundene Prozesse profitieren in der Regel nicht von parallelStream(). Im Gegenteil: Der Overhead des Thread-Managements kann den potenziellen Performancegewinn sogar übersteigen. Eine Parallelisierung lohnt sich erst dann, wenn die zu verarbeitenden Datenmengen hinreichend groß und die Operationen CPU-intensiv sind.

Zweitens: Nur thread-sichere oder isolierte Datenstrukturen verwenden. Das bedeutet entweder, dass jeder Thread seinen eigenen Akkumulator nutzt – was die Streams-API intern unterstützt – oder dass explizit nebenläufige Datenstrukturen wie ConcurrentHashMap, ConcurrentLinkedQueue oder atomare Wrapper eingesetzt werden.

Drittens: Collectors gezielt auswählen. Die Standardbibliothek bietet mit groupingByConcurrent, toConcurrentMap oder mapping leistungsfähige Werkzeuge, die speziell für den parallelen Einsatz konzipiert wurden. Wer darüber hinaus eigene Lösungen entwickelt, sollte besonderes Augenmerk auf den combiner und die Assoziativität der Logik legen.

Viertens: Ergebnisse validieren – insbesondere bei neuen oder komplexen Pipelines. Parallele Streams verhalten sich nicht deterministisch in der Ausführung, deshalb sind Tests in unterschiedlichen Auslastungsszenarien und unter variierender Last notwendig. Das gilt vor allem dann, wenn Entwicklerinnen oder Entwickler Collectoren selbst entwickeln oder anpassen.

Und nicht zuletzt: Messen statt vermuten. Tools wie JMH (Java Microbenchmark Harness), Flight Recorder oder async-profiler helfen dabei, realistische Aussagen über die Performancevorteile zu treffen. Parallelisierung ohne Metriken ist wie Blindflug mit Rückenwind – vielleicht schneller, aber womöglich in die falsche Richtung.



Source link

Weiterlesen

Künstliche Intelligenz

KI-Analyse für Aktien-Diskussionen auf Reddit: Anleitung zum Nachbauen


Das Subreddit r/wallstreetbets ist ein riesiges Forum, auf dem die Mitglieder täglich interessante Aktien und die Entwicklungen am Markt diskutieren. Dabei entsteht kontinuierlich eine enorme Informationsmenge, die sich kaum überblicken lässt. Wertvolle Unterstützung kann eine Text-KI liefern, die ein Python-Skript mit Anweisungen und Informationen füttert.

In diesem Projekt erklären wir Schritt für Schritt, wie Sie eine KI zur Analyse der Gespräche über die Aktien erstellen, die im Forum gerade populär sind. Als Ergebnis liefert das Projekt ein Word-Dokument mit kurzen Diskussionsanalysen. Zu den jeweils relevanten Posts gibt die KI eine Einschätzung, ob die Diskussion auf eine positive oder negative Kursentwicklung hindeutet, begründet die Einschätzung mit den Inhalten aus den Gesprächen und hebt wichtige inhaltliche Punkte hervor.

  • Erweiterungsprojekt des Aktien-Crawlers für Reddit: Das Projekt bindet eine KI ein, die die Diskussionen im Kontext der gecrawlten Aktiensymbole analysiert.
  • Um die KI effizient einzusetzen besteht das Projekt aus mehreren Skripten, die die relevanten Aktien für die KI-Analyse ermitteln und die zu untersuchenden Posts und Kommentare vorab filtern.
  • Das Ergebnis der Analyse erscheint als lesbarer Report in einem Word-Dokument.

Das Projekt eignet sich für Einsteiger in der Programmierung. Die Python-Skripte lassen wir auf Basis von Prompts von einer KI schreiben. Den Code können Sie herunterladen und für sich an wenigen Stellen anpassen. Das Projekt basiert auf unserem Artikel zum Reddit-Aktien-Crawler. Wir raten dazu, dass Sie zunächst das erste Projekt abschließen, bevor Sie die Erweiterung programmieren. Die Skripte haben wir in Windows 11 mit Python 3.13.5 erstellt.


Das war die Leseprobe unseres heise-Plus-Artikels „KI-Analyse für Aktien-Diskussionen auf Reddit: Anleitung zum Nachbauen“.
Mit einem heise-Plus-Abo können Sie den ganzen Artikel lesen.



Source link

Weiterlesen

Künstliche Intelligenz

Influencer sollen 300 Millionen Euro hinterzogen haben


Sogenannte Influencer sollen allein den Fiskus in Nordrhein-Westfalen um rund 300 Millionen Euro betrogen haben. Das bestätigte das Landesamt zur Bekämpfung der Finanzkriminalität (LBF NRW) auf Anfrage. Die Steuerfahnder analysieren nach eigenen Angaben aktuell ein Paket mehrerer Social-Media-Plattformen mit 6000 Datensätzen, aus denen sich der mutmaßliche Millionen-Schaden ergibt. Nach dpa-Informationen sind auch andere Bundesländer betroffen.

„Ziel der Ermittlungen sind professionelle Influencer, die ihre steuerlichen Pflichten mit hoher krimineller Energie umgehen“, hieß es von dem Landesamt, das seit Januar 2025 die gesamte nordrhein-westfälische Steuerfahndung mit rund 1200 Experten vereint. Es ist nach eigenen Angaben die erste Landesbehörde dieser Art in der Bundesrepublik. Innerhalb des LBF hatte man extra ein „Influencer-Team“ gebildet, um die Szene unter die Lupe zu nehmen.

„Im Fokus unseres Influencer-Teams stehen ausdrücklich nicht junge Menschen, die ein paar Follower gesammelt und ein paar Cremes oder Kleider beworben haben“, so Behördenleiterin Stephanie Thien: „Das LBF NRW hat auch auf den sozialen Netzwerken die großen Fische im Visier.“

Thien betonte: „Es gibt bei den großen Social-Media-Profilen Akteurinnen und Akteure, die mit hoher krimineller Energie jegliche Steuerverpflichtung zu umgehen versuchen. Es ist keine Seltenheit,dass eine Influencerin oder ein Influencer pro Monat mehrere zehntausend Euro verdient, aber nicht einmal eine Steuernummer hat. Da geht es nicht um Überforderung mit plötzlichem Ruhm, sondern umimmense Steuerhinterziehung mit Wissen und Willen.“

Die Ermittlungen seien aufwendig, so Thien: „Denn einen festen Arbeitsplatz gibt es nicht, oftmals melden sich die Content-Creators mit steigenden Umsätzen ins Ausland ab, um dem Finanzamt zuentgehen.“ So sei Dubai ein beliebtes Ziel.

Bei Werbung in sogenannten „Storys“, die nach 24 Stunden wieder verschwinden, sei die Beweisführung zudem schwierig. NRW habe aber „Ermittlungsmethoden initiiert, um Werbepartnerschaften und-einnahmen zurückverfolgen und beweissicher nachweisen zu können“, sagte Thien. Andere Länder hätten sich das zum Vorbild genommen.

Das LBF führt bereits rund 200 laufende Strafverfahren gegen in Nordrhein-Westfalen lebende Influencerinnen und Influencer – die Fälle aus dem aktuellen Datenpaket sind dabei noch nicht eingerechnet. Durchschnittlich geht es laut LBF um einen hohen fünfstelligen steuerlichen Fehlbetrag, in Einzelfällen auch um Fehlbeträge in Millionenhöhe.

NRW-Finanzminister Marcus Optendrenk (CDU) sagte der dpa: „Steuerhinterziehung im großen Stil tritt überall dort auf, wo Geld in großem Stil gemacht wird. Es ist ein Gebot der Gerechtigkeit, dass unsere Steuerfahndung ganz genau hinschaut.“


(dmk)



Source link

Weiterlesen

Beliebt