MoneyMoney Web Banking API

Einführung

Warum Web Scraping?

Viele Banken betreiben mittlerweile einen FinTS/HBCI-Server für Finanzsoftware. Einige Banken bieten jedoch leider überhaupt keine maschinenlesbare Schnittstelle an, über die eine Finanzsoftware (wie MoneyMoney) die Umsätze abrufen könnte. In so einem Fall können die Umsätze von einer Finanzsoftware nur mittels Web Scraping von der Website der Bank heruntergeladen werden.

Die Web Banking Engine

Die Web Banking Engine von MoneyMoney besteht aus einem recht umfangreichen Kern, der in C und Objective-C implementiert ist. Der Kern wird durch mehrere schlanke Extensions ergänzt. Diese Web Banking Extensions sind kurze Lua-Skripte, die einfach zu erstellen, zu modifizieren und auszuwechseln sind. Die Lua-Skripte werden von der Web Banking Engine in einer virtuellen Maschine ausgeführt und kommunizieren über eine dokumentierte API mit MoneyMoney. Das vorliegende Dokument spezifiziert diese API.

Die Wahl der Skriptsprache fiel auf Lua, da sie relativ leicht zu erlernen ist und sich gut mit C/C++/Objective-C kombinieren lässt. Für unsere Extensions reicht es vollkommen aus, die ersten fünf Kapitel von »Programming in Lua« gelesen zu haben. Die meisten innerhalb einer Extension aufgerufenen Funktionen sind nämlich gar nicht Bestandteil von Lua, sondern existieren ausschließlich in MoneyMoney.

Ein Praxisbeispiel

Das folgende Stück Lua-Code soll einen Eindruck davon vermitteln, wie eine Web Banking Extension in der Praxis vorgeht:

 connection = Connection()
  html = HTML(connection:get("/onlinebanking"))
 html:xpath("//input[@name='kontonummer']"):attr("value", username)
  html:xpath("//input[@name='pin']"):attr("value", password)
 connection:request(html:xpath("//input[@name='loginbutton']"):click())

Zuerst wird die Login-Seite vom Server geholt und aus ihrem HTML-Code eine Baumstruktur aufgebaut ➊. Mit Hilfe dieser Baumstruktur wird im HTML-Dokument mit XPath-Ausdrücken zu den Texteingabefeldern navigiert. Deren HTML-Attribute value werden dann mit den Anmeldedaten ausgefüllt ➋. Danach wird das Login-Formular abgeschickt ➌. Offensichtlich sind nur wenige Code-Zeilen notwendig, um den typischen Anmeldevorgang beim Online-Banking durchzuführen.

Das Skript erzeugt das gleiche Ergebnis, also die gleiche Serverkommunikation, wie sie ein Mensch mit einem Webbrowser beim Ausfüllen derselben Login-Seite erzeugen würde. Die Web Banking Engine kann man daher mit einem automatisch gesteuerten Webbrowser vergleichen.

Vom Skript zur Extension

Installation

Das Verzeichnis, in dem eigene Extensions abgelegt werden, kann über Menü Hilfe → Zeige Datenbank im Finder im Finder geöffnet werden:

~/Library/Containers/com.moneymoney-app.retail/Data/Library/Application Support/MoneyMoney/Extensions

Jede Änderung an Dateien in diesem Verzeichnis wirkt sich unmittelbar auf die Web Banking Engine aus, d.h. es ist nicht nötig, MoneyMoney neu zu starten.

Fehlermeldungen werden im Protokoll-Fenster von MoneyMoney angezeigt. Das Protokoll-Fenster lässt sich mit der Menüfunktion »Fenster« → »Protokollfenster« erreichen.

Hinweis: Für die Entwicklung eigener Extensions lässt sich die Überprüfung der digitalen Signatur in den Einstellungen von MoneyMoney ausschalten. Die Option lässt sich mit der Menüfunktion »MoneyMoney« → »Einstellungen« → »Erweiterungen« → »Digitale Signatur von Extensions überprüfen« erreichen.

Registrierung einer Extension

Ein Skript weist sich als Web Banking Extension aus, indem es am Beginn des Skripts einen Aufruf der Art

WebBanking{
  version = 1.00,
  url = "/onlinebanking",
  services = {"Premium Account"},
  description = "Demo"
}

enthält. Bei den benannten Parametern der Funktion WebBanking handelt es sich um:

ParameterTypOptionalBeschreibung
versionNumberneinVersionsnummer der Extension
urlStringjaURL der Einstiegsseite des Online-Bankings
servicesArrayjaDie in diesem Array enthaltenen Service-Namen werden in MoneyMoney in der Auswahlliste beim Anlegen eines Kontos angezeigt.
descriptionStringjaBeschreibung der Extension

Zugangsdaten und Feldbeschriftungen

Beim Einrichten eines Bankzugangs fragt MoneyMoney die Zugangsdaten in einem Dialog ab. Der Dialog besteht aus einem Feld für den Benutzernamen, einem Feld für das Passwort und bei Bedarf bis zu zwei weiteren Feldern, z. B. für eine Kundennummer oder ein API-Secret. Die Beschriftungen dieser Felder (»E-Mail-Adresse«, »Teilnehmernummer«, »API-Key« usw.), ihre Anzahl und Reihenfolge, die Eingaberegeln (Länge, nur Ziffern) und ob überhaupt ein Passwort abgefragt wird, sind Bankparameter, die MoneyMoney zentral für jeden Service-Namen pflegt. Sie sind nicht Bestandteil des Aufrufs von WebBanking und können von der Extension nicht gesetzt werden.

Für einen neuen Service-Namen gelten die Standardwerte: ein Feld »Benutzername«, ein Feld »Passwort«, keine weiteren Felder. Wer für eine Community-Extension andere Beschriftungen oder zusätzliche Felder benötigt, teilt sie bei der Einreichung der Extension mit; sie werden dann in die Bankdatenbank von MoneyMoney aufgenommen und mit dem nächsten Update an alle Anwender verteilt.

Die Reihenfolge der Felder im Dialog entspricht der Reihenfolge, in der die Werte an das Skript übergeben werden: als Parameter username, customer, password und credential von InitializeSession bzw. als Elemente des Arrays credentials von InitializeSession2, wobei Felder, die der Bankzugang nicht besitzt, im Array ausgelassen werden.

Lua-Laufzeitumgebung

Die Parameter der Funktion WebBanking sind später im Skript als globale Variablen version, url, services und description zugänglich. Zusätzlich ist auch noch die globale Variable extensionName mit dem Namen der Extension definiert.

Die Variablen MM.productName und MM.productVersion enthalten Informationen zur Anwendung, also MoneyMoney.

Die Ausgabe der Standard-Funktion print wird im Protokoll-Fenster von MoneyMoney angezeigt.

Die Standard-Funktion error bricht die Ausführung des Skripts ab. Die Fehlermeldung wird im Protokoll-Fenster und je nach Kontext auch in einem GUI-Dialog angezeigt.

Das Objekt LocalStorage kann über die Laufzeit des Skripts hinaus zur Speicherung von Informationen genutzt werden.

Das Skript selbst muss UTF-8-kodiert sein und es werden auch alle Strings als UTF-8-Strings zwischen dem Skript und MoneyMoney übergeben, außer es steht in der API-Beschreibung, dass es sich um Binärdaten handelt.

Ablauf

Die Web Banking Engine treibt die Ausführung des Skripts, was bedeutet, dass jedes Skript bestimmte Funktionen als Einsprungspunkte zur Verfügung stellen muss.

Es gibt zwei Anwendungsfälle, für die MoneyMoney die Web Banking Engine startet.

Für den Anwendungsfall Bankzugang einrichten ruft die Web Banking Engine nacheinander folgende Funktionen des Skripts auf:

  1. SupportsBank (Klärung der Zuständigkeit)
  2. InitializeSession (Anmeldung)
  3. ListAccounts (Auflistung der verfügbaren Konten)
  4. für jedes Konto: RefreshAccount (Aktualisierung eines Kontos)
  5. EndSession (Abmeldung)

Der Anwendungsfall Kontenrundruf läuft ähnlich ab:

  1. SupportsBank (Klärung der Zuständigkeit)
  2. InitializeSession (Anmeldung)
  3. für jedes Konto: RefreshAccount (Aktualisierung eines Kontos)
  4. EndSession (Abmeldung)

Die einzelnen Einsprungspunkte sind im Referenzteil dokumentiert.

Vorlage

Folgende Vorlage kann als Ausgangspunkt für eigene Web Banking Extensions dienen.

WebBanking{
  version = 1.00,
  url = "/onlinebanking",
  services = {"Premium Account"},
  description = "Demo"
}

function SupportsBank (protocol, bankCode)
  return protocol == ProtocolWebBanking and bankCode == "Premium Account"
end

function InitializeSession (protocol, bankCode, username, customer, password)
  -- Login.
end

function ListAccounts (knownAccounts)
  -- Return array of accounts.
  local account = {
    name = "Premium Account",
    owner = "Jane Doe",
    accountNumber = "111222333444",
    bankCode = "80007777",
    currency = "EUR",
    type = AccountTypeGiro
  }
  return {account}
end

function RefreshAccount (account, since)
  -- Return balance and array of transactions.
  local transaction = {
    bookingDate = 1325764800,
    purpose = "Hello World!",
    amount = 42.00
  }
  return {balance=42.00, transactions={transaction}}
end

function EndSession ()
  -- Logout.
end

Tipp: Um während der Entwicklung einer Extension nicht bei jeder Skriptänderung die Kontoeinrichtung von MoneyMoney durchlaufen zu müssen, kann man ListAccounts wie in der Vorlage statische Informationen zurückgeben lassen. Wenn man dann erst einmal die Funktionen InitializeSession und EndSession implementiert hat, kann man sich in Ruhe den Funktionen ListAccounts und RefreshAccount widmen.

Tipp: In der Anfangsphase der Entwicklung einer Extension ist es gar nicht nötig, eine Online-Verbindung aufzubauen. Vorab mit einem Browser gespeicherte HTML-Seiten können über Lua-Funktionen geladen werden, so dass man gefahrlos mit dem Skript experimentieren kann.

Einsprungspunkte

SupportsBank

function SupportsBank (protocol, bankCode)

Klärt die Zuständigkeit: Um herauszufinden, welche Extension für welchen Bankzugang zuständig ist, ruft die Web Banking Engine diese Funktion auf.

ParameterTypOptionalBeschreibung
protocolKonstanteneinProtokoll des Bankzugangs. Mögliche Werte sind ProtocolFinTS und ProtocolWebBanking. Der erste Wert ist dazu gedacht, einen FinTS/HBCI-Bankzugang um Konten zu bereichern, die von der Bank nicht über das FinTS/HBCI-Protokoll zur Verfügung gestellt werden. Der zweite Wert ist für Bankzugänge gedacht, die ausschließlich über Web Scraping abgefragt werden.
bankCodeStringneinBankleitzahl oder Service-Name
RückgabeTypBeschreibung
Boolean oder Stringfalse, wenn die Extension für den besagten Bankzugang das Web Scraping nicht übernehmen kann. true, wenn die Extension für den besagten Bankzugang das Web Scraping übernehmen kann. Anstelle von true kann auch die URL der Einstiegsseite des Online-Bankings zurückgegeben werden.

InitializeSession

function InitializeSession (protocol, bankCode, username, customer, password, credential)

Führt einen einfachen Anmeldevorgang durch.

ParameterTypOptionalBeschreibung
protocolKonstanteneinProtokoll des Bankzugangs. Mögliche Werte sind ProtocolFinTS und ProtocolWebBanking.
bankCodeStringneinBankleitzahl oder Service-Name
usernameStringneinInhalt des ersten Eingabefelds des Anmeldedialogs (Benutzername)
customerStringneinInhalt des zweiten Eingabefelds (z. B. Kundennummer). Leer, wenn der Bankzugang kein solches Feld besitzt. Siehe Abschnitt »Zugangsdaten und Feldbeschriftungen«.
passwordStringneinPasswort
credentialStringjaInhalt des dritten Eingabefelds (z. B. API-Secret). Leer, wenn der Bankzugang kein solches Feld besitzt.
RückgabeTypBeschreibung
nilNichts oder nil, wenn die Anmeldung erfolgreich war.
KonstanteLoginFailed, wenn die Zugangsdaten vom Server abgewiesen wurden. Um eine Sperrung des Passworts durch den Server zu vermeiden, werden die betroffenen Konten durch MoneyMoney nicht mehr automatisch aktualisiert, bis die Zugangsdaten durch den Anwender erneut eingegeben wurden.
StringEine Fehlermeldung.

Siehe auch: InitializeSession2

InitializeSession2

function InitializeSession2 (protocol, bankCode, step, credentials, interactive, hbciTanMethods, session)

Diese Alternative zur Funktion InitializeSession führt einen Anmeldevorgang mit Zwei-Faktor-Authentifizierung durch. Beim ersten Aufruf (step=1) enthält credentials die Zugangsdaten. Gibt die Funktion eine Tabelle mit einer Aufforderung zur Zwei-Faktor-Authentifizierung zurück, zeigt MoneyMoney den passenden Dialog an und ruft die Funktion anschließend mit erhöhtem step erneut auf; credentials enthält dann die Antwort des Anwenders. Das wiederholt sich, bis die Funktion nil, LoginFailed oder eine Fehlermeldung zurückgibt.

ParameterTypOptionalBeschreibung
protocolKonstanteneinProtokoll des Bankzugangs. Mögliche Werte sind ProtocolFinTS und ProtocolWebBanking.
bankCodeStringneinBankleitzahl oder Service-Name
stepNumberneinSchritt der Anmeldung, beginnend bei 1. Wird nach jeder Aufforderung zur Zwei-Faktor-Authentifizierung erhöht, siehe unten.
credentialsArrayneinBeim ersten Aufruf die vom Anwender eingegebenen Zugangsdaten in der Reihenfolge der Eingabefelder des Anmeldedialogs: Benutzername, gegebenenfalls zweites und drittes Feld, Passwort (siehe Abschnitt »Zugangsdaten und Feldbeschriftungen«). Bei Folgeaufrufen die Antwort auf die vorherige Aufforderung, siehe unten.
interactiveBooleanneintrue, wenn MoneyMoney im Vordergrund läuft und Dialoge anzeigen kann; false bei einer Aktualisierung im Hintergrund.
hbciTanMethodsArrayjaNur bei ProtocolFinTS: die TAN-Verfahren des FinTS/HBCI-Zugangs als Array von Tabellen (siehe Abschnitt »Datenstruktur eines TAN-Verfahrens«), sonst ein leeres Array.
sessionStringjaAnlass der Sitzung: "refresh" (Kontenrundruf), "new account" (Einrichtung eines Bankzugangs), "statement" (Abruf von Kontoauszügen), "payment" (Zahlungsauftrag) oder "tan media" (Abfrage der TAN-Verfahren).
RückgabeTypBeschreibung
nilNichts oder nil, wenn die Anmeldung erfolgreich war.
KonstanteLoginFailed, wenn die Zugangsdaten vom Server abgewiesen wurden. Um eine Sperrung des Passworts durch den Server zu vermeiden, werden die betroffenen Konten durch MoneyMoney nicht mehr automatisch aktualisiert, bis die Zugangsdaten durch den Anwender erneut eingegeben wurden.
StringEine Fehlermeldung.
TableEine Aufforderung zur Zwei-Faktor-Authentifizierung, siehe unten.

Aufforderung zur Zwei-Faktor-Authentifizierung

Die zurückgegebene Tabelle beschreibt, welchen Dialog MoneyMoney anzeigen soll. Mindestens eines der Felder challenge, label, tanMethod oder tanMethods muss belegt sein, sonst wird die Tabelle nicht als Aufforderung erkannt.

FeldTypOptionalBeschreibung
challengeString oder BinaryjaDie eigentliche Aufforderung: ein Text, die Binärdaten eines Bildes im PNG- oder JPEG-Format, eine URL (https://…) oder die Daten eines chipTAN-Verfahrens (QR-Code, Flickercode). Wie der Inhalt dargestellt wird, ist im Abschnitt »Dialogvarianten« beschrieben. HTML-Tags in einem Text werden entfernt.
labelStringjaBeschriftung des Eingabefelds, z. B. "TAN" oder "Code". Ohne label zeigt der Dialog kein Eingabefeld an.
titleStringjaAnleitungstext über der Aufforderung. Ohne Angabe erzeugt MoneyMoney einen zum Verfahren und zum Anlass passenden Text.
pollBooleanjatrue bei entkoppelten Verfahren (Freigabe in einer Banking-App), bei denen die Extension den Status wiederholt abfragt, statt auf eine Eingabe zu warten. Wirkt nur, wenn kein label angegeben ist.
tanMethodTablejaDas für diese Aufforderung verwendete TAN-Verfahren, siehe Abschnitt »Datenstruktur eines TAN-Verfahrens«. Bestimmt Länge und Zeichenvorrat der Eingabe sowie die von MoneyMoney erzeugten Texte.
tanMethodsArrayjaTAN-Verfahren, aus denen der Anwender zunächst eines auswählen soll (Array von Tabellen, siehe »Datenstruktur eines TAN-Verfahrens«). Wird mit tanMethods ein Auswahldialog angezeigt, werden challenge, label und tanMethod ignoriert.
buttonStringja"next", wenn der Bestätigungsknopf des Dialogs »Weiter« statt »OK« heißen soll, weil danach eine weitere Aufforderung folgt.
startCodeStringjaStartcode eines chipTAN-Verfahrens. Wird in den von MoneyMoney erzeugten Anleitungstext eingesetzt.
appToAppStringjaName einer Banking-App. Eine URL in challenge wird dann nicht im Browser geöffnet, sondern als QR-Code angezeigt, den der Anwender mit der Kamera seines Smartphones scannt, um die App zu starten.
stateStringjaDer state-Parameter einer OAuth-URL in challenge, siehe »Freigabe im Browser«.

Folgeaufrufe

Nach jeder Aufforderung ruft MoneyMoney die Funktion erneut auf. step wird dabei normalerweise um 1 erhöht. Wird tanMethod direkt mit einer Aufforderung angegeben, wird step um 2 erhöht, weil der Schritt für die Auswahl des Verfahrens entfällt, aber mitgezählt wird. Bei entkoppelten Verfahren bleibt step während des Pollings unverändert, solange die Extension dieselbe Aufforderung zurückgibt. Robuste Extensions verlassen sich deshalb nicht auf exakte Werte von step, sondern merken sich ihren Zustand in lokalen Variablen.

Bei Folgeaufrufen hat credentials eine andere Bedeutung als beim ersten Aufruf:

IndexTypBeschreibung
credentials[1]String oder TableDie Antwort des Anwenders auf die vorherige Aufforderung: bei einem Eingabefeld der eingegebene Text, bei einem Captcha das Lösungs-Token, bei einer Freigabe im Browser der code-Parameter der Weiterleitung, bei entkoppelten Verfahren ein leerer String. Nach der Auswahl eines TAN-Verfahrens die Tabelle des gewählten Verfahrens (siehe »Datenstruktur eines TAN-Verfahrens«).
credentials[2]StringLokalisierte Abbruchmeldung, die die Extension zurückgeben sollte, wenn das Polling erfolglos beendet werden muss. Fehlt nach der Auswahl eines TAN-Verfahrens.
credentials[3]Booleantrue, solange ein weiterer Polling-Versuch erlaubt ist. Die Anzahl der Versuche steuert MoneyMoney; die Extension sollte kein eigenes Zeitlimit implementieren. Fehlt nach der Auswahl eines TAN-Verfahrens.

Welche Art von Dialog MoneyMoney anzeigt, ergibt sich aus der Kombination der Felder. Die folgenden Dialogvarianten decken die üblichen Fälle ab.

Eingabe einer TAN oder eines Codes

Ein Text in challenge und eine Beschriftung in label ergeben einen Dialog mit Anleitungstext und Eingabefeld. Mit tanMethod legt die Extension Länge und Zeichenvorrat der Eingabe fest; ohne tanMethod akzeptiert das Feld beliebigen Text.

return {
  title="Bitte geben Sie den per SMS erhaltenen Code ein.",
  label="Code",
  tanMethod={
    name="SMS",
    tanLength=6,
    isNumeric=true
  }
}

Die kürzeste Form ist ein Eingabefeld ohne weiteren Text:

return {label="mobileTAN"}

Bild

Sind in challenge die Binärdaten eines PNG- oder JPEG-Bildes enthalten, zeigt der Dialog das Bild an, z. B. eine photoTAN-Grafik oder ein Bild-Captcha. Mit label kommt ein Eingabefeld hinzu.

local image = connection:get(
  html:xpath("//img[contains(@alt,'photoTAN')]"):attr("src")
)
return {label="photoTAN", challenge=image}

QR-Code

Für einen QR-Code gibt es zwei Wege. Entweder liefert die Extension den QR-Code als Bild (siehe oben), oder sie überlässt MoneyMoney die Darstellung: Enthält challenge eine URL (https://…) und ist tanMethod.name der lokalisierte Name MM.localizeText("QR Code"), erzeugt MoneyMoney den QR-Code selbst. Der Name muss exakt über MM.localizeText gebildet werden, da er je nach Sprache von MoneyMoney unterschiedlich lautet; andernfalls wird die URL als Text angezeigt.

Ohne label wird der QR-Code als entkoppeltes Verfahren behandelt: MoneyMoney zeigt einen Wartehinweis an und die Extension fragt mit poll=true den Status ab. Mit label erscheint zusätzlich ein Eingabefeld, z. B. für chipTAN QR.

return {
  challenge=qrUrl,
  tanMethod={
    name=MM.localizeText("QR Code")
  },
  poll=true
}

Entkoppeltes Verfahren

Bei einer Freigabe in einer Banking-App gibt es nichts einzugeben. Die Extension gibt einen Text in challenge und poll=true zurück, MoneyMoney zeigt einen Wartehinweis mit Abbrechen-Knopf an und ruft die Funktion so lange erneut auf, bis die Extension nil (Freigabe erteilt) oder eine Fehlermeldung zurückgibt. Zwischen den Aufrufen sollte die Extension mit MM.sleep eine kurze Pause einlegen. Ist tanMethod.name ein MoneyMoney bekanntes App-Verfahren (z. B. "pushTAN", "appTAN", "photoTAN push"), erzeugt MoneyMoney die Texte des Dialogs selbst.

if step > 1 then
  if pollAuthorizationStatus() == "approved" then
    return nil
  elseif credentials[3] then
    MM.sleep(2)
    return {
      challenge="Bitte bestätigen Sie die Anmeldung in der Banking-App.",
      poll=true
    }
  else
    return credentials[2]
  end
end

Auswahl des TAN-Verfahrens

Bietet die Bank mehrere Verfahren an, gibt die Extension sie in tanMethods zurück. MoneyMoney zeigt einen Auswahldialog an und übergibt beim nächsten Aufruf die Tabelle des gewählten Verfahrens in credentials[1]. Die Extension gibt daraufhin die eigentliche Aufforderung zurück. MoneyMoney merkt sich die Auswahl anhand von hbciMethod und wählt das Verfahren beim nächsten Mal vor. Verfahren mit errorMessage werden angezeigt, sind aber nicht auswählbar; die Meldung erklärt dem Anwender den Grund.

if step == 1 then
  -- Login.
  return {
    tanMethods={
      {
        name="pushTAN",
        hbciMethod="700"
      },
      {
        name="mobileTAN",
        hbciMethod="701",
        mediumName="+49 *** 4567"
      }
    }
  }
elseif step == 2 then
  local tanMethod = credentials[1]
  if tanMethod.name == "pushTAN" then
    -- Trigger push notification.
    return {challenge="pushTAN", poll=true}
  else
    -- Request SMS.
    return {label=tanMethod.label}
  end
else
  -- Poll pushTAN or submit mobileTAN from credentials[1].
end

Hat die Bank bereits beim Login eine Push-Freigabe ausgelöst, kann zusammen mit tanMethods auch poll=true gesetzt werden. Der Auswahldialog wartet dann parallel auf die Freigabe über das erste App-Verfahren der Liste, und die Funktion wird wie bei entkoppelten Verfahren wiederholt aufgerufen.

Captcha

Enthält challenge die Script-URL eines unterstützten Captcha-Anbieters, zeigt MoneyMoney das Captcha in einem eingebetteten Browser an; unsichtbare Varianten werden zunächst ohne Zutun des Anwenders versucht. Das Lösungs-Token wird beim nächsten Aufruf in credentials[1] übergeben. Unterstützt werden Google reCAPTCHA (https://www.recaptcha.net/recaptcha/api.js oder enterprise.js), hCaptcha (https://js.hcaptcha.com/1/api.js), FriendlyCaptcha (https://cdn.jsdelivr.net/npm/friendly-challenge/widget.module.min.js oder @friendlycaptcha/sdk/site.min.js) und Amazon WAF (https://….token.awswaf.com/…/challenge.js). Als Query-Parameter erwartet MoneyMoney den sitekey der Website, optional type=checkbox für die sichtbare Variante und referer mit der URL der Seite, in die das Captcha eingebettet ist.

return {
  challenge="https://www.recaptcha.net/recaptcha/api.js?sitekey=" ..
  siteKey ..
  "&type=checkbox&referer=" ..
  MM.urlencode(loginUrl)
}

Freigabe im Browser

Enthält challenge eine sonstige https://-URL, öffnet MoneyMoney sie in einem eigenen Browserfenster, z. B. für eine OAuth-Autorisierung. Leitet die Website anschließend auf die vereinbarte Weiterleitungs-URL um, übergibt MoneyMoney den code-Parameter (ersatzweise access_token, auth_code, tokenid oder ähnliche Parameter) beim nächsten Aufruf in credentials[1]. Den state-Parameter der URL kann die Extension in state mitgeben; fehlt er, liest MoneyMoney ihn aus der URL oder hängt selbst einen zufälligen Wert an. Der Host der URL muss in MoneyMoney freigeschaltet sein, andernfalls bricht die Sitzung mit einer entsprechenden Fehlermeldung ab. Für Community-Extensions ist diese Variante deshalb nur in Absprache mit dem MoneyMoney-Support nutzbar.

return {challenge=authorizeUrl, state=state}

Siehe auch: InitializeSession, FetchStatements

ListAccounts

function ListAccounts (knownAccounts)

Listet alle Konten auf, die mittels Web Scraping abgefragt werden können.

ParameterTypOptionalBeschreibung
knownAccountsArrayneinWenn das Protokoll des Bankzugangs FinTS/HBCI ist, Web Scraping also nur als Ergänzung dient, dann enthält dieser Parameter ein Array mit schon bekannten Konten. Das Skript kann anhand dieses Arrays feststellen, welche Kontoinformationen es nicht mehr über Web Scraping abzufragen braucht. Die Struktur der Array-Elemente ist im Abschnitt »Datenstruktur eines Kontos« beschrieben.
RückgabeTypBeschreibung
ArrayKonten, die mittels Web Scraping abgefragt werden können. Die Struktur der Array-Elemente ist im Abschnitt »Datenstruktur eines Kontos« beschrieben.
StringEine Fehlermeldung.

Für jedes Konto muss mindestens die Kontonummer zurückgegeben werden, andernfalls wird das Konto ignoriert.

RefreshAccount

function RefreshAccount (account, since)

Fragt Saldo- und Umsatzinformationen oder den Wertpapierbestand eines Kontos ab.

ParameterTypOptionalBeschreibung
accountTableneinDas Konto, das abgefragt werden soll. Die Struktur ist im Abschnitt »Datenstruktur eines Kontos« beschrieben.
sinceNumberneinDer Buchungstag, ab dem Umsätze geliefert werden sollten. Das Skript braucht ältere Umsätze nicht mehr zu liefern. Die Angabe erfolgt in Form eines POSIX-Zeitstempels. Bei Depots wird anstelle dieses Parameters nil übergeben.
RückgabeTypBeschreibung
TableEine Tabelle mit den unten beschriebenen Feldern.
StringEine Fehlermeldung.

Felder der zurückgegebenen Tabelle:

FeldTypBeschreibung
balanceNumberKontostand
balancesArrayEin Array mit Tupeln (Kontostand, Währung). Dieses Feld sollte nur dann an Stelle von balance zurückgegeben werden, wenn das Konto mehrere Kontostände in unterschiedlichen Währungen besitzt.
pendingBalanceNumberSumme der vorgemerkten Umsätze
transactionsArrayEin Array mit Umsätzen. Diese Umsätze werden als »neu« klassifiziert, wenn sie noch nicht in der Datenbank von MoneyMoney vorhanden sind. Andernfalls werden sie als Duplikate verworfen. Das Array sollte nach Buchungstag geordnet sein, mit den neuesten Umsätzen vorne. Die Struktur der Array-Elemente ist im Abschnitt »Datenstruktur eines Umsatzes« beschrieben.
securitiesArrayEin Array mit Depotpositionen. Die Struktur der Array-Elemente ist im Abschnitt »Datenstruktur von Wertpapieren« beschrieben.
bonusPointsNumberAnzahl der Punkte in einem Bonusprogramm

Bei Depots wird nur das Feld securities erwartet, bei allen anderen Konten die Felder balance/balances und transactions. Wenn diese fehlen oder den Wert nil enthalten, wird in der GUI eine Fehlermeldung angezeigt, dass der Kontostand bzw. die Umsätze bzw. der Wertpapierbestand nicht abgefragt werden konnte.

Für jeden Umsatz müssen mindestens Betrag und Buchungstag angegeben werden, andernfalls führt dies ebenfalls zu einer Fehlermeldung.

FetchStatements

function FetchStatements (accounts, knownIdentifiers, step, credentials, interactive)

Ruft elektronische Kontoauszüge und andere Postfach-Dokumente (PDF) ab. Diese Funktion ist optional — nur wenn das Skript sie definiert, bietet MoneyMoney den Dokumentenabruf für den Bankzugang an. Anders als RefreshAccount wird sie nicht je Konto aufgerufen, sondern einmal mit allen betroffenen Konten.

ParameterTypOptionalBeschreibung
accountsArrayneinDie Konten, für die Dokumente abgerufen werden sollen. Die Struktur der Array-Elemente ist im Abschnitt »Datenstruktur eines Kontos« beschrieben.
knownIdentifiersTableneinTabelle, deren Schlüssel die identifier bereits früher abgerufener Dokumente sind. Dokumente, deren Kennung hier enthalten ist, braucht das Skript nicht erneut herunterzuladen.
stepNumberneinSchritt der Zwei-Faktor-Authentifizierung, beginnend bei 1 — falls der Server für den Dokumentenabruf eine Freigabe verlangt.
credentialsArrayneinBei Folgeaufrufen nach einer Challenge belegt wie bei InitializeSession2 (Antwort, Abbruchmeldung, Polling-Status).
interactiveBooleanneinMoneyMoney wird im Vordergrund oder Hintergrund ausgeführt
RückgabeTypBeschreibung
TableEine Tabelle mit dem Feld statements: ein Array von Dokumenten, geordnet mit dem neuesten Dokument vorne. Die Struktur der Array-Elemente ist im Abschnitt »Datenstruktur eines Kontoauszugs« beschrieben.
TableEine Aufforderung zur Zwei-Faktor-Authentifizierung wie bei InitializeSession2 (siehe dort »Aufforderung zur Zwei-Faktor-Authentifizierung«) — die Funktion wird dann mit erhöhtem step erneut aufgerufen.
StringEine Fehlermeldung.

Siehe auch: InitializeSession2

EndSession

function EndSession ()

Führt den Abmeldevorgang durch.

RückgabeTypBeschreibung
nilNichts oder nil, wenn die Abmeldung erfolgreich war.
StringEine Fehlermeldung.

Datenstrukturen

Datenstruktur eines Kontos

Die Informationen eines Kontos werden in einer Lua-Tabelle gespeichert. Folgende Felder können belegt werden, soweit deren Inhalt bekannt ist:

FeldTypBeschreibung
nameStringBezeichnung des Kontos
ownerStringName des Kontoinhabers
accountNumberStringKontonummer
subAccountStringUnterkontomerkmal
portfolioBooleantrue für Depots und false für alle anderen Konten
bankCodeStringBankleitzahl
currencyStringKontowährung
ibanStringIBAN
bicStringBIC
typeKonstanteKontoart, siehe unten

Mögliche Werte für die Kontoart type:

KonstanteBedeutung
AccountTypeGiroGirokonto
AccountTypeSavingsSparkonto
AccountTypeFixedTermDepositFestgeldanlage
AccountTypeLoanDarlehenskonto
AccountTypeCreditCardKreditkarte
AccountTypePortfolioWertpapierdepot
AccountTypeOtherSonstige

Fehlt das Feld type, versucht MoneyMoney beim Anlegen des Kontos, die Kontoart aus Kontonummer und Kontobezeichnung abzuleiten. Eine Kontonummer mit 16 Zeichen oder mit maskierten Stellen (x, *) wird dabei als Kreditkarte gewertet. Ein explizit angegebener Wert wird unverändert übernommen, auch AccountTypeOther. Die Kontoart wird nur beim Anlegen gesetzt und beim Aktualisieren nicht mehr verändert.

Datenstruktur eines Umsatzes

Die Daten eines Umsatzes werden in einer Lua-Tabelle gespeichert:

FeldTypBeschreibung
nameStringName des Auftraggebers/Zahlungsempfängers
accountNumberStringKontonummer oder IBAN des Auftraggebers/Zahlungsempfängers
bankCodeStringBankleitzahl oder BIC des Auftraggebers/Zahlungsempfängers
amountNumberBetrag
currencyStringWährung
bookingDateNumberBuchungstag; Die Angabe erfolgt in Form eines POSIX-Zeitstempels.
valueDateNumberWertstellungsdatum; Die Angabe erfolgt in Form eines POSIX-Zeitstempels.
purposeStringVerwendungszweck; Mehrere Zeilen können durch Zeilenumbrüche (\n) getrennt werden.
transactionCodeNumberGeschäftsvorfallcode
textKeyExtensionNumberTextschlüsselergänzung
purposeCodeStringSEPA-Verwendungsschlüssel
bookingKeyStringSWIFT-Buchungsschlüssel
bookingTextStringUmsatzart
primanotaNumberStringPrimanota-Nummer
batchReferenceStringSammlerreferenz
endToEndReferenceStringSEPA-Ende-zu-Ende-Referenz
mandateReferenceStringSEPA-Mandatsreferenz
creditorIdStringSEPA-Gläubiger-ID
returnReasonStringRückgabegrund
bookedBooleanGebuchter oder vorgemerkter Umsatz

Datenstruktur von Wertpapieren

Die Daten von Wertpapieren werden in einer Lua-Tabelle gespeichert:

FeldTypBeschreibung
nameStringBezeichnung des Wertpapiers
isinStringISIN
securityNumberStringWKN
quantityNumberNominalbetrag oder Stückzahl
currencyOfQuantityStringWährung bei Nominalbetrag oder nil bei Stückzahl
purchasePriceNumberKaufpreis oder Kaufkurs
currencyOfPurchasePriceStringVon der Kontowährung abweichende Währung des Kaufpreises
exchangeRateOfPurchasePriceNumberWechselkurs zum Kaufzeitpunkt
priceNumberAktueller Preis oder Kurs
currencyOfPriceStringVon der Kontowährung abweichende Währung des Preises
exchangeRateOfPriceNumberAktueller Wechselkurs
amountNumberWert der Depotposition in Kontowährung
originalAmountNumberWert der Depotposition in Originalwährung
currencyOfOriginalAmountStringOriginalwährung
marketStringName des Börsenplatzes
tradeTimestampNumberNotierungszeitpunkt; Die Angabe erfolgt in Form eines POSIX-Zeitstempels.

Datenstruktur eines Kontoauszugs

Die von FetchStatements gelieferten Dokumente werden in Lua-Tabellen gespeichert:

FeldTypBeschreibung
pdfBinaryDas Dokument als PDF. Alternativ kann ein ZIP-Archiv übergeben werden; die darin enthaltenen PDF-Dateien werden automatisch entpackt. Dieses Feld ist Pflicht.
identifierStringEindeutige Kennung des Dokuments, z. B. eine Dokument-ID des Servers. Anhand dieser Kennung erkennt MoneyMoney bereits abgerufene Dokumente (siehe Parameter knownIdentifiers von FetchStatements).
nameStringAnzeigename des Dokuments
filenameStringDateiname des Dokuments
creationDateNumberErstellungsdatum; Die Angabe erfolgt in Form eines POSIX-Zeitstempels.
timezoneStringZeitzone, in der creationDate zu interpretieren ist, z. B. "Europe/Berlin"
accountTableDas Konto, dem das Dokument zugeordnet werden soll (aus dem accounts-Parameter von FetchStatements). Ohne dieses Feld wird das Dokument dem aktuellen Konto zugeordnet.

Datenstruktur eines TAN-Verfahrens

TAN-Verfahren werden bei InitializeSession2 und FetchStatements in den Feldern tanMethod und tanMethods an MoneyMoney übergeben und nach der Auswahl durch den Anwender in credentials[1] an die Extension zurückgegeben. Auch die TAN-Verfahren eines FinTS/HBCI-Zugangs (Parameter hbciTanMethods) haben diese Struktur.

FeldTypBeschreibung
nameStringAnzeigename des Verfahrens, z. B. "pushTAN", "mobileTAN" oder "photoTAN". Dieses Feld ist Pflicht. Für MoneyMoney bekannte App-Verfahren (z. B. "pushTAN", "appTAN", "photoTAN push") und für MM.localizeText("QR Code") erzeugt MoneyMoney passende Dialogtexte, siehe »Dialogvarianten« bei InitializeSession2.
mediumNameStringBezeichnung des TAN-Mediums, z. B. eine maskierte Mobilfunknummer oder ein Gerätename. Wird im Auswahldialog neben dem Namen angezeigt.
hbciMethodStringKennung des Verfahrens, üblicherweise dreistellig wie bei FinTS (z. B. "700"). Anhand dieser Kennung merkt sich MoneyMoney die Auswahl des Anwenders.
errorMessageStringIst dieses Feld belegt, wird das Verfahren im Auswahldialog angezeigt, ist aber nicht auswählbar; die Meldung erklärt den Grund (z. B. Verfahren muss erst auf der Website freigeschaltet werden).
tanLengthNumberFeste Länge der Eingabe. Standard: 6.
minLengthNumberMindestlänge der Eingabe, alternativ zu tanLength.
maxLengthNumberMaximale Länge der Eingabe, alternativ zu tanLength.
isNumericBooleantrue (Standard), wenn nur Ziffern eingegeben werden dürfen. Bei false sind auch Buchstaben erlaubt; die Eingabe wird dann in Großbuchstaben umgewandelt, sofern isUppercase nicht false ist.
isUppercaseBooleantrue, wenn die Eingabe in Großbuchstaben umgewandelt werden soll.
isPreferredBooleantrue, wenn das Verfahren im Auswahldialog vorausgewählt sein soll.
labelStringNur in den von MoneyMoney übergebenen Tabellen: die aus dem Namen abgeleitete Beschriftung für das Eingabefeld, z. B. "TAN". Kann von der Extension als label der Aufforderung weiterverwendet werden.

Objekt für eine HTTPS-Verbindung

Connection

connection = Connection()

Erzeugt ein Objekt, mit dem eine HTTPS-Verbindung zu einem Webserver aufgebaut werden kann.

connection:request

content, charset, mimeType, filename, headers = connection:request(method, url[, postContent, postContentType, headers])

Fordert eine Ressource vom Webserver an.

Falls noch keine HTTPS-Verbindung zum Server besteht, wird diese aufgebaut. Das Connection-Objekt verwendet HTTP-Pipelining. Wenn der Server dies auch anbietet und solange über den URL-Parameter nicht der Server gewechselt wird, werden alle Anfragen über dieselbe HTTPS-Verbindung geschickt.

Für JSON-basierte REST-APIs sollte im Parameter headers das HTTP-Header-Feld Accept auf "application/json" gesetzt werden. Dann wird auch bei einem HTTP-Fehler die Serverantwort im Skript zurückgegeben. Andernfalls wird im Fehlerfall die Ausführung des Skripts abgebrochen und stattdessen in der GUI eine Fehlermeldung angezeigt.

ParameterTypOptionalBeschreibung
methodStringneinHTTP-Request-Methode; Mögliche Werte sind "GET", "POST", "PUT", "PATCH" und "DELETE".
urlStringneinServer-URL; Die URL darf absolut oder relativ sein. Bei der ersten Server-Anfrage muss eine absolute URL angegeben werden. Relative URLs beziehen sich wie üblich auf die gerade aktive, d.h. zuletzt aufgerufene URL.
postContentBinaryjaDie Daten, die mit einem HTTP-POST-Request an den Server gesendet werden sollen
postContentTypeStringjaDer Inhalt des Felds Content-Type für den HTTP-POST-Header
headersDictionaryjaWeitere HTTP-Header-Felder
RückgabeTypBeschreibung
contentBinaryDaten vom Server
charsetStringDer Zeichensatz, mit dem die vom Server gelieferten Daten zu interpretieren sind
mimeTypeStringMIME-Type der vom Server gelieferten Daten
filenameStringDateiname aus dem HTTP-Header-Feld Content-Disposition
headersDictionaryVom Server gelieferte HTTP-Header-Felder

Zur Bestimmung des Zeichensatzes und des MIME-Typs werden der HTTP-Header des Servers und <meta>-Tags im HTML-Code herangezogen.

content, charset, mimeType = connection:request(
  "POST",
  "/onlinebanking",
  "username=foo&password=bar",
  "application/x-www-form-urlencoded; charset=UTF-8"
)
print(content)   -- "<html>\n<head>\n<title>[…]"
print(charset)   -- "UTF-8"
print(mimeType)  -- "text/html"

Tipp: Die Art und Reihenfolge der Rückgabewerte ist so gewählt, dass sie sich für die Erzeugung eines HTML-Objektes verwenden lassen:

html = HTML(connection:request("GET", "/onlinebanking"))

connection:get

content, charset, mimeType = connection:get(url)

Kurzform für: connection:request("GET", url)

Siehe auch: connection:request

connection:post

content, charset, mimeType = connection:post(url, postContent[, postContentType])

Kurzform für: connection:request("POST", url, postContent, postContentType)

Siehe auch: connection:request

connection:close

connection:close()

Schließt die HTTPS-Verbindung zum Server. Normalerweise braucht diese Methode nicht aufgerufen werden, da nach der Ausführung des Skripts alle offenen Verbindungen automatisch geschlossen werden.

connection:getBaseURL

url = connection:getBaseURL()

Gibt die zuletzt aufgerufene URL zurück.

RückgabeTypBeschreibung
urlStringDie zuletzt aufgerufene URL

connection:setCookie

connection:setCookie(cookie)

Fügt dem Cookie-Speicher weitere Cookies hinzu oder ändert vorhandene Cookies.

Jedes Skript erhält für die Dauer seiner Ausführung einen Speicher für HTTP-Cookies. Dieser Speicher wird von allen HTTP-Verbindungen, die innerhalb desselben Skripts aufgebaut werden, gemeinsam genutzt. Die Cookies werden automatisch aus dem HTTP-Header des Servers und den <meta>-Tags im HTML-Code extrahiert. Nach der Ausführung des Skripts werden alle Cookies wieder gelöscht.

ParameterTypOptionalBeschreibung
cookieStringneinHTTP-Cookie; Das Format ist identisch zum Feld Set-Cookie im HTTP-Header.
connection:setCookie("SESSION=foobar; path=/")

connection:getCookies

cookies = connection:getCookies()

Fragt die HTTP-Cookies ab, die für die gerade aktive, d.h. zuletzt aufgerufene URL gültig sind.

RückgabeTypBeschreibung
cookiesStringHTTP-Cookies; Das Format ist identisch zum Feld Cookie im HTTP-Header.

connection.useragent

Dieses Attribut vom Typ String enthält den Wert des Felds User-Agent für den HTTP-Header. Durch Veränderung dieses Werts lässt sich gegenüber dem Webserver ein bestimmter Browser oder ein mobiles Endgerät simulieren.

connection.useragent = "Mozilla/5.0 (compatible; " ..
  MM.productName ..
  "/" ..
  MM.productVersion ..
  ")"

connection.language

Dieses Attribut vom Typ String enthält den Wert des Felds Accept-Language für den HTTP-Header. Bei manchen Servern lässt sich so die Sprache der Inhalte auswählen. Als Standardwert ist die Sprache des Betriebssystems voreingestellt.

connection.language = "de-DE"

Objekt für ein HTML-Dokument

HTML

html = HTML(content[, charset])

Erzeugt ein neues Objekt, mit dem sich in einem HTML-Dokument navigieren lässt.

ParameterTypOptionalBeschreibung
contentBinaryneinHTML-Code
charsetStringjaDer Zeichensatz, mit dem der HTML-Code zu interpretieren ist. Wenn dieser Parameter fehlt, wird der Zeichensatz aus den <meta>-Tags extrahiert.

html:xpath

elements = html:xpath(query)

Wählt HTML-Elemente mittels eines XPath-Ausdrucks aus.

ParameterTypOptionalBeschreibung
queryStringneinXPath-Ausdruck in der XML Path Language Version 1.0; Alle Tag- und Attributsnamen müssen klein geschrieben werden.
RückgabeTypBeschreibung
elementsObjektEine Liste von HTML-Elementen, die durch den XPath-Ausdruck ausgewählt wurden. Die Methoden, die auf dieses Objekt angewendet werden können, sind im Abschnitt »Objekt für HTML-Elemente« beschrieben.

Tipp: Die Entwicklertools von Webbrowsern bieten komfortable Werkzeuge an, um XPath-Ausdrücke zu schreiben und zu testen.

html:html

text = html:html()

Generiert aus dem HTML-Dokument neuen, formatierten HTML-Code. Dieser ist nicht unbedingt identisch zum ursprünglichen HTML-Code. Der generierte HTML-Code ist immer UTF-8-kodiert.

RückgabeTypBeschreibung
textStringHTML-Code

Objekt für HTML-Elemente

elements:length

count = elements:length()

Liefert die Anzahl der HTML-Elemente, die sich im Objekt elements befinden.

RückgabeTypBeschreibung
countNumberAnzahl der HTML-Elemente

elements:get

elements = elements:get(n)

Wählt das n-te HTML-Element aus elements aus.

ParameterTypOptionalBeschreibung
nNumberneinIndex des auszuwählenden HTML-Elements; Wie in Lua üblich, beginnt die Indexierung bei 1.
RückgabeTypBeschreibung
elementsObjektDer Rückgabewert besteht selbst wieder aus einem Objekt für HTML-Elemente. Wenn n ein gültiger Index ist, enthält elements das n-te HTML-Element. Andernfalls ist elements leer.
if elements:get(2):length() == 1 then print "Fnord!" end

elements:each

elements:each(function (index, element))

Durchläuft alle HTML-Elemente von elements und führt für jedes HTML-Element eine Aktion aus.

ParameterTypOptionalBeschreibung
functionFunctionneinEine Funktion, die für jedes HTML-Element ausgeführt werden soll. Ihre Parameter: index (Number) — Index des aktuellen HTML-Elements, beginnend bei 1; element (Objekt) — ein Objekt für HTML-Elemente mit genau einem HTML-Element.

Wenn die Funktion den Wert false zurückgibt, wird die Methode each abgebrochen.

elements:each(function (index, element)
  print (index .. "=" .. element:text())
end)

elements:reverse

elements = elements:reverse()

Dreht die Reihenfolge der HTML-Elemente von elements um.

RückgabeTypBeschreibung
elementsObjektDer Rückgabewert besteht selbst wieder aus einem Objekt für HTML-Elemente, welches die HTML-Elemente in umgekehrter Reihenfolge enthält.

elements:children

elements = elements:children()

Wählt die unmittelbaren Kindelemente der HTML-Elemente aus elements aus.

RückgabeTypBeschreibung
elementsObjektDer Rückgabewert besteht selbst wieder aus einem Objekt für HTML-Elemente und enthält die HTML-Kindelemente.

elements:xpath

elements = elements:xpath(query)

Wählt mittels eines XPath-Ausdrucks HTML-Elemente relativ zum ersten HTML-Element von elements aus. Der XPath-Ausdruck query muss dazu ebenfalls relativ sein, d.h. mit einem Punkt beginnen.

ParameterTypOptionalBeschreibung
queryStringneinRelativer XPath-Ausdruck (beginnend mit einem Punkt) in der XML Path Language Version 1.0; Alle Tag- und Attributsnamen müssen klein geschrieben werden.
RückgabeTypBeschreibung
elementsObjektEine Liste von HTML-Elementen, die durch den XPath-Ausdruck ausgewählt wurden.

elements:text

text = elements:text()

Liefert den kombinierten Text, der sich zwischen den HTML-Tags der HTML-Elemente elements und deren Kindelementen befindet.

RückgabeTypBeschreibung
textStringText, der sich zwischen den HTML-Tags befindet.

elements:attr (lesen)

value = elements:attr(attribute)

Gibt den Inhalt eines Attributs des ersten HTML-Elements aus elements zurück.

ParameterTypOptionalBeschreibung
attributeStringneinName des Attributs
RückgabeTypBeschreibung
valueStringInhalt des Attributs

elements:attr (schreiben)

elements:attr(attribute, value)

Ändert ein Attribut für alle HTML-Elemente aus elements.

ParameterTypOptionalBeschreibung
attributeStringneinName des Attributs
valueStringneinNeuer Inhalt des Attributs

elements:val

value = elements:val()

Gibt den Wert eines Formularfelds zurück. Das erste HTML-Element in elements muss ein Formularfeld sein. Im Gegensatz zur Methode elements:attr("value") berücksichtigt diese Methode auch das Attribut disabled und wertet die ausgewählte Option von Auswahllisten (<select>-Tag) aus.

RückgabeTypBeschreibung
valueStringWert des Formularfelds

elements:select

elements:select(value)

Wählt eine Option in einer Auswahlliste (<select>-Tag) aus. Das erste HTML-Element in elements muss eine Auswahlliste sein. Im Gegensatz zur Methode elements:attr("selected", "selected") berücksichtigt diese Methode auch das Attribut disabled und wählt die übrigen Optionen ab.

ParameterTypOptionalBeschreibung
valueStringneinAusgewählte Option

elements:click

method, url[, postContent, postContentType] = elements:click()

Erzeugt aus einem HTML-Link oder einem HTML-Formular die Parameter für einen HTTP-Request. In elements muss als erstes HTML-Element ein Link (<a href>-Tag) oder ein Submit-Button (<input type="submit">-Tag, <button>-Tag) oder ein Image-Button (<input type="image">-Tag) vorhanden sein.

Bei einem HTML-Link wird die verlinkte URL zurückgegeben. Bei einem Formular werden die Werte der <input>-Tags URL-kodiert und entweder als GET-Parameter an die URL angehängt oder als POST-Parameter zurückgegeben.

RückgabeTypBeschreibung
methodStringHTTP-Request-Methode; Mögliche Werte sind "GET" und "POST".
urlStringServer-URL
postContentBinaryDie Daten, die mit einem HTTP-POST-Request an den Server gesendet werden sollen.
postContentTypeStringDer Inhalt des Felds Content-Type für den HTTP-POST-Header.

Tipp: Die Art und Reihenfolge der Rückgabewerte ist so gewählt, dass sie sich für einen HTTP-Request verwenden lassen:

connection:request(elements:click())

elements:submit

method, url[, postContent, postContentType] = elements:submit()

Erzeugt aus einem HTML-Formular ohne Submit-Button die Parameter für einen HTTP-Request. In elements muss als erstes HTML-Element ein Formular (<form>-Tag) vorhanden sein. Die Werte der <input>-Tags werden URL-kodiert und entweder als GET-Parameter an die URL angehängt oder als POST-Parameter zurückgegeben. Die Werte von Submit-Buttons (<input type="submit">-Tag) werden ignoriert, da das Formular ohne Submit-Button generiert wird.

RückgabeTypBeschreibung
methodStringHTTP-Request-Methode; Mögliche Werte sind "GET" und "POST".
urlStringServer-URL
postContentBinaryDie Daten, die mit einem HTTP-POST-Request an den Server gesendet werden sollen.
postContentTypeStringDer Inhalt des Felds Content-Type für den HTTP-POST-Header.

Tipp: Die Art und Reihenfolge der Rückgabewerte ist so gewählt, dass sie sich für einen HTTP-Request verwenden lassen:

connection:request(elements:submit())

Objekt für ein JSON-Dokument

JSON():dictionary

fields = JSON(json):dictionary()

Konvertiert ein JSON-Dokument in eine Lua-Datenstruktur.

ParameterTypOptionalBeschreibung
jsonBinaryneinJSON-Dokument
RückgabeTypBeschreibung
fieldsDictionary oder ArrayLua-Datenstruktur des JSON-Dokuments

JSON():set():json

json = JSON():set(fields):json()

Konvertiert eine Lua-Datenstruktur in ein JSON-Dokument.

ParameterTypOptionalBeschreibung
fieldsDictionary oder ArrayneinLua-Datenstruktur des JSON-Dokuments
RückgabeTypBeschreibung
jsonBinaryJSON-Dokument

Objekt für ein PDF-Dokument

PDF():text

text = PDF(pdf):text()

Extrahiert, so gut wie möglich, den unformatierten Text aus einem PDF-Dokument.

ParameterTypOptionalBeschreibung
pdfBinaryneinPDF-Dokument
RückgabeTypBeschreibung
textStringUnformatierter Text

Persistenter Speicher

LocalStorage

Das globale Objekt LocalStorage ist eine Lua-Tabelle, deren Inhalt über die Laufzeit des Skripts hinaus erhalten bleibt. Der Speicher ist je Bankzugang getrennt und wird nach der Ausführung des Skripts automatisch gesichert und beim nächsten Lauf wiederhergestellt — typischer Einsatz sind Geräteschlüssel, Registrierungs-IDs oder Sitzungs-Tokens, die eine erneute starke Kundenauthentifizierung ersparen.

if not LocalStorage.deviceKey then
  LocalStorage.deviceKey = MM.ecGenerateKeys("prime256v1")
end

Beim Sichern werden folgende Werte unterstützt:

TypVerhalten
Number, Boolean, StringWerden unverändert gesichert; Strings dürfen Binärdaten enthalten.
TableWird einschließlich verschachtelter Tabellen gesichert.
Connection-ObjektWird als Sonderfall gesichert: Die zuletzt aufgerufene URL, alle HTTP-Cookies, useragent und language bleiben erhalten. Beim nächsten Lauf steht damit eine Connection mit der alten Cookie-Sitzung zur Verfügung — Server-Sitzungen können so App-Neustarts überleben.
HTML-ObjektWird als UTF-8-HTML-Code gesichert und beim Laden wieder geparst.
Funktionen und andere ObjekteWerden nicht gesichert; sie sind beim nächsten Lauf nil (betrifft z. B. JSON-Objekte und HTML-Elementlisten — bei Bedarf stattdessen den Ursprungs-String speichern).

Skripte sollten beim Lesen stets mit fehlenden Werten rechnen (nil-Prüfung wie im Beispiel): Der Speicher ist leer, wenn der Bankzugang neu eingerichtet wurde, und einzelne Felder können nil sein, wenn eine ältere Skriptversion sie noch nicht geschrieben hat.

MM-Funktionen

Protokoll und Ablauf

MM.printStatus

MM.printStatus(...)

Zeigt eine Statusmeldung an. Diese Funktion arbeitet ähnlich zur Lua-Funktion print: Die Parameter werden mittels der Lua-Funktion tostring zu einem String konvertiert und im Protokoll-Fenster von MoneyMoney angezeigt. Zusätzlich wird der String als Statusmeldung in der GUI angezeigt.

Siehe auch: MM.printDebug

MM.printDebug

MM.printDebug(...)

Schreibt eine Debug-Meldung ins Protokoll-Fenster. Diese Funktion arbeitet wie print, kennzeichnet die Ausgabe aber als Debug-Meldung — anders als MM.printStatus erscheint sie nicht als Statusmeldung in der GUI.

Siehe auch: MM.printStatus

MM.sleep

MM.sleep(seconds)

Unterbricht die Ausführung des Skripts für ein paar Sekunden.

ParameterTypOptionalBeschreibung
secondsNumberneinAnzahl der Sekunden

Lokalisierung

MM.localizeText

str = MM.localizeText(str)

Übersetzt einen Text. Diese Funktion ist primär für die mit MoneyMoney ausgelieferten Extensions gedacht. Sie ist ein Wrapper für die Cocoa-Funktion NSLocalizedString und liefert natürlich nur dann eine Übersetzung, wenn der Text in MoneyMoney hinterlegt worden ist.

ParameterTypOptionalBeschreibung
strStringneinEnglischer Text
RückgabeTypBeschreibung
strStringÜbersetzter Text

MM.localizeDate

str = MM.localizeDate([format, ]date)

Lokalisiert eine Zeitangabe. Da die von Lua unterstützten POSIX Locales innerhalb von macOS-Apps nicht zur Verfügung stehen, baut diese Funktion auf der Cocoa-Klasse NSDateFormatter auf.

ParameterTypOptionalBeschreibung
formatStringjaAusgabeformat; Die Angabe erfolgt wie bei der Cocoa-Klasse NSDateFormatter nach dem Unicode Technical Standard #35.
dateNumberneinDatum; Die Angabe erfolgt in Form eines POSIX-Zeitstempels.
RückgabeTypBeschreibung
strStringDatum im lokalisierten Format

MM.localizeNumber

str = MM.localizeNumber([format, ]num)

Lokalisiert eine Zahl. Da die von Lua unterstützten POSIX Locales innerhalb von macOS-Apps nicht zur Verfügung stehen, baut diese Funktion auf der Cocoa-Klasse NSNumberFormatter auf.

ParameterTypOptionalBeschreibung
formatStringjaAusgabeformat; Die Angabe erfolgt wie bei der Cocoa-Klasse NSNumberFormatter nach dem Unicode Technical Standard #35.
numNumberneinZahl
RückgabeTypBeschreibung
strStringZahl im lokalisierten Format

MM.localizeAmount

str = MM.localizeAmount([format, ]amount[, currency])

Lokalisiert einen Währungsbetrag.

ParameterTypOptionalBeschreibung
formatStringjaAusgabeformat; Die Angabe erfolgt wie bei der Cocoa-Klasse NSNumberFormatter nach dem Unicode Technical Standard #35.
amountNumberneinBetrag
currencyStringjaWährung; Ohne diesen Parameter wird nur der Betrag ohne Währungsangabe zurückgegeben.
RückgabeTypBeschreibung
strStringWährungsbetrag im lokalisierten Format

Datum und Zeit

MM.time

timestamp = MM.time()

Gibt die aktuelle Uhrzeit zurück. Im Gegensatz zum Aufruf os.time() enthält der Rückgabewert auch Millisekunden als Nachkommastellen.

RückgabeTypBeschreibung
timestampNumberAktuelle Uhrzeit in Form eines POSIX-Zeitstempels.

MM.date

timestamp = MM.date()
timestamp = MM.date(timestamp, offset)
fields    = MM.date(timestamp, "*t")
timestamp = MM.date(fields)

Datumsberechnungen in vier Formen:

  1. Ohne Parameter: der aktuelle Zeitpunkt als ganzzahliger POSIX-Zeitstempel.
  2. Mit einem Offset-String: verschiebt den Zeitstempel um die angegebene Anzahl Tage ("D"), Wochen ("W"), Monate ("M"), Quartale ("Q") oder Jahre ("Y"), z. B. "-30D" oder "1M". Für timestamp kann nil übergeben werden, dann gilt der aktuelle Zeitpunkt.
  3. Mit "*t" als zweitem Parameter: zerlegt den Zeitstempel in eine Tabelle mit den Feldern timestamp, year, month, day (Number) und isBusinessDay (Boolean; berücksichtigt die Bankfeiertage des Landes des Bankzugangs).
  4. Mit einer Tabelle: setzt einen Zeitstempel aus Feldern zusammen. Unterstützte Felder: year, month, day (Standard: heutiges Datum), hour (Standard 12), min, sec (Standard 0) sowie from und to (Zeitzonen-Namen für die Umrechnung, z. B. "Europe/Berlin").
local monthAgo = MM.date(nil, "-1M")
local parts    = MM.date(MM.date(), "*t")
local noonCET  = MM.date{year=2026, month=9, day=3, from="Europe/Berlin"}

MM.timezone

name = MM.timezone()

Gibt den Namen der lokalen Zeitzone des Anwenders zurück.

RückgabeTypBeschreibung
nameStringZeitzonen-Name, z. B. "Europe/Berlin"; "GMT", falls keine Zeitzone ermittelt werden kann.

MM.gmtOffset

offset = MM.gmtOffset([timezone[, timestamp]])

Gibt die Abweichung einer Zeitzone von GMT in Sekunden zurück, unter Berücksichtigung der Sommerzeit zum angegebenen Zeitpunkt.

ParameterTypOptionalBeschreibung
timezoneStringjaZeitzonen-Name, z. B. "Europe/Berlin"; Standard ist die lokale Zeitzone.
timestampNumberjaZeitpunkt als POSIX-Zeitstempel; Standard ist der aktuelle Zeitpunkt.
RückgabeTypBeschreibung
offsetNumberAbweichung von GMT in Sekunden, z. B. 7200 für die mitteleuropäische Sommerzeit.

Zeichenketten und Kodierung

MM.urlencode

urlencoded = MM.urlencode(str[, charset])

Wendet eine URL-Kodierung an.

ParameterTypOptionalBeschreibung
strStringneinZu kodierender Text
charsetStringjaZeichensatz; Die Angabe erfolgt wie bei HTTP nach IANA. Ohne diesen Parameter wird ISO-8859-1 verwendet.
RückgabeTypBeschreibung
urlencodedStringURL-kodierter Text

Siehe auch: MM.urldecode

MM.urldecode

str = MM.urldecode(urlencoded)

Entfernt die URL-Kodierung.

ParameterTypOptionalBeschreibung
urlencodedStringneinURL-kodierter Text
RückgabeTypBeschreibung
strStringText ohne URL-Kodierung

Siehe auch: MM.urlencode

MM.toEncoding

data = MM.toEncoding(charset, str[, bom])

Konvertiert einen Text von UTF-8 zu einem anderen Zeichensatz.

ParameterTypOptionalBeschreibung
charsetStringneinZeichensatz; Die Angabe erfolgt wie bei HTTP nach IANA.
strStringneinText in UTF-8
bomBooleanjaWenn dieser Parameter mit true belegt ist, wird der Rückgabewert um eine Byte Order Mark (BOM) ergänzt, sofern sie für den angegebenen Zeichensatz existiert.
RückgabeTypBeschreibung
dataBinaryText im angegebenen Zeichensatz

Siehe auch: MM.fromEncoding

MM.fromEncoding

str = MM.fromEncoding(charset, data)

Konvertiert einen Text von einem anderen Zeichensatz zu UTF-8.

ParameterTypOptionalBeschreibung
charsetStringneinZeichensatz; Die Angabe erfolgt wie bei HTTP nach IANA.
dataBinaryneinText im angegebenen Zeichensatz
RückgabeTypBeschreibung
strStringText in UTF-8

Siehe auch: MM.toEncoding

MM.base64

encoded = MM.base64(data[, linebreaks])

Konvertiert Daten zu Base64.

ParameterTypOptionalBeschreibung
dataBinaryneinZu konvertierende Daten
linebreaksBooleanjaWenn dieser Parameter mit true belegt ist, wird die Ausgabe wie bei PEM alle 64 Zeichen umbrochen. Standard: keine Zeilenumbrüche.
RückgabeTypBeschreibung
encodedStringBase64-kodierte Daten

Siehe auch: MM.base64decode, MM.base64urlencode

MM.base64urlencode

encoded = MM.base64urlencode(data)

Konvertiert Daten in das URL-sichere Base64-Format (Base64URL nach RFC 4648, mit - und _ statt + und /, ohne =-Padding) — z. B. für JWTs und OAuth-Parameter.

ParameterTypOptionalBeschreibung
dataBinaryneinZu konvertierende Daten
RückgabeTypBeschreibung
encodedStringBase64URL-kodierte Daten

Siehe auch: MM.base64, MM.base64decode

MM.base64decode

data = MM.base64decode(encoded)

Konvertiert Daten von Base64. Auch Base64URL-kodierte Eingaben (-/_, fehlendes Padding) und Eingaben mit Zeilenumbrüchen werden akzeptiert.

ParameterTypOptionalBeschreibung
encodedStringneinBase64- oder Base64URL-kodierte Daten
RückgabeTypBeschreibung
dataBinaryKonvertierte Daten

Siehe auch: MM.base64, MM.base64urlencode

MM.binToHex

hex = MM.binToHex(data)

Konvertiert Binärdaten in einen Hexadezimal-String.

ParameterTypOptionalBeschreibung
dataBinaryneinZu konvertierende Daten
RückgabeTypBeschreibung
hexStringHexadezimal-String in Großbuchstaben, ohne Trennzeichen

Siehe auch: MM.hexToBin

MM.hexToBin

data = MM.hexToBin(hex)

Konvertiert einen Hexadezimal-String in Binärdaten.

ParameterTypOptionalBeschreibung
hexStringneinHexadezimal-String; Groß-/Kleinschreibung ist egal, :-Trennzeichen werden ignoriert.
RückgabeTypBeschreibung
dataBinaryKonvertierte Daten

Fehlerverhalten: nil bei ungültiger Eingabe.

Siehe auch: MM.binToHex

MM.utf8len

count = MM.utf8len(str)

Liefert die Länge eines UTF-8-Strings in Unicode-Zeichen — im Gegensatz zum Lua-Operator #, der die Anzahl der Bytes liefert. (Gezählt werden UTF-16-Einheiten; Zeichen außerhalb der Basic Multilingual Plane, z. B. Emoji, zählen doppelt.)

ParameterTypOptionalBeschreibung
strStringneinUTF-8-Text
RückgabeTypBeschreibung
countNumberAnzahl der Zeichen

MM.utf8sub

str = MM.utf8sub(str, start[, end])

Liefert einen Teilstring, wobei die Positionen wie bei MM.utf8len in Zeichen statt in Bytes zählen. Die Parameter verhalten sich wie bei der Lua-Funktion string.sub: Die Indexierung beginnt bei 1, negative Positionen zählen vom Ende, end ist standardmäßig -1 (Ende des Strings).

ParameterTypOptionalBeschreibung
strStringneinUTF-8-Text
startNumberneinErste Zeichenposition
endNumberjaLetzte Zeichenposition (Standard: -1)
RückgabeTypBeschreibung
strStringTeilstring

MM.utf8lower

str = MM.utf8lower(str)

Konvertiert einen UTF-8-String in Kleinbuchstaben — im Gegensatz zur Lua-Funktion string.lower Unicode-korrekt, also auch für Umlaute und andere Nicht-ASCII-Zeichen.

ParameterTypOptionalBeschreibung
strStringneinUTF-8-Text
RückgabeTypBeschreibung
strStringText in Kleinbuchstaben

Hashes und Message Authentication Codes

MM.sha512, MM.sha256, MM.sha1, MM.sha3_256, MM.md5

digest = MM.sha512(data)
digest = MM.sha256(data)
digest = MM.sha1(data)
digest = MM.sha3_256(data)
digest = MM.md5(data)

Berechnet einen SHA512-, SHA256-, SHA1-, SHA3-256- oder MD5-Hashwert.

ParameterTypOptionalBeschreibung
dataBinaryneinDaten, über die der Hashwert berechnet werden soll.
RückgabeTypBeschreibung
digestStringHashwert als hexadezimaler String in Großbuchstaben

MM.hmac512, MM.hmac384, MM.hmac256, MM.hmac1

digest = MM.hmac512(key, data)
digest = MM.hmac384(key, data)
digest = MM.hmac256(key, data)
digest = MM.hmac1(key, data)

Berechnet einen HMAC512-, HMAC384-, HMAC256- oder HMAC1-Message-Authentication-Code.

ParameterTypOptionalBeschreibung
keyBinaryneinHMAC-Schlüssel
dataBinaryneinDaten, über die der Message Authentication Code berechnet werden soll.
RückgabeTypBeschreibung
digestBinaryMessage Authentication Code als binärer String

Zufallswerte

MM.random

data = MM.random(length)

Generiert zufällige binäre Daten mit der angegebenen Länge.

ParameterTypOptionalBeschreibung
lengthNumberneinAnzahl der Bytes
RückgabeTypBeschreibung
dataBinaryZufällig generierte Daten

MM.uuid

uuid = MM.uuid()

Generiert eine zufällige UUID (Version 4).

RückgabeTypBeschreibung
uuidStringUUID in Kleinbuchstaben, z. B. "f81d4fae-7dec-41d0-a765-00a0c91e6bf6"

Umgebung

MM.productName, MM.productVersion, MM.productBuild

Diese Attribute enthalten Informationen zur Anwendung: productName (String) ist der Name der Anwendung, also "MoneyMoney", productVersion (String) die Versionsnummer, z. B. "2.4.38", und productBuild (Number) die fortlaufende Build-Nummer. Für Versionsvergleiche eignet sich productBuild, da es sich um eine Zahl handelt.

connection.useragent = "Mozilla/5.0 (compatible; " ..
  MM.productName ..
  "/" ..
  MM.productVersion ..
  ")"

MM.language

Dieses Attribut vom Typ String enthält das Sprachkürzel der MoneyMoney-Benutzeroberfläche, z. B. "de" oder "en" — etwa um Fehlermeldungen der Extension in der Sprache des Anwenders auszugeben.

MM.deviceUuid

Dieses Attribut vom Typ String enthält eine zufällig erzeugte, dauerhaft gespeicherte Gerätekennung (UUID) — z. B. um bei einer Geräteregistrierung gegenüber dem Bankserver stabil dasselbe Gerät zu identifizieren. Das Attribut kann nil sein, wenn noch keine Kennung erzeugt wurde.

MM.DEBUG, MM.BETA, MM.RETAIL, MM.APPSTORE

Genau eines dieser Attribute ist gesetzt (als leerer String) und kennzeichnet die Build-Variante der laufenden Anwendung; die übrigen sind nil. Damit lässt sich Verhalten auf einzelne Varianten beschränken:

local DEBUG = MM.DEBUG ~= nil
if DEBUG then print("Rohantwort: " .. content) end

MM-Funktionen: Kryptographie

RSA

MM.rsaGenerateKeys

key = MM.rsaGenerateKeys(bits)

Erzeugt ein neues RSA-Schlüsselpaar mit dem öffentlichen Exponenten 65537.

ParameterTypOptionalBeschreibung
bitsNumberneinSchlüssellänge in Bit (512 bis 4096)
RückgabeTypBeschreibung
keyTableSchlüssel-Tabelle mit den Feldern n, e, d, p, q, dmp1, dmq1, iqmp (alle Binary, Big-Endian)

Fehlerverhalten: nil bei ungültiger Schlüssellänge.

Siehe auch: MM.rsaSign, MM.rsaDecrypt, MM.pkcs8decode

MM.rsaSign

signature = MM.rsaSign(key, data, algorithm)

Signiert Daten mit einem privaten RSA-Schlüssel. Die Daten werden mit SHA-256 gehasht und der Hash nach RSASSA-PKCS1-v1_5 signiert.

ParameterTypOptionalBeschreibung
keyTableneinSchlüssel-Tabelle; benötigt werden n, e, d, p, q, optional die CRT-Felder dmp1, dmq1, iqmp.
dataBinaryneinZu signierende Daten
algorithmStringnein"pkcs1-v1_5 sha256"
RückgabeTypBeschreibung
signatureBinarySignatur; die Länge entspricht der Schlüssellänge.

Fehlerverhalten: nil bei unbekanntem Algorithmus oder unpassenden Schlüsselfeldern.

Siehe auch: MM.rsaVerify, MM.ecSign

MM.rsaVerify

valid = MM.rsaVerify(key, data, signature, algorithm)

Prüft, ob eine RSA-Signatur zu den Daten und dem öffentlichen Schlüssel passt — das Gegenstück zu MM.rsaSign.

ParameterTypOptionalBeschreibung
keyTableneinSchlüssel-Tabelle; benötigt werden nur n und e.
dataBinaryneinSignierte Daten
signatureBinaryneinZu prüfende Signatur
algorithmStringnein"pkcs1-v1_5 sha256"
RückgabeTypBeschreibung
validBooleantrue, wenn die Signatur gültig ist, sonst false.

Fehlerverhalten: false auch bei fehlerhaften Parametern.

Siehe auch: MM.rsaSign, MM.ecVerify

MM.rsaEncrypt

encrypted = MM.rsaEncrypt(key, data, algorithm)

Verschlüsselt Daten mit einem öffentlichen RSA-Schlüssel nach RSAES-OAEP.

ParameterTypOptionalBeschreibung
keyTableneinSchlüssel-Tabelle; benötigt werden nur n und e.
dataBinaryneinZu verschlüsselnde Daten
algorithmStringnein"pkcs1-oaep sha256" (OAEP mit SHA-256 für Hash und MGF1), "pkcs1-oaep sha512" (SHA-512 für Hash und MGF1) oder "pkcs1-oaep sha256 sha1" (SHA-256 für den Hash, SHA-1 für MGF1)
RückgabeTypBeschreibung
encryptedBinaryVerschlüsselte Daten; die Länge entspricht der Schlüssellänge.

Fehlerverhalten: nil bei unbekanntem Algorithmus oder unpassenden Schlüsselfeldern.

Siehe auch: MM.rsaDecrypt

MM.rsaDecrypt

data = MM.rsaDecrypt(key, encrypted, algorithm)

Entschlüsselt RSAES-OAEP-verschlüsselte Daten mit einem privaten RSA-Schlüssel.

ParameterTypOptionalBeschreibung
keyTableneinSchlüssel-Tabelle; benötigt werden n, e, d, p, q, optional die CRT-Felder dmp1, dmq1, iqmp.
encryptedBinaryneinVerschlüsselte Daten
algorithmStringnein"pkcs1-oaep sha256" oder "pkcs1-oaep sha512" (jeweils derselbe Hash für Label und MGF1)
RückgabeTypBeschreibung
dataBinaryEntschlüsselte Daten

Fehlerverhalten: nil bei unbekanntem Algorithmus, unpassenden Schlüsselfeldern oder fehlgeschlagener Entschlüsselung.

Siehe auch: MM.rsaEncrypt

MM.rsaPkcs1

encrypted = MM.rsaPkcs1(modulus, exponent, data)

Verschlüsselt Daten mit einem öffentlichen RSA-Schlüssel nach dem älteren RSAES-PKCS1-v1_5-Verfahren. Anders als die übrigen RSA-Funktionen nimmt diese Funktion Modulus und Exponent direkt entgegen statt einer Schlüssel-Tabelle.

ParameterTypOptionalBeschreibung
modulusBinaryneinModulus n des öffentlichen Schlüssels (Big-Endian)
exponentBinaryneinÖffentlicher Exponent e (Big-Endian)
dataBinaryneinZu verschlüsselnde Daten
RückgabeTypBeschreibung
encryptedBinaryVerschlüsselte Daten; die Länge entspricht der Schlüssellänge.

Fehlerverhalten: nil bei ungültigen Parametern oder zu langen Daten.

Siehe auch: MM.rsaEncrypt

Elliptische Kurven

MM.ecGenerateKeys

key = MM.ecGenerateKeys(curve)

Erzeugt ein neues Schlüsselpaar für elliptische-Kurven-Kryptographie. Typischer Einsatz: einmalige Erzeugung eines Geräteschlüssels bei der Kontoeinrichtung, der in LocalStorage abgelegt und bei späteren Anmeldungen zum Signieren verwendet wird.

ParameterTypOptionalBeschreibung
curveStringneinName der elliptischen Kurve, z. B. "prime256v1". Der Wert "ed25519" (Groß-/Kleinschreibung egal) erzeugt ein Ed25519-Schlüsselpaar.
RückgabeTypBeschreibung
keyTableSchlüssel-Tabelle, siehe unten.

Für ECDSA-Kurven enthält die Schlüssel-Tabelle die Felder curve (String), x und y (Binary, Koordinaten des öffentlichen Punkts) sowie d (Binary, privater Skalar). Für "ed25519" enthält sie curve, x (Binary, 32 Byte, öffentlicher Schlüssel) und d (Binary, 32 Byte, privater Schlüssel).

Fehlerverhalten: nil bei unbekannter Kurve.

Siehe auch: MM.ecSign, MM.ecVerify, MM.pkcs8decode

MM.ecSign

signature = MM.ecSign(key, data, algorithm)

Signiert Daten mit einem privaten elliptische-Kurven-Schlüssel — etwa zum Signieren von API-Requests oder JWTs (mit "eddsa" auch JWTs mit dem Algorithmus EdDSA nach RFC 8037).

ParameterTypOptionalBeschreibung
keyTableneinSchlüssel-Tabelle, siehe MM.ecGenerateKeys
dataBinaryneinZu signierende Daten
algorithmStringnein"ecdsa sha256", "ecdsa sha512" oder "eddsa"
RückgabeTypBeschreibung
signatureBinarySignatur; bei ECDSA DER-codiert, bei EdDSA die rohe 64-Byte-Signatur.

Bei "ecdsa sha256"/"ecdsa sha512" werden die Daten gehasht und der Hash signiert; benötigt werden die Schlüsselfelder curve, x, y und d. Bei "eddsa" (PureEdDSA nach RFC 8032) werden die Daten direkt signiert, ohne vorgelagerten Hash; benötigt werden nur curve (= "ed25519") und d.

Fehlerverhalten: nil bei unbekanntem Algorithmus, unbekannter Kurve oder unpassenden Schlüsselfeldern.

Siehe auch: MM.ecVerify, MM.ecGenerateKeys

MM.ecVerify

valid = MM.ecVerify(key, data, signature, algorithm)

Prüft, ob eine Signatur zu den Daten und dem öffentlichen Schlüssel passt — das Gegenstück zu MM.ecSign.

ParameterTypOptionalBeschreibung
keyTableneinSchlüssel-Tabelle; nur die öffentlichen Felder werden benötigt (bei ECDSA curve, x, y; bei EdDSA curve, x). Ein enthaltener privater Schlüssel d wird ignoriert.
dataBinaryneinSignierte Daten
signatureBinaryneinZu prüfende Signatur (DER bei ECDSA, 64 Byte roh bei EdDSA)
algorithmStringnein"ecdsa sha256", "ecdsa sha512" oder "eddsa"
RückgabeTypBeschreibung
validBooleantrue, wenn die Signatur gültig ist, sonst false.

Fehlerverhalten: false auch bei fehlerhaften Parametern.

Siehe auch: MM.ecSign, MM.rsaVerify

Symmetrische Verschlüsselung

MM.aes256encrypt

encrypted      = MM.aes256encrypt(key, iv, data)
encrypted, tag = MM.aes256encrypt(key, iv, data, "aes256 gcm", aad)

Verschlüsselt Daten mit AES-256.

ParameterTypOptionalBeschreibung
keyBinaryneinSchlüssel, 32 Byte
ivBinaryneinInitialisierungsvektor; 16 Byte bei CBC, 12 Byte bei GCM
dataBinaryneinZu verschlüsselnde Daten
algorithmStringja"aes256 cbc" (Standard) oder "aes256 gcm"
aadBinarybei GCM neinZusätzliche authentifizierte Daten (Additional Authenticated Data); bei GCM erforderlich, darf leer sein.
RückgabeTypBeschreibung
encryptedBinaryVerschlüsselte Daten; bei CBC mit PKCS#7-Padding.
tagBinaryNur bei GCM: der 16-Byte-Authentication-Tag als zweiter Rückgabewert.

Fehlerverhalten: nil bei unbekanntem Algorithmus oder falschen Schlüssel-/IV-Längen.

Siehe auch: MM.aes256decrypt

MM.aes256decrypt

data = MM.aes256decrypt(key, iv, encrypted)
data = MM.aes256decrypt(key, iv, encrypted, "aes256 gcm", aad, tag)

Entschlüsselt AES-256-verschlüsselte Daten.

ParameterTypOptionalBeschreibung
keyBinaryneinSchlüssel, 32 Byte
ivBinaryneinInitialisierungsvektor; 16 Byte bei CBC, 12 Byte bei GCM
encryptedBinaryneinVerschlüsselte Daten
algorithmStringja"aes256 cbc" (Standard) oder "aes256 gcm"
aadBinarybei GCM neinZusätzliche authentifizierte Daten, wie bei der Verschlüsselung übergeben
tagBinarybei GCM neinDer 16-Byte-Authentication-Tag aus der Verschlüsselung
RückgabeTypBeschreibung
dataBinaryEntschlüsselte Daten (bei CBC ohne Padding)

Fehlerverhalten: nil bei falschen Parametern, ungültigem Padding oder — bei GCM — fehlgeschlagener Authentifizierung.

Siehe auch: MM.aes256encrypt

Schlüsselformate

MM.pkcs8decode

key = MM.pkcs8decode(data)

Liest einen Schlüssel aus dem Standard-Auslieferungsformat ein, in dem Dienste API-Schlüssel bereitstellen, und wandelt ihn in die Schlüssel-Tabelle um, die die Sign- und Verify-Funktionen erwarten. Der Schlüsseltyp (RSA, EC, Ed25519) und die Frage privat/öffentlich werden automatisch erkannt — der vom Anwender eingefügte Schlüsselblock kann also unverändert durchgereicht werden.

ParameterTypOptionalBeschreibung
dataStringneinSchlüssel im PKCS#8- bzw. SubjectPublicKeyInfo-Format: PEM (-----BEGIN PRIVATE KEY----- / -----BEGIN PUBLIC KEY-----, auch traditionelle PEM-Formate) oder binäres DER; privat oder öffentlich.
RückgabeTypBeschreibung
keyTableSchlüssel-Tabelle mit dem Feld type ("rsa", "ec" oder "ed25519") und den typabhängigen Feldern, siehe unten.

Typabhängige Felder der Schlüssel-Tabelle (alle Binary; die privaten Felder nur bei privaten Schlüsseln):

typeÖffentliche FelderPrivate FelderPassend für
"rsa"n, ed, p, q, dmp1, dmq1, iqmpMM.rsaSign, MM.rsaVerify, MM.rsaEncrypt
"ec"curve, x, ydMM.ecSign, MM.ecVerify
"ed25519"curve (= "ed25519"), xdMM.ecSign/MM.ecVerify mit "eddsa"

Alle Zahlen-/Schlüsselfelder sind Binärstrings (Big-Endian bei RSA/EC, Rohformat bei Ed25519). Fehlt in einer EC-Schlüsseldatei der öffentliche Punkt, wird er aus dem privaten Skalar abgeleitet.

Fehlerverhalten: nil, wenn der Schlüssel nicht gelesen werden konnte.

local key = MM.pkcs8decode(apiKeyPem)
if key == nil then
  return "Der API-Schlüssel konnte nicht gelesen werden."
end
local signature = MM.ecSign(key, message, "eddsa")

Siehe auch: MM.ecSign, MM.rsaSign

MM.rsaPkcs8

pem = MM.rsaPkcs8(key)

Erzeugt aus einem RSA-Schlüssel den PEM-Block des öffentlichen Schlüssels (SubjectPublicKeyInfo, -----BEGIN PUBLIC KEY-----) — z. B. um den öffentlichen Schlüssel bei einer Geräteregistrierung an einen Server zu übertragen.

ParameterTypOptionalBeschreibung
keyTableneinSchlüssel-Tabelle; benötigt werden nur n und e.
RückgabeTypBeschreibung
pemStringÖffentlicher Schlüssel als PEM-Block

Fehlerverhalten: nil bei unpassenden Schlüsselfeldern.

Siehe auch: MM.rsaGenerateKeys, MM.pkcs8decode

MM.rsaPkcs8decode

key = MM.rsaPkcs8decode(pem)

Liest einen öffentlichen RSA-Schlüssel aus einem PEM-Block (-----BEGIN PUBLIC KEY-----) und liefert die Felder n und e. Für neue Extensions wird das universellere MM.pkcs8decode empfohlen, das zusätzlich private Schlüssel, DER-Eingaben sowie EC- und Ed25519-Schlüssel versteht.

ParameterTypOptionalBeschreibung
pemStringneinÖffentlicher RSA-Schlüssel als PEM-Block
RückgabeTypBeschreibung
keyTableSchlüssel-Tabelle mit den Feldern n und e (Binary)

Fehlerverhalten: nil, wenn der Schlüssel nicht gelesen werden konnte.

Siehe auch: MM.pkcs8decode, MM.rsaPkcs8