git - Server-Hostschlüssel nicht zwischengespeichert


101

Ich versuche, Änderungen von meinem lokalen Repo auf ein Remote-Repo zu übertragen. Wenn ich tippe:

git push origin

Ich erhalte folgende Fehlermeldung:

The server's host key is not cached in the registry. You
have no guarantee that the server is the computer you
think it is.
The server's rsa2 key fingerprint is:
ssh-rsa 2048 xx:xx:xx:xx:xx:xx:xx:xx:xx:xx:xx:xx:xx:xx:xx:xx
Connection abandoned.
fatal: The remote end hung up unexpectedly

Wie kann ich das lösen? Ich verwende Git über die Befehlszeile in Windows 7.

Bearbeiten

Wenn ich versuche, ein einfaches ssh zu machen

ssh user@hostname

Ich erhalte folgende Fehlermeldung:

Could not create directory '/c//%HOMEDRIVE%%HOMEPATH%/.ssh'.
percent_expand: unknown key %H

Irgendwie wird das Verzeichnis nicht erstellt, da der Pfad ungültig ist. Wie kann ich das beheben?

@eckes: Edit2

Mein Zuhause ist auf %HOMEDRIVE%%HOMEPATH%richtig eingestellt?


2
Scheint $HOMEnicht richtig eingerichtet zu sein. Versuchen Sie, die HOMEUmgebungsvariable unter Windows mit My Computer-> Rechtsklick -> Properties-> Tab Advanced-> ButtonEnvironment Variables
Ecks

1
Ich bin kein Windows-Typ, aber es kommt mir seltsam vor, dass Sie nach /c//(vermutlich einem Laufwerksbuchstaben) immer noch %HOMEDRIVE%... Sie könnten sich Zeit sparen, indem Sie selbst an dem Wert herumspielen und ihn wiederholen?
Cascabel

1
Erweitern Sie HOMEDRIVEund HOMEPATHund setzen Sie HOMEauf den resultierenden Wert ...
eckes

Antworten:


54

Die Nachricht bedeutet, dass der Hostschlüssel von originnicht in Ihrer vertrauenswürdigen Hosts-Datei vorhanden ist.

Um dies zu originumgehen , öffnen Sie eine einfache SSH-Verbindung zu und SSH fragt Sie, ob Sie dem Remote-Host (über die Git-Konsole) vertrauen möchten:

$ ssh 127.0.0.1
The authenticity of host '127.0.0.1 (127.0.0.1)' can't be established.
RSA key fingerprint is <FINGERPRINT>.
Are you sure you want to continue connecting (yes/no)?

Wenn Sie dem Remote-Host (dh dem Typ yes) vertrauen , fügt SSH seinen Schlüssel der Liste der bekannten Hosts hinzu.

Danach sollten Sie in der Lage sein, Ihre git push origin.

Als Alternative können Sie auch manuell den Schlüssel der originzu , .ssh/known_hostsaber dies erfordert , dass Sie das Format der haften known_hostsDatei wie in der Manpage von beschrieben sshd(Abschnitt authorized_keys FORMAT ).


4
Ich habe die gleiche Nachricht erhalten, als ich einen Push an Github ausgeführt habe, aber ich kann ssh an Github senden und habe github.com in meiner known_hostsDatei.
Magnus Lindhe

1
Schauen Sie, um unten in diesem Fall zu antworten
Nikita Koksharov

3
Sie können PuTTY unter Windows für dieselben Zwecke anstelle eines Befehlszeilen-SSH-Clients verwenden.
Brianmearns

1
Stellen Sie sicher, dass die Hostnamen genau gleich sind. Wenn Sie beispielsweise git lokal installiert haben und den Namen 'home.mydomain.com' als Remote verwenden, den Schlüssel jedoch mit putty speichern, um eine Verbindung zu 'localhost' herzustellen, funktioniert dies nicht. Sie müssen eine Verbindung zu genau dem Hostnamen in Ihrer Remote-URL herstellen.
Jason Goemaat

Für mich wurde der Versuch behoben, mit Putty eine Verbindung zum Server herzustellen. Nehmen wir an, die Git-URL lautet ssh: //git@example.ex.com: 222 / etwas / shop.git, also habe ich das Feld putty Hostname example.ex.com und Port 222 eingegeben. Dann ist die Verbindung fehlgeschlagen, aber ich denke, es wurde ein Finger hinzugefügt Drucken Sie dort, wo es benötigt wird. Ich verstehe nur nicht, wo es hinzugefügt wurde, weil in meinem Home-Verzeichnis bekannte_Hosts - Datei nicht betroffen war, als ich alten Schlüssel gelöscht hatte
Darius.V

157

Für diejenigen unter Ihnen, die MSYS Git unter Windows mit PuTTY über die Standard-Eingabeaufforderung einrichten, besteht die Möglichkeit, einen Host zum PuTTY-Cache hinzuzufügen

> plink.exe <host>

Beispielsweise:

> plink.exe codebasehq.com

The server's host key is not cached in the registry. You
have no guarantee that the server is the computer you
think it is.
The server's rsa2 key fingerprint is:
ssh-rsa 2048 2e:db:b6:22:f7:bd:48:f6:da:72:bf:59:d7:75:d7:4e
If you trust this host, enter "y" to add the key to
PuTTY's cache and carry on connecting.
If you want to carry on connecting just once, without
adding the key to the cache, enter "n".
If you do not trust this host, press Return to abandon the
connection.
Store key in cache? (y/n)

Antworte einfach yund dann Strg + C den Rest.

Überprüfen Sie jedoch den Fingerabdruck. Diese Warnung gibt es aus gutem Grund. Fingerabdrücke für einige Git-Dienste (bitte bearbeiten, um weitere hinzuzufügen):


15
Dies sollte die akzeptierte Antwort sein. Genau darauf bezieht sich die Fehlermeldung. In meinem Fall hatte ich beim Klonen einen vollqualifizierten Domänennamen verwendet, aber auf meinem neuen Computer hatte ich mich nur mit dem kurzen lokalen Domänennamen angemeldet. Ich musste mich über Putty oder Plink als FQDN anmelden, um den Schlüssel für den Hostnamen auf dem Ursprung zwischenzuspeichern. Es kann hilfreich sein, den Hostnamen, der als Remote verwendet wird, mit "git remote -v" zu überprüfen.
Peabody

3
Es funktioniert auch, interaktives PuTTY für den Host zu verwenden, den Sie verwenden möchten. Wenn Sie beispielsweise versuchen, ein Github-Repository zum ersten Mal auf einem neuen Windows-Computer zu klonen, öffnen Sie mit PuTTY eine Sitzung für den Host 'github.com', akzeptieren Sie die Aufforderung zur Serververtrauensstellung und klonen Sie dann auf Kommandozeile sollte funktionieren.
Jeremy McGee

1
Sie können feststellen, dass MSYS git versucht zu verwenden, plinkindem Sie es ausführen $ set | grep GIT_SSHund nachGIT_SSH='C:\Program Files (x86)\PuTTY\plink.exe'
shuckc

2
Am Ende habe ich das Problem gelöst, indem ich meinen Schlüssel zu Pageant hinzugefügt und mit Putty direkt auf den Host zugegriffen habe. Hiermit werden Sie aufgefordert, den Host zum Cache hinzuzufügen. Das Gleiche tun.
Knossos

1
Wenn Ihr Git-Repository auf einem benutzerdefinierten SSH-Port bereitgestellt wird -P, wählen Sie den Port aus, z plink.exe example.com -P 2222. Ich konnte von Github klonen, aber nicht von meinem persönlichen Server, und das verwirrte mich bis zum Äußersten.
Hay

79

Versuchen Sie, an der Git Bash-Eingabeaufforderung ein "set | grep -i ssh" auszuführen

Wenn Ihr Setup meinem entspricht, haben Sie wahrscheinlich folgende Einstellungen:

GIT_SSH='C:\Program Files (x86)\PuTTY\plink.exe'
PLINK_PROTOCOL=ssh
SVN_SSH='"C:\\Program Files (x86)\\PuTTY\\plink.exe"'

Ich habe ein

unset GIT_SSH
unset PLINK_PROTOCOL
unset GIT_SVN

und es hat danach funktioniert. Ich denke, Putty speichert seine Schlüssel woanders als $ HOME / .ssh oder so ... (Ich hatte auch ein Problem mit einer Box, in der $ HOME auf "C: \ Users \" gesetzt war usrnam "anstelle von" / C / Users / usrnam / "

Trotzdem kann Ihr Kilometerstand variieren, aber das hat es für mich behoben. :-)

(Wahrscheinlich reicht es aus, nur das nicht gesetzte GIT_SSH zu machen, aber ich war auf einer Rolle)

Hinweis: Wenn unset nicht für Sie funktioniert, versuchen Sie Folgendes:

set GIT_SSH=

1
"unset GIT_SSH" hat bei mir funktioniert. Ich hatte Pageant / Putty zuvor für einen anderen Server eingerichtet, aber als ich mithilfe der Git Bash-Eingabeaufforderung neue Schlüssel erstellte, musste ich zurückgehen. Danke für die Hilfe.
Supermitch

Nachdem ich Ihre Schritte unternommen habe, bin ich weiter gekommen, aber jetzt erhalte ich den Fehler "Mac bei Eingabe beschädigt" ... jemals gesehen?
CD Smith

2
Bei der Installation von git können Sie diese Variablen NICHT festlegen. Es ist sogar die Standardvariante. Obwohl ich mich auch für die Plink-Integration entschieden habe, bin ich deshalb hier.) Danke.
Antony Hatchkins

1
Das hat auch bei Win7 funktioniert. Anscheinend hat das Setup von git bash mit plink das Problem in meinem Fall verursacht.
nhylated

2
unset GIT_SSHhat auch für mich funktioniert, obwohl ich es jedes Mal tun muss, wenn ich Git Bash starte, was ziemlich langweilig ist. Irgendeine Idee, wie man das automatisiert?
Loïc

19

Ich vermute, dass Ihre GIT_SSHUmgebungsvariable auf gesetzt ist %ProgramFiles(x86)%\putty\plink.exe. Aus irgendeinem Grund verwendet PLink die .ssh/known_hostsDatei in Ihrem Benutzerverzeichnis nicht zum Speichern der Remote-Hosts-Schlüssel.

Wenn dies tatsächlich der Fall ist und dies möglicherweise absichtlich der Fall ist, wenn Sie einen Festzug verwenden möchten, müssen Sie zuerst PLink verwenden, um eine Verbindung zum Host herzustellen.

"$GIT_SSH" user@hostname

Sie sollten eine ähnliche Nachricht erhalten

The server's host key is not cached in the registry. You
have no guarantee that the server is the computer you
think it is.
The server's rsa2 key fingerprint is:
ssh-rsa 2048 86:7b:1b:12:85:35:8a:b7:98:b6:d2:97:5e:96:58:1d
If you trust this host, enter "y" to add the key to
PuTTY's cache and carry on connecting.
If you want to carry on connecting just once, without
adding the key to the cache, enter "n".
If you do not trust this host, press Return to abandon the
connection.
Store key in cache? (y/n)

Sobald Sie ydie Frage beantwortet und erfolgreich eine Verbindung zum Remote-Host hergestellt haben, sollten Sie fertig sein. Fahren Sie fort und versuchen Sie es erneut.


Dies war es für mich mit Git Bash unter Windows mit PLink / Pageant. Vielen Dank!
Amsross

1
Mit einem Stash-Repository (jetzt Bitbucket) musste ich"$GIT_SSH" -P 7999 git@stash.domain.local
Julien

4

Nur auf den Host zuzugreifen, reicht zumindest unter Windows nicht aus. Das fügt den Host-Schlüssel hinzu, ssh/known_hostsaber der Fehler bleibt bestehen.

Sie müssen das Git-Bash-Fenster schließen und ein neues öffnen. Dann wird der Registrierungscache geleert und das Push / Pull funktioniert dann.


ssh/known_hostsist relativ zu was?,% USERPROFILE% Ich habe dieses Problem unter Win 7 und keine Lösung ...
Frank Nocke

2

Rene, deine HOMEVariable ist nicht richtig eingestellt. Entweder ändern Sie es zu c:\Users\(your-username)oder nur zu %USERNAME%.


2

Lösung mit Plink

Speichern Sie dieses Python-Skript unter known_hosts.py:

#! /usr/bin/env python

# $Id$
# Convert OpenSSH known_hosts and known_hosts2 files to "new format" PuTTY
# host keys.
#   usage:
#     kh2reg.py [ --win ] known_hosts1 2 3 4 ... > hosts.reg
#       Creates a Windows .REG file (double-click to install).
#     kh2reg.py --unix    known_hosts1 2 3 4 ... > sshhostkeys
#       Creates data suitable for storing in ~/.putty/sshhostkeys (Unix).
# Line endings are someone else's problem as is traditional.
# Developed for Python 1.5.2.

import fileinput
import base64
import struct
import string
import re
import sys
import getopt

def winmungestr(s):
    "Duplicate of PuTTY's mungestr() in winstore.c:1.10 for Registry keys"
    candot = 0
    r = ""
    for c in s:
        if c in ' \*?%~' or ord(c)<ord(' ') or (c == '.' and not candot):
            r = r + ("%%%02X" % ord(c))
        else:
            r = r + c
        candot = 1
    return r

def strtolong(s):
    "Convert arbitrary-length big-endian binary data to a Python long"
    bytes = struct.unpack(">%luB" % len(s), s)
    return reduce ((lambda a, b: (long(a) << 8) + long(b)), bytes)

def longtohex(n):
    """Convert long int to lower-case hex.

    Ick, Python (at least in 1.5.2) doesn't appear to have a way to
    turn a long int into an unadorned hex string -- % gets upset if the
    number is too big, and raw hex() uses uppercase (sometimes), and
    adds unwanted "0x...L" around it."""

    plain=string.lower(re.match(r"0x([0-9A-Fa-f]*)l?$", hex(n), re.I).group(1))
    return "0x" + plain

output_type = 'windows'

try:
    optlist, args = getopt.getopt(sys.argv[1:], '', [ 'win', 'unix' ])
    if filter(lambda x: x[0] == '--unix', optlist):
        output_type = 'unix'
except getopt.error, e:
    sys.stderr.write(str(e) + "\n")
    sys.exit(1)

if output_type == 'windows':
    # Output REG file header.
    sys.stdout.write("""REGEDIT4

[HKEY_CURRENT_USER\Software\SimonTatham\PuTTY\SshHostKeys]
""")

# Now process all known_hosts input.
for line in fileinput.input(args):

    try:
        # Remove leading/trailing whitespace (should zap CR and LF)
        line = string.strip (line)

        # Skip blanks and comments
        if line == '' or line[0] == '#':
            raise "Skipping input line"

        # Split line on spaces.
        fields = string.split (line, ' ')

        # Common fields
        hostpat = fields[0]
        magicnumbers = []   # placeholder
        keytype = ""        # placeholder

        # Grotty heuristic to distinguish known_hosts from known_hosts2:
        # is second field entirely decimal digits?
        if re.match (r"\d*$", fields[1]):

            # Treat as SSH-1-type host key.
            # Format: hostpat bits10 exp10 mod10 comment...
            # (PuTTY doesn't store the number of bits.)
            magicnumbers = map (long, fields[2:4])
            keytype = "rsa"

        else:

            # Treat as SSH-2-type host key.
            # Format: hostpat keytype keyblob64 comment...
            sshkeytype, blob = fields[1], base64.decodestring (fields[2])

            # 'blob' consists of a number of
            #   uint32    N (big-endian)
            #   uint8[N]  field_data
            subfields = []
            while blob:
                sizefmt = ">L"
                (size,) = struct.unpack (sizefmt, blob[0:4])
                size = int(size)   # req'd for slicage
                (data,) = struct.unpack (">%lus" % size, blob[4:size+4])
                subfields.append(data)
                blob = blob [struct.calcsize(sizefmt) + size : ]

            # The first field is keytype again, and the rest we can treat as
            # an opaque list of bignums (same numbers and order as stored
            # by PuTTY). (currently embedded keytype is ignored entirely)
            magicnumbers = map (strtolong, subfields[1:])

            # Translate key type into something PuTTY can use.
            if   sshkeytype == "ssh-rsa":   keytype = "rsa2"
            elif sshkeytype == "ssh-dss":   keytype = "dss"
            else:
                raise "Unknown SSH key type", sshkeytype

        # Now print out one line per host pattern, discarding wildcards.
        for host in string.split (hostpat, ','):
            if re.search (r"[*?!]", host):
                sys.stderr.write("Skipping wildcard host pattern '%s'\n"
                                 % host)
                continue
            elif re.match (r"\|", host):
                sys.stderr.write("Skipping hashed hostname '%s'\n" % host)
                continue
            else:
                m = re.match (r"\[([^]]*)\]:(\d*)$", host)
                if m:
                    (host, port) = m.group(1,2)
                    port = int(port)
                else:
                    port = 22
                # Slightly bizarre output key format: 'type@port:hostname'
                # XXX: does PuTTY do anything useful with literal IP[v4]s?
                key = keytype + ("@%d:%s" % (port, host))
                value = string.join (map (longtohex, magicnumbers), ',')
                if output_type == 'unix':
                    # Unix format.
                    sys.stdout.write('%s %s\n' % (key, value))
                else:
                    # Windows format.
                    # XXX: worry about double quotes?
                    sys.stdout.write("\"%s\"=\"%s\"\n"
                                     % (winmungestr(key), value))

    except "Unknown SSH key type", k:
        sys.stderr.write("Unknown SSH key type '%s', skipping\n" % k)
    except "Skipping input line":
        pass

Getestet unter Win7x64 und Python 2.7 .

Dann renne:

ssh-keyscan -t rsa bitbucket.org >>~/.ssh/known_hosts
python --win known_hosts.py >known_hosts.reg
start known_hosts.reg

Und wählen Sie den Import in die Registrierung. Der Keyscan ruft den öffentlichen Schlüssel für die Domain ab (ich hatte Probleme mit Bitbucket), und das Python-Skript konvertiert ihn dann in das Plink-Format.


2

Hatte das gleiche Problem und vergiss, eine Verbindung zu SSH an dem Port herzustellen , an dem sich das eigentliche Repository befindet , nicht nur der allgemeine SSH-Port, dann ist der Hostschlüssel anders!


Verwenden Sie auch genau die gleiche Methode zur Angabe des Hosts, z. B. nicht gitserver.example.com für ssh und gitserver für git.
Matthijs P

2

Öffnen Sie einfach Putty und versuchen Sie, eine Verbindung zu dem Remote-Server herzustellen, auf den Sie Ihren Code übertragen möchten. Wenn der Dialog angezeigt wird, drücken Sie Ja (Sie vertrauen Remote), dann ist alles in Ordnung.


2

Arbeitsumfeld:

  • Windows 10
  • git
  • Kitt

Erstens: Löschen Sie Putty bekannte_Hosts in der Registrierung gemäß dem Regedit.
Dann: Das Ausführen des Befehls %GIT_SSH% user@hostnamein Window's cmd löst das Problem.

Hoffe es hilft euch allen.


1

Ich hatte auch das gleiche Problem, als ich versuchte, ein Repository auf meinem Windows 7-Computer zu klonen. Ich habe die meisten der hier genannten Antworten ausprobiert. Keiner von ihnen hat für mich gearbeitet.

Was für mich funktionierte, war das Ausführen des Programms Pageant (Putty Authentication Agent). Sobald der Festzug im Hintergrund lief, konnte ich klonen, schieben und vom / zum Repository ziehen. Dies hat bei mir möglicherweise funktioniert, weil ich meinen öffentlichen Schlüssel so eingerichtet habe, dass bei jeder erstmaligen Verwendung ein Kennwort erforderlich ist und der Festzug gestartet wird.


Sie erhalten eine andere Fehlermeldung, wenn es sich um ein Festzugsproblem handelt. Nicht Connection abandoned, aber so etwas wieAccess denied (private key)
Andrey Regentov

1

Der Wechsel von PuTTY zu OpenSSH hat dieses Problem für mich behoben, ohne dass GIT_SSH usw. deaktiviert werden musste.


Wenn Sie die Nachricht über den nicht erkannten Hostschlüssel erhalten, während Sie Git-Push / Pull-Operationen mit ATLASSIAN SOURCETREE ausführen, können Sie nicht mit j / n antworten, und die Push / Pull-Operation wird abgebrochen, ohne die Taste zwischenzuspeichern. Wenn Sie jedoch zu SourceTree Tools-> Optionen (Registerkarte Allgemein) gehen und den SSH-Client unter (unter SSH-Client-Konfiguration) von PuTTY in OpenSSH ändern, kann der Schlüssel zwischengespeichert werden, ohne dass etwas anderes geändert wird.
Rod Dewell

1

Ich löste ähnliches Problem dies mit Abhilfe .

Sie müssen nur zu Embedded Git wechseln, drücken, die Ja-Taste drücken und dann wieder zu System Git wechseln.

Sie finden diese Option in

Tools -> Options -> Git

1
Jetzt auf v2.5.5.0 Ort:C:\Users\{UserName}\AppData\Local\SourceTree\app-2.5.5\tools\putty> .\plink.exe {YourNewHost}
John_J

1

Wie von Roman Starkov beantwortet , plinkmuss der Host zu seinem Cache hinzugefügt werden.

Für Benutzer von Git Extensions :

  1. Öffnen Sie Git Extensions
  2. Gehen Sie zu Extras -> Einstellungen -> SSH
  3. Kopieren Sie den Pfad nach "plink.exe" (bei Verwendung von PuTTY) / "klink.exe" (bei Verwendung von KiTTY).
  4. Führen Sie in einer Konsole den folgenden Befehl aus:

(durch die tatsächlichen Pfade ersetzen)

<the path to plink/klink.exe> <address to the server>

z.B

%ProgramData%\chocolatey\lib\kitty\tools\klink.exe codebasehq.com

Hinweis : Stellen Sie sicher, dass Sie denselben Plink / Klink verwenden, den Git Extensions verwendet!


0

Das direkte Hinzufügen des Hosts mit Bash hat das Problem nicht behoben. Der Fehler trat dennoch auf, wenn in Git Extensions 'Alle abrufen' verwendet wurde. Durch die Verwendung von 'Pull' für einen Zweig wurde der erforderliche Host automatisch von Git Extensions mit einem Bash-Popup-Bildschirm hinzugefügt. Danach konnte ich 'Fetch All' wieder verwenden. Ich bin mir nicht sicher, was Git Extensions anders macht.


0

Ich habe alle oben genannten Methoden ausprobiert, aber keine davon konnte das gleiche Problem auf meinem Laptop beheben. Anstatt den Zweig in git bash auf den Ursprung zu verschieben, verwende ich die Push-Option von TortoiseGit, um das Pushing durchzuführen. Anschließend wird ein Fenster angezeigt, in dem ich aufgefordert werde, den neuen Hostschlüssel zum Cache hinzuzufügen. Nachdem ich auf die Schaltfläche "Ja" geklickt habe, ist alles möglich gut jetzt.

Hoffe es hilft euch allen.


0

Ich habe eine Festplatte gewechselt und Windows installiert. Beim Versuch, Dateien hochzuladen, wurde dieses Befehlsfenster empfangen.

Ich drückte "y", dann Strg + C. Geöffnet putty.exe, fügte einen alten Schlüssel hinzu, kehrte zu git zurück und schob Dateien.


0

Deinstallieren Sie einfach Git Extensions und installieren Sie es erneut, indem Sie stattdessen OpenSSH wählen


0

In Windows 7 oder 10 hat der Trick, der bei mir funktioniert hat, das Löschen der Systemvariablen GIT_SSH. Es wurde zuvor für die Verwendung von Plink festgelegt und jetzt durch Putty ersetzt. Dies verursachte einen Plink.exe-Fehler

Es gab auch eine alte Installation von Git (32-Bit-Version) und ein Update auf Git (z. B. Git-2.20.1-64-bit.exe), da der PC ein 64-Bit-Betriebssystem war.

Auf jeden Fall wurde der Putty / Plink nicht einmal von Git verwendet, da in der Git-Installation standardmäßig Open SSH verwendet wurde.


0

Wenn Sie die Nachricht über den nicht erkannten Hostschlüssel erhalten, während Sie Git-Push / Pull-Operationen mit ATLASSIAN SOURCETREE ausführen, können Sie nicht mit j / n antworten, und die Push / Pull-Operation wird abgebrochen, ohne die Taste zwischenzuspeichern. Wenn Sie jedoch zu SourceTree Tools-> Optionen (Registerkarte Allgemein) gehen und den SSH-Client unter (unter SSH-Client-Konfiguration) von PuTTY in OpenSSH ändern, kann der Schlüssel zwischengespeichert werden, ohne dass etwas anderes geändert wird.

Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.