Compare commits
	
		
			94 Commits
		
	
	
		
			1.04
			...
			1.05d-none
		
	
	| Author | SHA1 | Date | |
|---|---|---|---|
| 
						 | 
					832d3b3a95 | ||
| 
						 | 
					37867634cd | ||
| 
						 | 
					b1b7bff09d | ||
| 
						 | 
					dfed92ac61 | ||
| 
						 | 
					0d6c9b468e | ||
| 
						 | 
					2bc12c510b | ||
| 
						 | 
					f3022a19c2 | ||
| 
						 | 
					800afae1c9 | ||
| 
						 | 
					3c19f8e76f | ||
| 
						 | 
					3ca462f46f | ||
| 
						 | 
					fadd21ebd0 | ||
| 
						 | 
					a10c474ce5 | ||
| 
						 | 
					513ea5a198 | ||
| 
						 | 
					4bab1c32d7 | ||
| 
						 | 
					39064eb2c6 | ||
| 
						 | 
					28a60f5243 | ||
| 
						 | 
					56b9b878f8 | ||
| 
						 | 
					e7ad6e32e3 | ||
| 
						 | 
					9e80013e28 | ||
| 
						 | 
					77593969b2 | ||
| 
						 | 
					c39d0048a8 | ||
| 
						 | 
					5fc22b9530 | ||
| 
						 | 
					51735c3f6d | ||
| 
						 | 
					f14aad0c50 | ||
| 
						 | 
					cdbb492f2c | ||
| 
						 | 
					de18aefd7b | ||
| 
						 | 
					5f8807d62c | ||
| 
						 | 
					e42d8b8eeb | ||
| 
						 | 
					d67b8b8298 | ||
| 
						 | 
					10c8d157f5 | ||
| 
						 | 
					1f10558f1f | ||
| 
						 | 
					409228285e | ||
| 
						 | 
					0ac7758c04 | ||
| 
						 | 
					802e3d04b2 | ||
| 
						 | 
					39ef4a4711 | ||
| 
						 | 
					b2215e1db6 | ||
| 
						 | 
					7d42da5d3c | ||
| 
						 | 
					82770e6dd0 | ||
| 
						 | 
					62bbfc6075 | ||
| 
						 | 
					a5eb77dd87 | ||
| 
						 | 
					cb9cf4885f | ||
| 
						 | 
					a5455925ea | ||
| 
						 | 
					61ef383c38 | ||
| 
						 | 
					b0aa706c07 | ||
| 
						 | 
					a04c8f6214 | ||
| 
						 | 
					fd5b582c6c | ||
| 
						 | 
					dc45613b7b | ||
| 
						 | 
					d986d8f398 | ||
| 
						 | 
					6c64f20a14 | ||
| 
						 | 
					2071087794 | ||
| 
						 | 
					ba56ab719c | ||
| 
						 | 
					617c053b95 | ||
| 
						 | 
					868cff2c4c | ||
| 
						 | 
					8e23ebf3e4 | ||
| 
						 | 
					d9713f8e18 | ||
| 
						 | 
					c583b58cb9 | ||
| 
						 | 
					6dd6eff02c | ||
| 
						 | 
					3a1fcd2147 | ||
| 
						 | 
					bfeaf5dbf5 | ||
| 
						 | 
					d4bd4a8150 | ||
| 
						 | 
					2ace518db9 | ||
| 
						 | 
					e8641cee8f | ||
| 
						 | 
					884328d10f | ||
| 
						 | 
					d8bd8a29bc | ||
| 
						 | 
					cbd6b796ca | ||
| 
						 | 
					90cfa4ed5c | ||
| 
						 | 
					6426abfedf | ||
| 
						 | 
					d746928765 | ||
| 
						 | 
					f83554c817 | ||
| 
						 | 
					6fc4741c9a | ||
| 
						 | 
					7b63346bd0 | ||
| 
						 | 
					737c63e8b0 | ||
| 
						 | 
					5fa2bc3bc8 | ||
| 
						 | 
					5d7a5ace66 | ||
| 
						 | 
					0bd213a327 | ||
| 
						 | 
					3d9f351d84 | ||
| 
						 | 
					9fda220f33 | ||
| 
						 | 
					991ae1d6e3 | ||
| 
						 | 
					b993be4658 | ||
| 
						 | 
					c4f8af2311 | ||
| 
						 | 
					c34e38e50f | ||
| 
						 | 
					b98676ea77 | ||
| 
						 | 
					002c67e48c | ||
| 
						 | 
					cf21684916 | ||
| 
						 | 
					9fe1a904c8 | ||
| 
						 | 
					c4e67db75f | ||
| 
						 | 
					8487555315 | ||
| 
						 | 
					304c1ef5d2 | ||
| 
						 | 
					f0a86db9e4 | ||
| 
						 | 
					0907fa5685 | ||
| 
						 | 
					ff8dc76c75 | ||
| 
						 | 
					0b09e2790f | ||
| 
						 | 
					781350aa5f | ||
| 
						 | 
					9716130336 | 
							
								
								
									
										2
									
								
								.gitignore
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										2
									
								
								.gitignore
									
									
									
									
										vendored
									
									
								
							@@ -158,3 +158,5 @@ src/java/KP2ASoftkeyboard_AS/build/generated/mockable-android-23.jar
 | 
			
		||||
*.rawproto
 | 
			
		||||
src/java/Keepass2AndroidPluginSDK2/build/generated/mockable-Google-Inc.-Google-APIs-23.jar
 | 
			
		||||
/src/.vs
 | 
			
		||||
/src/JavaFileStorageBindings/Jars/JavaFileStorage-release.aar
 | 
			
		||||
/src/PluginSdkBinding/Jars/app-debug.aar
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										2
									
								
								.gitmodules
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										2
									
								
								.gitmodules
									
									
									
									
										vendored
									
									
								
							@@ -3,4 +3,4 @@
 | 
			
		||||
	url = https://github.com/PhilippC/Xamarin-Samsung-Pass.git
 | 
			
		||||
[submodule "src/netftpandroid"]
 | 
			
		||||
	path = src/netftpandroid
 | 
			
		||||
	url = https://git01.codeplex.com/forks/philippc/netftpandroid
 | 
			
		||||
	url = https://github.com/PhilippC/netftpandroid.git
 | 
			
		||||
 
 | 
			
		||||
@@ -12,7 +12,7 @@ As of January 2018, the following browsers are known to have Android Autofill su
 | 
			
		||||
These browsers do not (yet) have autofill support:
 | 
			
		||||
 | 
			
		||||
* Google Chrome
 | 
			
		||||
* Firefox for Android
 | 
			
		||||
* Firefox for Android ([bugzilla entry](https://bugzilla.mozilla.org/show_bug.cgi?id=1352011))
 | 
			
		||||
* Brave-Browser
 | 
			
		||||
* Opera
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -1,12 +1,11 @@
 | 
			
		||||
 | 
			
		||||
# What is Keepass2Android?
 | 
			
		||||
Keepass2Android is a password manager app. It allows to store and retrieve passwords and other sensitive information in a file called "database". This database is secured with a so-called master password. The master password typically is a strong password and can be complemented with a second factor for additional security.
 | 
			
		||||
The password database file can be synchronized across different devices. This works best using one of the built-in cloud storage options, but can also be performed with third-party apps. Keepass2Android is compatible with Keepass 1 and Keepass 2 on Windows and KepassX on Linux.
 | 
			
		||||
The password database file can be synchronized across different devices. This works best using one of the built-in cloud storage options, but can also be performed with third-party apps. Keepass2Android is compatible with Keepass 1 and Keepass 2 on Windows and KeepassX on Linux.
 | 
			
		||||
 | 
			
		||||
# Where to get it?
 | 
			
		||||
Regular stable releases of Keepass2Android are available on [Google Play](https://play.google.com/store/apps/details?id=keepass2android.keepass2android).
 | 
			
		||||
 | 
			
		||||
Beta-releases can be obtained by opting in to the [Beta testing channel](https://play.google.com/apps/testing/keepass2android.keepass2android). Please join the [Beta tester group](https://plus.google.com/communities/107293657110547776032) for news and discussions about the latest beta releases.
 | 
			
		||||
Beta-releases can be obtained by opting in to the [Beta testing channel](https://play.google.com/apps/testing/keepass2android.keepass2android) or [Beta testing channel for Keepass2Android Offline](https://play.google.com/apps/testing/keepass2android.keepass2android_nonet). Please join the [Beta tester group](https://plus.google.com/communities/107293657110547776032) for news and discussions about the latest beta releases.
 | 
			
		||||
 | 
			
		||||
# How can I contribute?
 | 
			
		||||
* Help to translate Keepass2Android into your language or improve translations at [our Crowdin page](http://crowdin.net/project/keepass2android)
 | 
			
		||||
@@ -16,4 +15,4 @@ Beta-releases can be obtained by opting in to the [Beta testing channel](https:/
 | 
			
		||||
# How do I learn more?
 | 
			
		||||
Please see the [documentation](Documentation.md).
 | 
			
		||||
 | 
			
		||||
[](https://www.bitrise.io/app/43a23ab54dee9f7e)
 | 
			
		||||
[](https://www.bitrise.io/app/43a23ab54dee9f7e)
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										3287
									
								
								graphics/launcher_icon/Logo-blue.svg
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										3287
									
								
								graphics/launcher_icon/Logo-blue.svg
									
									
									
									
									
										Normal file
									
								
							
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							| 
		 After Width: | Height: | Size: 353 KiB  | 
							
								
								
									
										47
									
								
								graphics/launcher_icon/Logo-green-foreground.svg
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										47
									
								
								graphics/launcher_icon/Logo-green-foreground.svg
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,47 @@
 | 
			
		||||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
 | 
			
		||||
<!-- Generator: Adobe Illustrator 22.0.1, SVG Export Plug-In . SVG Version: 6.00 Build 0)  -->
 | 
			
		||||
 | 
			
		||||
<svg
 | 
			
		||||
   xmlns:dc="http://purl.org/dc/elements/1.1/"
 | 
			
		||||
   xmlns:cc="http://creativecommons.org/ns#"
 | 
			
		||||
   xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
 | 
			
		||||
   xmlns:svg="http://www.w3.org/2000/svg"
 | 
			
		||||
   xmlns="http://www.w3.org/2000/svg"
 | 
			
		||||
   xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
 | 
			
		||||
   xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
 | 
			
		||||
   version="1.1"
 | 
			
		||||
   id="Layer_1"
 | 
			
		||||
   x="0px"
 | 
			
		||||
   y="0px"
 | 
			
		||||
   viewBox="0 0 800 800"
 | 
			
		||||
   enable-background="new 0 0 800 800"
 | 
			
		||||
   xml:space="preserve"
 | 
			
		||||
   sodipodi:docname="Logo-green-foreground.svg"
 | 
			
		||||
   inkscape:version="0.92.2 (5c3e80d, 2017-08-06)"><metadata
 | 
			
		||||
     id="metadata4969"><rdf:RDF><cc:Work
 | 
			
		||||
         rdf:about=""><dc:format>image/svg+xml</dc:format><dc:type
 | 
			
		||||
           rdf:resource="http://purl.org/dc/dcmitype/StillImage" /><dc:title></dc:title></cc:Work></rdf:RDF></metadata><defs
 | 
			
		||||
     id="defs4967" /><sodipodi:namedview
 | 
			
		||||
     pagecolor="#ffffff"
 | 
			
		||||
     bordercolor="#666666"
 | 
			
		||||
     borderopacity="1"
 | 
			
		||||
     objecttolerance="10"
 | 
			
		||||
     gridtolerance="10"
 | 
			
		||||
     guidetolerance="10"
 | 
			
		||||
     inkscape:pageopacity="0"
 | 
			
		||||
     inkscape:pageshadow="2"
 | 
			
		||||
     inkscape:window-width="1920"
 | 
			
		||||
     inkscape:window-height="1017"
 | 
			
		||||
     id="namedview4965"
 | 
			
		||||
     showgrid="false"
 | 
			
		||||
     inkscape:zoom="0.75130096"
 | 
			
		||||
     inkscape:cx="413.59403"
 | 
			
		||||
     inkscape:cy="332.90312"
 | 
			
		||||
     inkscape:window-x="-8"
 | 
			
		||||
     inkscape:window-y="-8"
 | 
			
		||||
     inkscape:window-maximized="1"
 | 
			
		||||
     inkscape:current-layer="Layer_1" /><path
 | 
			
		||||
     d="m 318.7,232 c 13.6,0 24.6,10.9 24.6,24.4 0,13.5 -11,24.4 -24.6,24.4 -13.6,0 -24.6,-10.9 -24.6,-24.4 0,-13.5 11,-24.4 24.6,-24.4 z m 134.8,24.4 c 0,13.5 11,24.4 24.6,24.4 13.6,0 24.6,-10.9 24.6,-24.4 0,-13.5 -11,-24.4 -24.6,-24.4 -13.6,0 -24.6,10.9 -24.6,24.4 z M 399.8,177.7 M 140.2,600.6 v 47 h 517.3 v -47 z m 0,-249.7 v 47 h 517.3 v -47 z m -0.1,130.3 h 191.8 c -0.8,-4.1 -1.2,-8.3 -1.2,-12.4 0,-12.4 3.4,-24.2 9.9,-34.6 H 140.1 Z m 517.4,0 v -47 H 454.9 c 6.5,10.4 9.8,22.2 9.8,34.6 0,4.1 -0.4,8.3 -1.2,12.4 z m -517.4,36.2 v 47 h 186.6 l 14.3,-47 z m 314.2,0 14.4,47 h 188.8 v -47 z m -21.6,48.4 -21,-68.9 2.7,-1.6 c 10.3,-5.9 16.7,-16.9 16.7,-28.6 0,-18.2 -15,-33 -33.3,-33 -18.3,0 -33.3,14.8 -33.3,33 0,11.8 6.4,22.7 16.7,28.6 l 2.7,1.6 -21.1,68.9 z m 74.8,-407.3 0.2,-0.3 35.6,-51.3 c 2.4,-3.5 1.8,-8.1 -1.4,-10.3 -3.2,-2.2 -7.7,-1.1 -10.2,2.4 l -37.2,53.5 -0.1,0.3 c -29.3,-11.8 -62.1,-18.5 -96.8,-18.5 -35.2,0 -68.5,6.9 -98.1,19 L 261.8,99 c -2.4,-3.5 -7,-4.6 -10.2,-2.4 -3.2,2.2 -3.8,6.8 -1.4,10.3 l 36.2,52.2 c -66.8,32.2 -111.9,92.4 -111.9,161.3 h 42.9 c 0,-79.1 80.8,-143.5 180.1,-143.5 99.3,0 180.1,64.3 180.1,143.5 h 42.9 c 0.2,-69.3 -45.4,-129.8 -113,-161.9 z"
 | 
			
		||||
     id="path4962"
 | 
			
		||||
     inkscape:connector-curvature="0"
 | 
			
		||||
     style="clip-rule:evenodd;fill:#ffffff;fill-rule:evenodd" /></svg>
 | 
			
		||||
| 
		 After Width: | Height: | Size: 2.8 KiB  | 
							
								
								
									
										3279
									
								
								graphics/launcher_icon/Logo-green.svg
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										3279
									
								
								graphics/launcher_icon/Logo-green.svg
									
									
									
									
									
										Normal file
									
								
							
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							| 
		 After Width: | Height: | Size: 353 KiB  | 
@@ -10,7 +10,7 @@
 | 
			
		||||
    <RootNamespace>AndroidFileChooserBinding</RootNamespace>
 | 
			
		||||
    <AssemblyName>AndroidFileChooserBinding</AssemblyName>
 | 
			
		||||
    <FileAlignment>512</FileAlignment>
 | 
			
		||||
    <TargetFrameworkVersion>v8.0</TargetFrameworkVersion>
 | 
			
		||||
    <TargetFrameworkVersion>v8.1</TargetFrameworkVersion>
 | 
			
		||||
    <AndroidUseLatestPlatformSdk>True</AndroidUseLatestPlatformSdk>
 | 
			
		||||
  </PropertyGroup>
 | 
			
		||||
  <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										
											BIN
										
									
								
								src/JavaFileStorageBindings/Jars/adal-1.14.0.aar
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										
											BIN
										
									
								
								src/JavaFileStorageBindings/Jars/adal-1.14.0.aar
									
									
									
									
									
										Normal file
									
								
							
										
											Binary file not shown.
										
									
								
							@@ -11,7 +11,7 @@
 | 
			
		||||
    <AssemblyName>JavaFileStorageBindings</AssemblyName>
 | 
			
		||||
    <FileAlignment>512</FileAlignment>
 | 
			
		||||
    <AndroidUseLatestPlatformSdk>True</AndroidUseLatestPlatformSdk>
 | 
			
		||||
    <TargetFrameworkVersion>v8.0</TargetFrameworkVersion>
 | 
			
		||||
    <TargetFrameworkVersion>v8.1</TargetFrameworkVersion>
 | 
			
		||||
  </PropertyGroup>
 | 
			
		||||
  <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
 | 
			
		||||
    <DebugSymbols>true</DebugSymbols>
 | 
			
		||||
@@ -60,6 +60,7 @@
 | 
			
		||||
    </LibraryProjectZip>
 | 
			
		||||
    <None Include="Jars\AboutJars.txt" />
 | 
			
		||||
    <None Include="Additions\AboutAdditions.txt" />
 | 
			
		||||
    <LibraryProjectZip Include="Jars\adal-1.14.0.aar" />
 | 
			
		||||
  </ItemGroup>
 | 
			
		||||
  <ItemGroup>
 | 
			
		||||
    <TransformFile Include="Transforms\Metadata.xml" />
 | 
			
		||||
@@ -92,9 +93,6 @@
 | 
			
		||||
  <ItemGroup>
 | 
			
		||||
    <EmbeddedReferenceJar Include="Jars\onedrive-sdk-android-1.2.2\classes-onedrive-sdk.jar" />
 | 
			
		||||
  </ItemGroup>
 | 
			
		||||
  <ItemGroup>
 | 
			
		||||
    <EmbeddedReferenceJar Include="Jars\adal-1.1.19\classes-adal.jar" />
 | 
			
		||||
  </ItemGroup>
 | 
			
		||||
  <ItemGroup>
 | 
			
		||||
    <EmbeddedReferenceJar Include="Jars\gdrive\commons-logging-1.1.1.jar" />
 | 
			
		||||
  </ItemGroup>
 | 
			
		||||
 
 | 
			
		||||
@@ -10,7 +10,7 @@
 | 
			
		||||
    <RootNamespace>KP2AKdbLibraryBinding</RootNamespace>
 | 
			
		||||
    <AssemblyName>KP2AKdbLibraryBinding</AssemblyName>
 | 
			
		||||
    <FileAlignment>512</FileAlignment>
 | 
			
		||||
    <TargetFrameworkVersion>v8.0</TargetFrameworkVersion>
 | 
			
		||||
    <TargetFrameworkVersion>v8.1</TargetFrameworkVersion>
 | 
			
		||||
    <AndroidUseLatestPlatformSdk>True</AndroidUseLatestPlatformSdk>
 | 
			
		||||
  </PropertyGroup>
 | 
			
		||||
  <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
 | 
			
		||||
 
 | 
			
		||||
@@ -1,7 +1,7 @@
 | 
			
		||||
 | 
			
		||||
Microsoft Visual Studio Solution File, Format Version 12.00
 | 
			
		||||
# Visual Studio 15
 | 
			
		||||
VisualStudioVersion = 15.0.27004.2009
 | 
			
		||||
VisualStudioVersion = 15.0.27130.2010
 | 
			
		||||
MinimumVisualStudioVersion = 10.0.40219.1
 | 
			
		||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "KeePassLib2Android", "KeePassLib2Android\KeePassLib2Android.csproj", "{545B4A6B-8BBA-4FBE-92FC-4AC060122A54}"
 | 
			
		||||
EndProject
 | 
			
		||||
@@ -13,8 +13,6 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Kp2aBusinessLogic", "Kp2aBu
 | 
			
		||||
EndProject
 | 
			
		||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "TwofishCipher", "TwofishCipher\TwofishCipher.csproj", "{5CF675A5-9BEE-4720-BED9-D5BF14A2EBF9}"
 | 
			
		||||
EndProject
 | 
			
		||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "JavaFileStorageBindings", "JavaFileStorageBindings\JavaFileStorageBindings.csproj", "{48574278-4779-4B3A-A9E4-9CF1BC285D0B}"
 | 
			
		||||
EndProject
 | 
			
		||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "AndroidFileChooserBinding", "AndroidFileChooserBinding\AndroidFileChooserBinding.csproj", "{3C0F7FE5-639F-4422-A087-8B26CF862D1B}"
 | 
			
		||||
EndProject
 | 
			
		||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "KP2AKdbLibraryBinding", "KP2AKdbLibraryBinding\KP2AKdbLibraryBinding.csproj", "{70D3844A-D9FA-4A64-B205-A84C6A822196}"
 | 
			
		||||
@@ -23,8 +21,6 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "PluginSdkBinding", "PluginS
 | 
			
		||||
EndProject
 | 
			
		||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ZlibAndroid", "ZlibAndroid\ZlibAndroid.csproj", "{6C29A7E7-E016-4FC1-B1A0-DEE26AC711BB}"
 | 
			
		||||
EndProject
 | 
			
		||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "System.Net.FtpClient.Android", "netftpandroid\System.Net.FtpClient\System.Net.FtpClient.Android.csproj", "{146FD497-BA03-4740-B6C5-5C84EA8FCDE2}"
 | 
			
		||||
EndProject
 | 
			
		||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "SamsungPass", "SamsungPass\Xamarin.SamsungPass\SamsungPass\SamsungPass.csproj", "{3A4B8E88-FA9B-4663-BCDA-21C12E3AF98A}"
 | 
			
		||||
EndProject
 | 
			
		||||
Global
 | 
			
		||||
@@ -109,8 +105,8 @@ Global
 | 
			
		||||
		{A8779D4D-7C49-4C2F-82BD-2CDC448391DA}.Release|Win32.Build.0 = Release|Any CPU
 | 
			
		||||
		{A8779D4D-7C49-4C2F-82BD-2CDC448391DA}.Release|x64.ActiveCfg = Release|Any CPU
 | 
			
		||||
		{A8779D4D-7C49-4C2F-82BD-2CDC448391DA}.Release|x64.Build.0 = Release|Any CPU
 | 
			
		||||
		{A8779D4D-7C49-4C2F-82BD-2CDC448391DA}.ReleaseNoNet|Any CPU.ActiveCfg = Debug|Any CPU
 | 
			
		||||
		{A8779D4D-7C49-4C2F-82BD-2CDC448391DA}.ReleaseNoNet|Any CPU.Build.0 = Debug|Any CPU
 | 
			
		||||
		{A8779D4D-7C49-4C2F-82BD-2CDC448391DA}.ReleaseNoNet|Any CPU.ActiveCfg = ReleaseNoNet|Any CPU
 | 
			
		||||
		{A8779D4D-7C49-4C2F-82BD-2CDC448391DA}.ReleaseNoNet|Any CPU.Build.0 = ReleaseNoNet|Any CPU
 | 
			
		||||
		{A8779D4D-7C49-4C2F-82BD-2CDC448391DA}.ReleaseNoNet|Mixed Platforms.ActiveCfg = ReleaseNoNet|Any CPU
 | 
			
		||||
		{A8779D4D-7C49-4C2F-82BD-2CDC448391DA}.ReleaseNoNet|Mixed Platforms.Build.0 = ReleaseNoNet|Any CPU
 | 
			
		||||
		{A8779D4D-7C49-4C2F-82BD-2CDC448391DA}.ReleaseNoNet|Win32.ActiveCfg = Release|Any CPU
 | 
			
		||||
@@ -151,24 +147,6 @@ Global
 | 
			
		||||
		{5CF675A5-9BEE-4720-BED9-D5BF14A2EBF9}.ReleaseNoNet|Mixed Platforms.Build.0 = ReleaseNoNet|Any CPU
 | 
			
		||||
		{5CF675A5-9BEE-4720-BED9-D5BF14A2EBF9}.ReleaseNoNet|Win32.ActiveCfg = Release|Any CPU
 | 
			
		||||
		{5CF675A5-9BEE-4720-BED9-D5BF14A2EBF9}.ReleaseNoNet|x64.ActiveCfg = Release|Any CPU
 | 
			
		||||
		{48574278-4779-4B3A-A9E4-9CF1BC285D0B}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
 | 
			
		||||
		{48574278-4779-4B3A-A9E4-9CF1BC285D0B}.Debug|Any CPU.Build.0 = Debug|Any CPU
 | 
			
		||||
		{48574278-4779-4B3A-A9E4-9CF1BC285D0B}.Debug|Mixed Platforms.ActiveCfg = Debug|Any CPU
 | 
			
		||||
		{48574278-4779-4B3A-A9E4-9CF1BC285D0B}.Debug|Mixed Platforms.Build.0 = Debug|Any CPU
 | 
			
		||||
		{48574278-4779-4B3A-A9E4-9CF1BC285D0B}.Debug|Win32.ActiveCfg = Debug|Any CPU
 | 
			
		||||
		{48574278-4779-4B3A-A9E4-9CF1BC285D0B}.Debug|x64.ActiveCfg = Debug|Any CPU
 | 
			
		||||
		{48574278-4779-4B3A-A9E4-9CF1BC285D0B}.Release|Any CPU.ActiveCfg = Release|Any CPU
 | 
			
		||||
		{48574278-4779-4B3A-A9E4-9CF1BC285D0B}.Release|Any CPU.Build.0 = Release|Any CPU
 | 
			
		||||
		{48574278-4779-4B3A-A9E4-9CF1BC285D0B}.Release|Mixed Platforms.ActiveCfg = Release|Any CPU
 | 
			
		||||
		{48574278-4779-4B3A-A9E4-9CF1BC285D0B}.Release|Mixed Platforms.Build.0 = Release|Any CPU
 | 
			
		||||
		{48574278-4779-4B3A-A9E4-9CF1BC285D0B}.Release|Win32.ActiveCfg = Release|Any CPU
 | 
			
		||||
		{48574278-4779-4B3A-A9E4-9CF1BC285D0B}.Release|x64.ActiveCfg = Release|Any CPU
 | 
			
		||||
		{48574278-4779-4B3A-A9E4-9CF1BC285D0B}.ReleaseNoNet|Any CPU.ActiveCfg = Release|Any CPU
 | 
			
		||||
		{48574278-4779-4B3A-A9E4-9CF1BC285D0B}.ReleaseNoNet|Any CPU.Build.0 = Release|Any CPU
 | 
			
		||||
		{48574278-4779-4B3A-A9E4-9CF1BC285D0B}.ReleaseNoNet|Mixed Platforms.ActiveCfg = ReleaseNoNet|Any CPU
 | 
			
		||||
		{48574278-4779-4B3A-A9E4-9CF1BC285D0B}.ReleaseNoNet|Mixed Platforms.Build.0 = ReleaseNoNet|Any CPU
 | 
			
		||||
		{48574278-4779-4B3A-A9E4-9CF1BC285D0B}.ReleaseNoNet|Win32.ActiveCfg = Release|Any CPU
 | 
			
		||||
		{48574278-4779-4B3A-A9E4-9CF1BC285D0B}.ReleaseNoNet|x64.ActiveCfg = Release|Any CPU
 | 
			
		||||
		{3C0F7FE5-639F-4422-A087-8B26CF862D1B}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
 | 
			
		||||
		{3C0F7FE5-639F-4422-A087-8B26CF862D1B}.Debug|Any CPU.Build.0 = Debug|Any CPU
 | 
			
		||||
		{3C0F7FE5-639F-4422-A087-8B26CF862D1B}.Debug|Mixed Platforms.ActiveCfg = Debug|Any CPU
 | 
			
		||||
@@ -181,8 +159,8 @@ Global
 | 
			
		||||
		{3C0F7FE5-639F-4422-A087-8B26CF862D1B}.Release|Mixed Platforms.Build.0 = Release|Any CPU
 | 
			
		||||
		{3C0F7FE5-639F-4422-A087-8B26CF862D1B}.Release|Win32.ActiveCfg = Release|Any CPU
 | 
			
		||||
		{3C0F7FE5-639F-4422-A087-8B26CF862D1B}.Release|x64.ActiveCfg = Release|Any CPU
 | 
			
		||||
		{3C0F7FE5-639F-4422-A087-8B26CF862D1B}.ReleaseNoNet|Any CPU.ActiveCfg = Release|Any CPU
 | 
			
		||||
		{3C0F7FE5-639F-4422-A087-8B26CF862D1B}.ReleaseNoNet|Any CPU.Build.0 = Release|Any CPU
 | 
			
		||||
		{3C0F7FE5-639F-4422-A087-8B26CF862D1B}.ReleaseNoNet|Any CPU.ActiveCfg = ReleaseNoNet|Any CPU
 | 
			
		||||
		{3C0F7FE5-639F-4422-A087-8B26CF862D1B}.ReleaseNoNet|Any CPU.Build.0 = ReleaseNoNet|Any CPU
 | 
			
		||||
		{3C0F7FE5-639F-4422-A087-8B26CF862D1B}.ReleaseNoNet|Mixed Platforms.ActiveCfg = ReleaseNoNet|Any CPU
 | 
			
		||||
		{3C0F7FE5-639F-4422-A087-8B26CF862D1B}.ReleaseNoNet|Mixed Platforms.Build.0 = ReleaseNoNet|Any CPU
 | 
			
		||||
		{3C0F7FE5-639F-4422-A087-8B26CF862D1B}.ReleaseNoNet|Win32.ActiveCfg = Release|Any CPU
 | 
			
		||||
@@ -199,8 +177,8 @@ Global
 | 
			
		||||
		{70D3844A-D9FA-4A64-B205-A84C6A822196}.Release|Mixed Platforms.Build.0 = Release|Any CPU
 | 
			
		||||
		{70D3844A-D9FA-4A64-B205-A84C6A822196}.Release|Win32.ActiveCfg = Release|Any CPU
 | 
			
		||||
		{70D3844A-D9FA-4A64-B205-A84C6A822196}.Release|x64.ActiveCfg = Release|Any CPU
 | 
			
		||||
		{70D3844A-D9FA-4A64-B205-A84C6A822196}.ReleaseNoNet|Any CPU.ActiveCfg = Release|Any CPU
 | 
			
		||||
		{70D3844A-D9FA-4A64-B205-A84C6A822196}.ReleaseNoNet|Any CPU.Build.0 = Release|Any CPU
 | 
			
		||||
		{70D3844A-D9FA-4A64-B205-A84C6A822196}.ReleaseNoNet|Any CPU.ActiveCfg = ReleaseNoNet|Any CPU
 | 
			
		||||
		{70D3844A-D9FA-4A64-B205-A84C6A822196}.ReleaseNoNet|Any CPU.Build.0 = ReleaseNoNet|Any CPU
 | 
			
		||||
		{70D3844A-D9FA-4A64-B205-A84C6A822196}.ReleaseNoNet|Mixed Platforms.ActiveCfg = ReleaseNoNet|Any CPU
 | 
			
		||||
		{70D3844A-D9FA-4A64-B205-A84C6A822196}.ReleaseNoNet|Mixed Platforms.Build.0 = ReleaseNoNet|Any CPU
 | 
			
		||||
		{70D3844A-D9FA-4A64-B205-A84C6A822196}.ReleaseNoNet|Win32.ActiveCfg = Release|Any CPU
 | 
			
		||||
@@ -217,8 +195,8 @@ Global
 | 
			
		||||
		{3DA3911E-36DE-465E-8F15-F1991B6437E5}.Release|Mixed Platforms.Build.0 = Release|Any CPU
 | 
			
		||||
		{3DA3911E-36DE-465E-8F15-F1991B6437E5}.Release|Win32.ActiveCfg = Release|Any CPU
 | 
			
		||||
		{3DA3911E-36DE-465E-8F15-F1991B6437E5}.Release|x64.ActiveCfg = Release|Any CPU
 | 
			
		||||
		{3DA3911E-36DE-465E-8F15-F1991B6437E5}.ReleaseNoNet|Any CPU.ActiveCfg = Release|Any CPU
 | 
			
		||||
		{3DA3911E-36DE-465E-8F15-F1991B6437E5}.ReleaseNoNet|Any CPU.Build.0 = Release|Any CPU
 | 
			
		||||
		{3DA3911E-36DE-465E-8F15-F1991B6437E5}.ReleaseNoNet|Any CPU.ActiveCfg = ReleaseNoNet|Any CPU
 | 
			
		||||
		{3DA3911E-36DE-465E-8F15-F1991B6437E5}.ReleaseNoNet|Any CPU.Build.0 = ReleaseNoNet|Any CPU
 | 
			
		||||
		{3DA3911E-36DE-465E-8F15-F1991B6437E5}.ReleaseNoNet|Mixed Platforms.ActiveCfg = ReleaseNoNet|Any CPU
 | 
			
		||||
		{3DA3911E-36DE-465E-8F15-F1991B6437E5}.ReleaseNoNet|Mixed Platforms.Build.0 = ReleaseNoNet|Any CPU
 | 
			
		||||
		{3DA3911E-36DE-465E-8F15-F1991B6437E5}.ReleaseNoNet|Win32.ActiveCfg = Release|Any CPU
 | 
			
		||||
@@ -247,24 +225,6 @@ Global
 | 
			
		||||
		{6C29A7E7-E016-4FC1-B1A0-DEE26AC711BB}.ReleaseNoNet|Win32.Build.0 = Release|Any CPU
 | 
			
		||||
		{6C29A7E7-E016-4FC1-B1A0-DEE26AC711BB}.ReleaseNoNet|x64.ActiveCfg = Release|Any CPU
 | 
			
		||||
		{6C29A7E7-E016-4FC1-B1A0-DEE26AC711BB}.ReleaseNoNet|x64.Build.0 = Release|Any CPU
 | 
			
		||||
		{146FD497-BA03-4740-B6C5-5C84EA8FCDE2}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
 | 
			
		||||
		{146FD497-BA03-4740-B6C5-5C84EA8FCDE2}.Debug|Any CPU.Build.0 = Debug|Any CPU
 | 
			
		||||
		{146FD497-BA03-4740-B6C5-5C84EA8FCDE2}.Debug|Mixed Platforms.ActiveCfg = Debug|Any CPU
 | 
			
		||||
		{146FD497-BA03-4740-B6C5-5C84EA8FCDE2}.Debug|Mixed Platforms.Build.0 = Debug|Any CPU
 | 
			
		||||
		{146FD497-BA03-4740-B6C5-5C84EA8FCDE2}.Debug|Win32.ActiveCfg = Debug|Any CPU
 | 
			
		||||
		{146FD497-BA03-4740-B6C5-5C84EA8FCDE2}.Debug|x64.ActiveCfg = Debug|Any CPU
 | 
			
		||||
		{146FD497-BA03-4740-B6C5-5C84EA8FCDE2}.Release|Any CPU.ActiveCfg = Release|Any CPU
 | 
			
		||||
		{146FD497-BA03-4740-B6C5-5C84EA8FCDE2}.Release|Any CPU.Build.0 = Release|Any CPU
 | 
			
		||||
		{146FD497-BA03-4740-B6C5-5C84EA8FCDE2}.Release|Mixed Platforms.ActiveCfg = Release|Any CPU
 | 
			
		||||
		{146FD497-BA03-4740-B6C5-5C84EA8FCDE2}.Release|Mixed Platforms.Build.0 = Release|Any CPU
 | 
			
		||||
		{146FD497-BA03-4740-B6C5-5C84EA8FCDE2}.Release|Win32.ActiveCfg = Release|Any CPU
 | 
			
		||||
		{146FD497-BA03-4740-B6C5-5C84EA8FCDE2}.Release|x64.ActiveCfg = Release|Any CPU
 | 
			
		||||
		{146FD497-BA03-4740-B6C5-5C84EA8FCDE2}.ReleaseNoNet|Any CPU.ActiveCfg = Release|Any CPU
 | 
			
		||||
		{146FD497-BA03-4740-B6C5-5C84EA8FCDE2}.ReleaseNoNet|Any CPU.Build.0 = Release|Any CPU
 | 
			
		||||
		{146FD497-BA03-4740-B6C5-5C84EA8FCDE2}.ReleaseNoNet|Mixed Platforms.ActiveCfg = Release|Any CPU
 | 
			
		||||
		{146FD497-BA03-4740-B6C5-5C84EA8FCDE2}.ReleaseNoNet|Mixed Platforms.Build.0 = Release|Any CPU
 | 
			
		||||
		{146FD497-BA03-4740-B6C5-5C84EA8FCDE2}.ReleaseNoNet|Win32.ActiveCfg = Release|Any CPU
 | 
			
		||||
		{146FD497-BA03-4740-B6C5-5C84EA8FCDE2}.ReleaseNoNet|x64.ActiveCfg = Release|Any CPU
 | 
			
		||||
		{3A4B8E88-FA9B-4663-BCDA-21C12E3AF98A}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
 | 
			
		||||
		{3A4B8E88-FA9B-4663-BCDA-21C12E3AF98A}.Debug|Any CPU.Build.0 = Debug|Any CPU
 | 
			
		||||
		{3A4B8E88-FA9B-4663-BCDA-21C12E3AF98A}.Debug|Mixed Platforms.ActiveCfg = Debug|Any CPU
 | 
			
		||||
 
 | 
			
		||||
@@ -55,7 +55,10 @@ namespace KeePassLib.Cryptography.KeyDerivation
 | 
			
		||||
			get { return "AES-KDF"; }
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		public AesKdf()
 | 
			
		||||
        public override byte[] GetSeed(KdfParameters p)
 | 
			
		||||
        { return p.GetByteArray(ParamSeed); }
 | 
			
		||||
 | 
			
		||||
        public AesKdf()
 | 
			
		||||
		{
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -68,7 +68,10 @@ namespace KeePassLib.Cryptography.KeyDerivation
 | 
			
		||||
			get { return "Argon2"; }
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		public Argon2Kdf()
 | 
			
		||||
        public override byte[] GetSeed(KdfParameters p)
 | 
			
		||||
        { return p.GetByteArray(ParamSalt); }
 | 
			
		||||
 | 
			
		||||
        public Argon2Kdf()
 | 
			
		||||
		{
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -36,7 +36,9 @@ namespace KeePassLib.Cryptography.KeyDerivation
 | 
			
		||||
			get;
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		public virtual KdfParameters GetDefaultParameters()
 | 
			
		||||
        public abstract byte[] GetSeed(KdfParameters p);
 | 
			
		||||
 | 
			
		||||
        public virtual KdfParameters GetDefaultParameters()
 | 
			
		||||
		{
 | 
			
		||||
			return new KdfParameters(this.Uuid);
 | 
			
		||||
		}
 | 
			
		||||
 
 | 
			
		||||
@@ -12,7 +12,7 @@
 | 
			
		||||
    <AndroidResgenFile>Resources\Resource.designer.cs</AndroidResgenFile>
 | 
			
		||||
    <AndroidResgenClass>Resource</AndroidResgenClass>
 | 
			
		||||
    <AssemblyName>KeePassLib2Android</AssemblyName>
 | 
			
		||||
    <TargetFrameworkVersion>v8.0</TargetFrameworkVersion>
 | 
			
		||||
    <TargetFrameworkVersion>v8.1</TargetFrameworkVersion>
 | 
			
		||||
    <AndroidUseLatestPlatformSdk>True</AndroidUseLatestPlatformSdk>
 | 
			
		||||
    <NuGetPackageImportStamp>8482b288</NuGetPackageImportStamp>
 | 
			
		||||
  </PropertyGroup>
 | 
			
		||||
 
 | 
			
		||||
@@ -20,11 +20,8 @@
 | 
			
		||||
using System;
 | 
			
		||||
using System.Collections.Generic;
 | 
			
		||||
using System.Diagnostics;
 | 
			
		||||
using System.Text;
 | 
			
		||||
 | 
			
		||||
using KeePassLib.Cryptography;
 | 
			
		||||
using KeePassLib.Cryptography.KeyDerivation;
 | 
			
		||||
using KeePassLib.Native;
 | 
			
		||||
using KeePassLib.Resources;
 | 
			
		||||
using KeePassLib.Security;
 | 
			
		||||
using KeePassLib.Utility;
 | 
			
		||||
@@ -168,7 +165,7 @@ namespace KeePassLib.Keys
 | 
			
		||||
		/// Creates the composite key from the supplied user key sources (password,
 | 
			
		||||
		/// key file, user account, computer ID, etc.).
 | 
			
		||||
		/// </summary>
 | 
			
		||||
		private byte[] CreateRawCompositeKey32(byte[] mPbMasterSeed)
 | 
			
		||||
		private byte[] CreateRawCompositeKey32(byte[] mPbMasterSeed, byte[] mPbKdfSeed)
 | 
			
		||||
		{
 | 
			
		||||
			ValidateUserKeys();
 | 
			
		||||
 | 
			
		||||
@@ -178,7 +175,7 @@ namespace KeePassLib.Keys
 | 
			
		||||
			foreach(IUserKey pKey in m_vUserKeys)
 | 
			
		||||
			{
 | 
			
		||||
				if (pKey is ISeedBasedUserKey)
 | 
			
		||||
					((ISeedBasedUserKey)pKey).SetParams(mPbMasterSeed);
 | 
			
		||||
					((ISeedBasedUserKey)pKey).SetParams(mPbMasterSeed, mPbKdfSeed);
 | 
			
		||||
				ProtectedBinary b = pKey.KeyData;
 | 
			
		||||
				if(b != null)
 | 
			
		||||
				{
 | 
			
		||||
@@ -211,15 +208,17 @@ namespace KeePassLib.Keys
 | 
			
		||||
		{
 | 
			
		||||
			if(p == null) { Debug.Assert(false); throw new ArgumentNullException("p"); }
 | 
			
		||||
 | 
			
		||||
			byte[] pbRaw32 = CreateRawCompositeKey32(mPbMasterSeed);
 | 
			
		||||
 | 
			
		||||
		    KdfEngine kdf = KdfPool.Get(p.KdfUuid);
 | 
			
		||||
		    if (kdf == null) // CryptographicExceptions are translated to "file corrupted"
 | 
			
		||||
		        throw new Exception(KLRes.UnknownKdf + MessageService.NewParagraph +
 | 
			
		||||
		                            KLRes.FileNewVerOrPlgReq + MessageService.NewParagraph +
 | 
			
		||||
		                            "UUID: " + p.KdfUuid.ToHexString() + ".");
 | 
			
		||||
 | 
			
		||||
            byte[] pbRaw32 = CreateRawCompositeKey32(mPbMasterSeed, kdf.GetSeed(p));
 | 
			
		||||
			if((pbRaw32 == null) || (pbRaw32.Length != 32))
 | 
			
		||||
				{ Debug.Assert(false); return null; }
 | 
			
		||||
 | 
			
		||||
			KdfEngine kdf = KdfPool.Get(p.KdfUuid);
 | 
			
		||||
			if(kdf == null) // CryptographicExceptions are translated to "file corrupted"
 | 
			
		||||
				throw new Exception(KLRes.UnknownKdf + MessageService.NewParagraph +
 | 
			
		||||
					KLRes.FileNewVerOrPlgReq + MessageService.NewParagraph +
 | 
			
		||||
					"UUID: " + p.KdfUuid.ToHexString() + ".");
 | 
			
		||||
 | 
			
		||||
			byte[] pbTrf32 = kdf.Transform(pbRaw32, p);
 | 
			
		||||
			if(pbTrf32 == null) { Debug.Assert(false); return null; }
 | 
			
		||||
@@ -256,7 +255,7 @@ namespace KeePassLib.Keys
 | 
			
		||||
 | 
			
		||||
	public interface ISeedBasedUserKey
 | 
			
		||||
	{
 | 
			
		||||
		void SetParams(byte[] masterSeed);
 | 
			
		||||
		void SetParams(byte[] masterSeed, byte[] mPbKdfSeed);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	public sealed class InvalidCompositeKeyException : Exception
 | 
			
		||||
 
 | 
			
		||||
@@ -100,7 +100,8 @@ namespace keepass2android
 | 
			
		||||
				int count = 0;
 | 
			
		||||
				while (File.Exists(LogFilename + "." + count))
 | 
			
		||||
					count++;
 | 
			
		||||
				File.Move(LogFilename, LogFilename + "." + count);
 | 
			
		||||
                if (count > 0)
 | 
			
		||||
				    File.Move(LogFilename, LogFilename + "." + count);
 | 
			
		||||
				
 | 
			
		||||
			}
 | 
			
		||||
				
 | 
			
		||||
 
 | 
			
		||||
@@ -52,7 +52,7 @@ namespace keepass2android
 | 
			
		||||
		/// <summary>
 | 
			
		||||
		/// Tell the app that the file from ioc was opened with keyfile.
 | 
			
		||||
		/// </summary>
 | 
			
		||||
		void StoreOpenedFileAsRecent(IOConnectionInfo ioc, string keyfile);
 | 
			
		||||
		void StoreOpenedFileAsRecent(IOConnectionInfo ioc, string keyfile, string displayName = "");
 | 
			
		||||
 | 
			
		||||
		/// <summary>
 | 
			
		||||
		/// Creates a new database and returns it
 | 
			
		||||
 
 | 
			
		||||
@@ -2,11 +2,15 @@ using System;
 | 
			
		||||
using System.Collections.Generic;
 | 
			
		||||
using System.IO;
 | 
			
		||||
using System.Linq;
 | 
			
		||||
using System.Runtime.Serialization;
 | 
			
		||||
using Android;
 | 
			
		||||
using Android.Content;
 | 
			
		||||
using Android.Database;
 | 
			
		||||
using Android.OS;
 | 
			
		||||
using Android.Provider;
 | 
			
		||||
using Java.IO;
 | 
			
		||||
using KeePassLib.Serialization;
 | 
			
		||||
using Console = System.Console;
 | 
			
		||||
 | 
			
		||||
namespace keepass2android.Io
 | 
			
		||||
{
 | 
			
		||||
@@ -28,7 +32,12 @@ namespace keepass2android.Io
 | 
			
		||||
			get { yield return "content"; }
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		public void Delete(IOConnectionInfo ioc)
 | 
			
		||||
	    public bool UserShouldBackup
 | 
			
		||||
	    {
 | 
			
		||||
	        get { return true; }
 | 
			
		||||
	    }
 | 
			
		||||
 | 
			
		||||
	    public void Delete(IOConnectionInfo ioc)
 | 
			
		||||
		{
 | 
			
		||||
			throw new NotImplementedException();
 | 
			
		||||
		}
 | 
			
		||||
@@ -45,7 +54,20 @@ namespace keepass2android.Io
 | 
			
		||||
 | 
			
		||||
		public Stream OpenFileForRead(IOConnectionInfo ioc)
 | 
			
		||||
		{
 | 
			
		||||
			return _ctx.ContentResolver.OpenInputStream(Android.Net.Uri.Parse(ioc.Path));
 | 
			
		||||
		    try
 | 
			
		||||
            { 
 | 
			
		||||
		        return _ctx.ContentResolver.OpenInputStream(Android.Net.Uri.Parse(ioc.Path));
 | 
			
		||||
		    }
 | 
			
		||||
		    catch (Exception e)
 | 
			
		||||
		    {
 | 
			
		||||
		        if (e.Message.Contains("requires that you obtain access using ACTION_OPEN_DOCUMENT"))
 | 
			
		||||
		        {
 | 
			
		||||
		            //looks like permission was revoked.
 | 
			
		||||
		            throw new DocumentAccessRevokedException();
 | 
			
		||||
		        }
 | 
			
		||||
		        throw;
 | 
			
		||||
		    }
 | 
			
		||||
			
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		public IWriteTransaction OpenWriteTransaction(IOConnectionInfo ioc, bool useFileTransaction)
 | 
			
		||||
@@ -261,7 +283,26 @@ namespace keepass2android.Io
 | 
			
		||||
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	class AndroidContentWriteTransaction : IWriteTransaction
 | 
			
		||||
    public class DocumentAccessRevokedException : Exception
 | 
			
		||||
    {
 | 
			
		||||
        public DocumentAccessRevokedException()
 | 
			
		||||
        {
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        public DocumentAccessRevokedException(string message) : base(message)
 | 
			
		||||
        {
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        public DocumentAccessRevokedException(string message, Exception innerException) : base(message, innerException)
 | 
			
		||||
        {
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        protected DocumentAccessRevokedException(SerializationInfo info, StreamingContext context) : base(info, context)
 | 
			
		||||
        {
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    class AndroidContentWriteTransaction : IWriteTransaction
 | 
			
		||||
	{
 | 
			
		||||
		private readonly string _path;
 | 
			
		||||
		private readonly Context _ctx;
 | 
			
		||||
@@ -286,11 +327,15 @@ namespace keepass2android.Io
 | 
			
		||||
 | 
			
		||||
		public void CommitWrite()
 | 
			
		||||
		{
 | 
			
		||||
			using (Stream outputStream = _ctx.ContentResolver.OpenOutputStream(Android.Net.Uri.Parse(_path)))
 | 
			
		||||
		    ParcelFileDescriptor fileDescriptor = _ctx.ContentResolver.OpenFileDescriptor(Android.Net.Uri.Parse(_path), "w");
 | 
			
		||||
            
 | 
			
		||||
            using (var outputStream = new FileOutputStream(fileDescriptor.FileDescriptor))
 | 
			
		||||
			{
 | 
			
		||||
				byte[] data = _memoryStream.ToArray();
 | 
			
		||||
				outputStream.Write(data, 0, data.Length);
 | 
			
		||||
			    outputStream.Close();
 | 
			
		||||
			}
 | 
			
		||||
            fileDescriptor.Close();
 | 
			
		||||
			
 | 
			
		||||
			
 | 
			
		||||
		}
 | 
			
		||||
 
 | 
			
		||||
@@ -2,6 +2,7 @@ using System;
 | 
			
		||||
using System.Collections.Generic;
 | 
			
		||||
using System.Globalization;
 | 
			
		||||
using System.IO;
 | 
			
		||||
using System.Linq;
 | 
			
		||||
using System.Net;
 | 
			
		||||
 | 
			
		||||
using System.Security;
 | 
			
		||||
@@ -10,10 +11,14 @@ using Android.App;
 | 
			
		||||
using Android.Content;
 | 
			
		||||
using Android.Content.PM;
 | 
			
		||||
using Android.OS;
 | 
			
		||||
using Android.Preferences;
 | 
			
		||||
using Android.Support.V13.App;
 | 
			
		||||
using Android.Support.V4.App;
 | 
			
		||||
using Java.IO;
 | 
			
		||||
using Java.Util;
 | 
			
		||||
using KeePassLib.Serialization;
 | 
			
		||||
using KeePassLib.Utility;
 | 
			
		||||
 | 
			
		||||
using ActivityCompat = Android.Support.V13.App.ActivityCompat;
 | 
			
		||||
using File = System.IO.File;
 | 
			
		||||
using FileNotFoundException = System.IO.FileNotFoundException;
 | 
			
		||||
using IOException = System.IO.IOException;
 | 
			
		||||
@@ -59,7 +64,12 @@ namespace keepass2android.Io
 | 
			
		||||
 | 
			
		||||
		public abstract IEnumerable<string> SupportedProtocols { get; }
 | 
			
		||||
 | 
			
		||||
		public void Delete(IOConnectionInfo ioc)
 | 
			
		||||
	    public bool UserShouldBackup
 | 
			
		||||
	    {
 | 
			
		||||
	        get { return true; }
 | 
			
		||||
	    }
 | 
			
		||||
 | 
			
		||||
	    public void Delete(IOConnectionInfo ioc)
 | 
			
		||||
		{
 | 
			
		||||
			//todo check if directory
 | 
			
		||||
			IOConnection.DeleteFile(ioc);
 | 
			
		||||
@@ -253,10 +263,14 @@ namespace keepass2android.Io
 | 
			
		||||
 | 
			
		||||
				if (requiresPermission && (Build.VERSION.SdkInt >= BuildVersionCodes.M))
 | 
			
		||||
				{
 | 
			
		||||
					if (activity.Activity.CheckSelfPermission(Manifest.Permission.WriteExternalStorage) ==
 | 
			
		||||
					if ((activity.Activity.CheckSelfPermission(Manifest.Permission.WriteExternalStorage) ==
 | 
			
		||||
						Permission.Denied)
 | 
			
		||||
					{
 | 
			
		||||
						activity.StartFileUsageProcess(ioc, requestCode, alwaysReturnSuccess);
 | 
			
		||||
                        ||
 | 
			
		||||
					    (activity.Activity.CheckSelfPermission(Manifest.Permission.ReadExternalStorage) ==
 | 
			
		||||
					     Permission.Denied))
 | 
			
		||||
 | 
			
		||||
                    {
 | 
			
		||||
                        activity.StartFileUsageProcess(ioc, requestCode, alwaysReturnSuccess);
 | 
			
		||||
						return;
 | 
			
		||||
					}	
 | 
			
		||||
				}
 | 
			
		||||
@@ -274,7 +288,7 @@ namespace keepass2android.Io
 | 
			
		||||
 | 
			
		||||
		public void OnCreate(IFileStorageSetupActivity fileStorageSetupActivity, Bundle savedInstanceState)
 | 
			
		||||
		{
 | 
			
		||||
			((Activity)fileStorageSetupActivity).RequestPermissions(new[] { Manifest.Permission.WriteExternalStorage }, 0);
 | 
			
		||||
		    Android.Support.V4.App.ActivityCompat.RequestPermissions(((Activity)fileStorageSetupActivity), new[] { Manifest.Permission.WriteExternalStorage, Manifest.Permission.ReadExternalStorage }, 0);
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		public void OnResume(IFileStorageSetupActivity activity)
 | 
			
		||||
@@ -367,7 +381,14 @@ namespace keepass2android.Io
 | 
			
		||||
		{
 | 
			
		||||
			if (ioc.IsLocalFile())
 | 
			
		||||
			{
 | 
			
		||||
				if (IsLocalFileFlaggedReadOnly(ioc))
 | 
			
		||||
			    if (IsLocalBackup(ioc))
 | 
			
		||||
			    {
 | 
			
		||||
			        if (reason != null)
 | 
			
		||||
			            reason.Result = UiStringKey.ReadOnlyReason_LocalBackup;
 | 
			
		||||
			        return true;
 | 
			
		||||
			    }
 | 
			
		||||
 | 
			
		||||
                    if (IsLocalFileFlaggedReadOnly(ioc))
 | 
			
		||||
				{
 | 
			
		||||
					if (reason != null)
 | 
			
		||||
						reason.Result = UiStringKey.ReadOnlyReason_ReadOnlyFlag;
 | 
			
		||||
@@ -388,7 +409,22 @@ namespace keepass2android.Io
 | 
			
		||||
			return false;
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		private bool IsLocalFileFlaggedReadOnly(IOConnectionInfo ioc)
 | 
			
		||||
	    private readonly Dictionary<string, bool> _isLocalBackupCache = new Dictionary<string, bool>();
 | 
			
		||||
	    public bool IsLocalBackup(IOConnectionInfo ioc)
 | 
			
		||||
	    {
 | 
			
		||||
	        if (!ioc.IsLocalFile())
 | 
			
		||||
                return false;
 | 
			
		||||
	        bool result;
 | 
			
		||||
	        if (_isLocalBackupCache.TryGetValue(ioc.Path, out result))
 | 
			
		||||
	            return result;
 | 
			
		||||
 | 
			
		||||
	        result = (PreferenceManager.GetDefaultSharedPreferences(Application.Context)
 | 
			
		||||
	            .GetBoolean(IoUtil.GetIocPrefKey(ioc, "is_local_backup"), false));
 | 
			
		||||
	        _isLocalBackupCache[ioc.Path] = result;
 | 
			
		||||
	        return result;
 | 
			
		||||
	    }
 | 
			
		||||
 | 
			
		||||
	    private bool IsLocalFileFlaggedReadOnly(IOConnectionInfo ioc)
 | 
			
		||||
		{
 | 
			
		||||
			//see http://stackoverflow.com/a/33292700/292233
 | 
			
		||||
			try
 | 
			
		||||
@@ -412,7 +448,7 @@ namespace keepass2android.Io
 | 
			
		||||
		public void OnRequestPermissionsResult(IFileStorageSetupActivity fileStorageSetupActivity, int requestCode,
 | 
			
		||||
			string[] permissions, Permission[] grantResults)
 | 
			
		||||
		{
 | 
			
		||||
			fileStorageSetupActivity.State.PutBoolean(PermissionGrantedKey, grantResults[0] == Permission.Granted);
 | 
			
		||||
			fileStorageSetupActivity.State.PutBoolean(PermissionGrantedKey, grantResults.All(res => res == Permission.Granted));
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -84,7 +84,12 @@ namespace keepass2android.Io
 | 
			
		||||
 | 
			
		||||
		public IEnumerable<string> SupportedProtocols { get { return _cachedStorage.SupportedProtocols; } }
 | 
			
		||||
 | 
			
		||||
		public void DeleteFile(IOConnectionInfo ioc)
 | 
			
		||||
	    public bool UserShouldBackup
 | 
			
		||||
	    {
 | 
			
		||||
	        get { return _cachedStorage.UserShouldBackup; }
 | 
			
		||||
	    }
 | 
			
		||||
 | 
			
		||||
	    public void DeleteFile(IOConnectionInfo ioc)
 | 
			
		||||
		{
 | 
			
		||||
			if (IsCached(ioc))
 | 
			
		||||
			{
 | 
			
		||||
 
 | 
			
		||||
@@ -10,7 +10,11 @@ namespace keepass2android.Io
 | 
			
		||||
		{
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		
 | 
			
		||||
 | 
			
		||||
	    public override bool UserShouldBackup
 | 
			
		||||
	    {
 | 
			
		||||
	        get { return false; }
 | 
			
		||||
	    }
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	public partial class DropboxAppFolderFileStorage: JavaFileStorage
 | 
			
		||||
@@ -20,8 +24,12 @@ namespace keepass2android.Io
 | 
			
		||||
		{
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		
 | 
			
		||||
	}
 | 
			
		||||
	    public override bool UserShouldBackup
 | 
			
		||||
	    {
 | 
			
		||||
	        get { return false; }
 | 
			
		||||
	    }
 | 
			
		||||
 | 
			
		||||
    }
 | 
			
		||||
	
 | 
			
		||||
}
 | 
			
		||||
#endif
 | 
			
		||||
@@ -22,6 +22,10 @@ namespace keepass2android.Io
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
	    public override bool UserShouldBackup
 | 
			
		||||
	    {
 | 
			
		||||
	        get { return false; }
 | 
			
		||||
	    }
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
#endif
 | 
			
		||||
@@ -46,9 +46,14 @@ namespace keepass2android.Io
 | 
			
		||||
		/// <summary>
 | 
			
		||||
		/// returns the protocol ids supported by this FileStorage. Can return pseudo-protocols like "dropbox" or real protocols like "ftp"
 | 
			
		||||
		/// </summary>
 | 
			
		||||
		IEnumerable<string> SupportedProtocols { get; } 
 | 
			
		||||
		IEnumerable<string> SupportedProtocols { get; }
 | 
			
		||||
 | 
			
		||||
		/// <summary>
 | 
			
		||||
        /// <summary>
 | 
			
		||||
        /// returns true if users should backup files on this file storage (if the file is important). Can be false for cloud providers with built-in versioning or backups.
 | 
			
		||||
        /// </summary>
 | 
			
		||||
	    bool UserShouldBackup { get; }
 | 
			
		||||
 | 
			
		||||
	    /// <summary>
 | 
			
		||||
		/// Deletes the given file or directory.
 | 
			
		||||
		/// </summary>
 | 
			
		||||
		void Delete(IOConnectionInfo ioc);
 | 
			
		||||
 
 | 
			
		||||
@@ -1,10 +1,12 @@
 | 
			
		||||
using System;
 | 
			
		||||
using System.Collections.Generic;
 | 
			
		||||
using System.Security.Cryptography;
 | 
			
		||||
using System.Text;
 | 
			
		||||
using Android.Content;
 | 
			
		||||
using Android.OS;
 | 
			
		||||
using Java.IO;
 | 
			
		||||
using KeePassLib.Serialization;
 | 
			
		||||
using KeePassLib.Utility;
 | 
			
		||||
 | 
			
		||||
namespace keepass2android.Io
 | 
			
		||||
{
 | 
			
		||||
@@ -125,5 +127,53 @@ namespace keepass2android.Io
 | 
			
		||||
				return ctx.FilesDir;
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
	}
 | 
			
		||||
        //creates a local ioc where the sourceIoc can be stored to
 | 
			
		||||
	    public static IOConnectionInfo GetInternalIoc(IOConnectionInfo sourceIoc, Context ctx)
 | 
			
		||||
	    {
 | 
			
		||||
	        Java.IO.File internalDirectory = IoUtil.GetInternalDirectory(ctx);
 | 
			
		||||
	        string targetPath = UrlUtil.GetFileName(sourceIoc.Path);
 | 
			
		||||
	        targetPath = targetPath.Trim("|\\?*<\":>+[]/'".ToCharArray());
 | 
			
		||||
	        if (targetPath == "")
 | 
			
		||||
	            targetPath = "internal";
 | 
			
		||||
	        if (new File(internalDirectory, targetPath).Exists())
 | 
			
		||||
	        {
 | 
			
		||||
	            int c = 1;
 | 
			
		||||
	            var ext = UrlUtil.GetExtension(targetPath);
 | 
			
		||||
	            var filenameWithoutExt = UrlUtil.StripExtension(targetPath);
 | 
			
		||||
	            do
 | 
			
		||||
	            {
 | 
			
		||||
	                c++;
 | 
			
		||||
	                targetPath = filenameWithoutExt + c;
 | 
			
		||||
	                if (!String.IsNullOrEmpty(ext))
 | 
			
		||||
	                    targetPath += "." + ext;
 | 
			
		||||
	            } while (new File(internalDirectory, targetPath).Exists());
 | 
			
		||||
	        }
 | 
			
		||||
	        return IOConnectionInfo.FromPath(new File(internalDirectory, targetPath).CanonicalPath);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
	    public static IOConnectionInfo ImportFileToInternalDirectory(IOConnectionInfo sourceIoc, Context ctx, IKp2aApp app)
 | 
			
		||||
	    {
 | 
			
		||||
	        var targetIoc = GetInternalIoc(sourceIoc, ctx);
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
            IoUtil.Copy(targetIoc, sourceIoc, app);
 | 
			
		||||
	        return targetIoc;
 | 
			
		||||
	    }
 | 
			
		||||
 | 
			
		||||
	    public static string GetIocPrefKey(IOConnectionInfo ioc, string suffix)
 | 
			
		||||
	    {
 | 
			
		||||
	        var iocAsHexString = IocAsHexString(ioc);
 | 
			
		||||
 | 
			
		||||
	        return "kp2a_ioc_key_" + iocAsHexString + suffix;
 | 
			
		||||
	    }
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
	    public static string IocAsHexString(IOConnectionInfo ioc)
 | 
			
		||||
	    {
 | 
			
		||||
	        SHA256Managed sha256 = new SHA256Managed();
 | 
			
		||||
	        string iocAsHexString =
 | 
			
		||||
	            MemUtil.ByteArrayToHexString(sha256.ComputeHash(Encoding.Unicode.GetBytes(ioc.Path.ToCharArray())));
 | 
			
		||||
	        return iocAsHexString;
 | 
			
		||||
	    }
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -22,9 +22,10 @@ namespace keepass2android.Io
 | 
			
		||||
		protected string Protocol { get { return _jfs.ProtocolId; } }
 | 
			
		||||
 | 
			
		||||
		public virtual IEnumerable<string> SupportedProtocols { get { yield return Protocol; } }
 | 
			
		||||
	    public abstract bool UserShouldBackup { get; }
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
		private readonly IJavaFileStorage _jfs;
 | 
			
		||||
	    private readonly IJavaFileStorage _jfs;
 | 
			
		||||
		private readonly IKp2aApp _app;
 | 
			
		||||
 | 
			
		||||
		public JavaFileStorage(IJavaFileStorage jfs, IKp2aApp app)
 | 
			
		||||
 
 | 
			
		||||
@@ -161,7 +161,12 @@ namespace keepass2android.Io
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		public void Delete(IOConnectionInfo ioc)
 | 
			
		||||
	    public bool UserShouldBackup
 | 
			
		||||
	    {
 | 
			
		||||
	        get { return true; }
 | 
			
		||||
	    }
 | 
			
		||||
 | 
			
		||||
	    public void Delete(IOConnectionInfo ioc)
 | 
			
		||||
		{
 | 
			
		||||
			try
 | 
			
		||||
			{
 | 
			
		||||
@@ -226,7 +231,7 @@ namespace keepass2android.Io
 | 
			
		||||
 | 
			
		||||
		
 | 
			
		||||
 | 
			
		||||
		internal Uri IocToUri(IOConnectionInfo ioc)
 | 
			
		||||
		public static Uri IocToUri(IOConnectionInfo ioc)
 | 
			
		||||
		{
 | 
			
		||||
			if (!string.IsNullOrEmpty(ioc.UserName))
 | 
			
		||||
			{
 | 
			
		||||
@@ -570,7 +575,7 @@ namespace keepass2android.Io
 | 
			
		||||
			{
 | 
			
		||||
 | 
			
		||||
				_client = _fileStorage.GetClient(_ioc, false);
 | 
			
		||||
				_stream = _client.OpenWrite(_fileStorage.IocToUri(_iocTemp).PathAndQuery);
 | 
			
		||||
				_stream = _client.OpenWrite(NetFtpFileStorage.IocToUri(_iocTemp).PathAndQuery);
 | 
			
		||||
				return _stream;
 | 
			
		||||
			}
 | 
			
		||||
			catch (FtpCommandException ex)
 | 
			
		||||
@@ -590,8 +595,8 @@ namespace keepass2android.Io
 | 
			
		||||
				//make sure target file does not exist:
 | 
			
		||||
				//try
 | 
			
		||||
				{
 | 
			
		||||
					if (_client.FileExists(_fileStorage.IocToUri(_ioc).PathAndQuery))
 | 
			
		||||
						_client.DeleteFile(_fileStorage.IocToUri(_ioc).PathAndQuery);
 | 
			
		||||
					if (_client.FileExists(NetFtpFileStorage.IocToUri(_ioc).PathAndQuery))
 | 
			
		||||
						_client.DeleteFile(NetFtpFileStorage.IocToUri(_ioc).PathAndQuery);
 | 
			
		||||
 | 
			
		||||
				}
 | 
			
		||||
				//catch (FtpCommandException)
 | 
			
		||||
@@ -599,8 +604,8 @@ namespace keepass2android.Io
 | 
			
		||||
					//TODO get a new clien? might be stale
 | 
			
		||||
				}
 | 
			
		||||
 | 
			
		||||
				_client.Rename(_fileStorage.IocToUri(_iocTemp).PathAndQuery,
 | 
			
		||||
					_fileStorage.IocToUri(_ioc).PathAndQuery);
 | 
			
		||||
				_client.Rename(NetFtpFileStorage.IocToUri(_iocTemp).PathAndQuery,
 | 
			
		||||
				    NetFtpFileStorage.IocToUri(_ioc).PathAndQuery);
 | 
			
		||||
				
 | 
			
		||||
			}
 | 
			
		||||
			catch (FtpCommandException ex)
 | 
			
		||||
 
 | 
			
		||||
@@ -32,7 +32,12 @@ namespace keepass2android.Io
 | 
			
		||||
			get { return _baseStorage.SupportedProtocols; }
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		public void Delete(IOConnectionInfo ioc)
 | 
			
		||||
	    public bool UserShouldBackup
 | 
			
		||||
	    {
 | 
			
		||||
	        get { return _baseStorage.UserShouldBackup; }
 | 
			
		||||
	    }
 | 
			
		||||
 | 
			
		||||
	    public void Delete(IOConnectionInfo ioc)
 | 
			
		||||
		{
 | 
			
		||||
			_baseStorage.Delete(ioc);
 | 
			
		||||
		}
 | 
			
		||||
 
 | 
			
		||||
@@ -33,6 +33,11 @@ namespace keepass2android.Io
 | 
			
		||||
				yield return "onedrive";
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
	    public override bool UserShouldBackup
 | 
			
		||||
	    {
 | 
			
		||||
	        get { return false; }
 | 
			
		||||
	    }
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
#endif
 | 
			
		||||
@@ -10,7 +10,11 @@ namespace keepass2android.Io
 | 
			
		||||
		{
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		
 | 
			
		||||
 | 
			
		||||
	    public override bool UserShouldBackup
 | 
			
		||||
	    {
 | 
			
		||||
	        get { return true; }
 | 
			
		||||
	    }
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	
 | 
			
		||||
 
 | 
			
		||||
@@ -33,7 +33,12 @@ namespace keepass2android.Io
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		public static string Owncloud2Webdav(string owncloudUrl)
 | 
			
		||||
	    public override bool UserShouldBackup
 | 
			
		||||
	    {
 | 
			
		||||
	        get { return true; }
 | 
			
		||||
	    }
 | 
			
		||||
 | 
			
		||||
	    public static string Owncloud2Webdav(string owncloudUrl)
 | 
			
		||||
		{
 | 
			
		||||
			string owncloudPrefix = "owncloud://";
 | 
			
		||||
			if (owncloudUrl.StartsWith(owncloudPrefix))
 | 
			
		||||
 
 | 
			
		||||
@@ -12,9 +12,10 @@
 | 
			
		||||
    <FileAlignment>512</FileAlignment>
 | 
			
		||||
    <AndroidResgenFile>Resources\Resource.Designer.cs</AndroidResgenFile>
 | 
			
		||||
    <GenerateSerializationAssemblies>Off</GenerateSerializationAssemblies>
 | 
			
		||||
    <TargetFrameworkVersion>v8.0</TargetFrameworkVersion>
 | 
			
		||||
    <TargetFrameworkVersion>v8.1</TargetFrameworkVersion>
 | 
			
		||||
    <AndroidUseLatestPlatformSdk>true</AndroidUseLatestPlatformSdk>
 | 
			
		||||
    <NuGetPackageImportStamp>06ffb71c</NuGetPackageImportStamp>
 | 
			
		||||
    <NuGetPackageImportStamp>
 | 
			
		||||
    </NuGetPackageImportStamp>
 | 
			
		||||
  </PropertyGroup>
 | 
			
		||||
  <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
 | 
			
		||||
    <DebugSymbols>true</DebugSymbols>
 | 
			
		||||
@@ -30,7 +31,7 @@
 | 
			
		||||
    <DebugType>pdbonly</DebugType>
 | 
			
		||||
    <Optimize>true</Optimize>
 | 
			
		||||
    <OutputPath>bin\Release\</OutputPath>
 | 
			
		||||
    <DefineConstants>TRACE</DefineConstants>
 | 
			
		||||
    <DefineConstants>TRACE;NoNet;EXCLUDE_JAVAFILESTORAGE</DefineConstants>
 | 
			
		||||
    <ErrorReport>prompt</ErrorReport>
 | 
			
		||||
    <WarningLevel>4</WarningLevel>
 | 
			
		||||
    <AndroidUseSharedRuntime>false</AndroidUseSharedRuntime>
 | 
			
		||||
@@ -52,9 +53,38 @@
 | 
			
		||||
    <Reference Include="mscorlib" />
 | 
			
		||||
    <Reference Include="System" />
 | 
			
		||||
    <Reference Include="System.Core" />
 | 
			
		||||
    <Reference Include="System.Net.Http" />
 | 
			
		||||
    <Reference Include="System.Xml.Linq" />
 | 
			
		||||
    <Reference Include="System.Xml" />
 | 
			
		||||
    <Reference Include="Xamarin.Android.Arch.Core.Common, Version=1.0.0.0, Culture=neutral, processorArchitecture=MSIL">
 | 
			
		||||
      <HintPath>..\packages\Xamarin.Android.Arch.Core.Common.1.0.0\lib\MonoAndroid80\Xamarin.Android.Arch.Core.Common.dll</HintPath>
 | 
			
		||||
    </Reference>
 | 
			
		||||
    <Reference Include="Xamarin.Android.Arch.Lifecycle.Common, Version=1.0.0.0, Culture=neutral, processorArchitecture=MSIL">
 | 
			
		||||
      <HintPath>..\packages\Xamarin.Android.Arch.Lifecycle.Common.1.0.1\lib\MonoAndroid80\Xamarin.Android.Arch.Lifecycle.Common.dll</HintPath>
 | 
			
		||||
    </Reference>
 | 
			
		||||
    <Reference Include="Xamarin.Android.Arch.Lifecycle.Runtime, Version=1.0.0.0, Culture=neutral, processorArchitecture=MSIL">
 | 
			
		||||
      <HintPath>..\packages\Xamarin.Android.Arch.Lifecycle.Runtime.1.0.0\lib\MonoAndroid80\Xamarin.Android.Arch.Lifecycle.Runtime.dll</HintPath>
 | 
			
		||||
    </Reference>
 | 
			
		||||
    <Reference Include="Xamarin.Android.Support.Annotations, Version=1.0.0.0, Culture=neutral, processorArchitecture=MSIL">
 | 
			
		||||
      <HintPath>..\packages\Xamarin.Android.Support.Annotations.26.1.0.1\lib\MonoAndroid80\Xamarin.Android.Support.Annotations.dll</HintPath>
 | 
			
		||||
    </Reference>
 | 
			
		||||
    <Reference Include="Xamarin.Android.Support.Compat, Version=1.0.0.0, Culture=neutral, processorArchitecture=MSIL">
 | 
			
		||||
      <HintPath>..\packages\Xamarin.Android.Support.Compat.26.1.0.1\lib\MonoAndroid80\Xamarin.Android.Support.Compat.dll</HintPath>
 | 
			
		||||
    </Reference>
 | 
			
		||||
    <Reference Include="Xamarin.Android.Support.Core.UI, Version=1.0.0.0, Culture=neutral, processorArchitecture=MSIL">
 | 
			
		||||
      <HintPath>..\packages\Xamarin.Android.Support.Core.UI.26.1.0.1\lib\MonoAndroid80\Xamarin.Android.Support.Core.UI.dll</HintPath>
 | 
			
		||||
    </Reference>
 | 
			
		||||
    <Reference Include="Xamarin.Android.Support.Core.Utils, Version=1.0.0.0, Culture=neutral, processorArchitecture=MSIL">
 | 
			
		||||
      <HintPath>..\packages\Xamarin.Android.Support.Core.Utils.26.1.0.1\lib\MonoAndroid80\Xamarin.Android.Support.Core.Utils.dll</HintPath>
 | 
			
		||||
    </Reference>
 | 
			
		||||
    <Reference Include="Xamarin.Android.Support.Fragment, Version=1.0.0.0, Culture=neutral, processorArchitecture=MSIL">
 | 
			
		||||
      <HintPath>..\packages\Xamarin.Android.Support.Fragment.26.1.0.1\lib\MonoAndroid80\Xamarin.Android.Support.Fragment.dll</HintPath>
 | 
			
		||||
    </Reference>
 | 
			
		||||
    <Reference Include="Xamarin.Android.Support.Media.Compat, Version=1.0.0.0, Culture=neutral, processorArchitecture=MSIL">
 | 
			
		||||
      <HintPath>..\packages\Xamarin.Android.Support.Media.Compat.26.1.0.1\lib\MonoAndroid80\Xamarin.Android.Support.Media.Compat.dll</HintPath>
 | 
			
		||||
    </Reference>
 | 
			
		||||
    <Reference Include="Xamarin.Android.Support.v13, Version=1.0.0.0, Culture=neutral, processorArchitecture=MSIL">
 | 
			
		||||
      <HintPath>..\packages\Xamarin.Android.Support.v13.26.1.0.1\lib\MonoAndroid80\Xamarin.Android.Support.v13.dll</HintPath>
 | 
			
		||||
    </Reference>
 | 
			
		||||
  </ItemGroup>
 | 
			
		||||
  <ItemGroup>
 | 
			
		||||
    <Compile Include="database\CheckDatabaseForChanges.cs" />
 | 
			
		||||
@@ -75,20 +105,12 @@
 | 
			
		||||
    <Compile Include="Io\AndroidContentStorage.cs" />
 | 
			
		||||
    <Compile Include="Io\BuiltInFileStorage.cs" />
 | 
			
		||||
    <Compile Include="Io\CachingFileStorage.cs" />
 | 
			
		||||
    <Compile Include="Io\DropboxFileStorage.cs" />
 | 
			
		||||
    <Compile Include="Io\DropboxFileStorageKeys.cs" />
 | 
			
		||||
    <Compile Include="Io\FileDescription.cs" />
 | 
			
		||||
    <Compile Include="Io\FileStorageSetupActivity.cs" />
 | 
			
		||||
    <Compile Include="Io\FileStorageSetupInitiatorActivity.cs" />
 | 
			
		||||
    <Compile Include="Io\GDriveFileStorage.cs" />
 | 
			
		||||
    <Compile Include="Io\IFileStorage.cs" />
 | 
			
		||||
    <Compile Include="Io\IoUtil.cs" />
 | 
			
		||||
    <Compile Include="Io\JavaFileStorage.cs" />
 | 
			
		||||
    <Compile Include="Io\NetFtpFileStorage.cs" />
 | 
			
		||||
    <Compile Include="Io\OfflineSwitchableFileStorage.cs" />
 | 
			
		||||
    <Compile Include="Io\SftpFileStorage.cs" />
 | 
			
		||||
    <Compile Include="Io\OneDriveFileStorage.cs" />
 | 
			
		||||
    <Compile Include="Io\WebDavFileStorage.cs" />
 | 
			
		||||
    <Compile Include="IProgressDialog.cs" />
 | 
			
		||||
    <Compile Include="PreferenceKey.cs" />
 | 
			
		||||
    <Compile Include="SelectStorageLocationActivityBase.cs" />
 | 
			
		||||
@@ -124,10 +146,6 @@
 | 
			
		||||
    <Compile Include="Utils\Spr\SprEngine.PickChars.cs" />
 | 
			
		||||
  </ItemGroup>
 | 
			
		||||
  <ItemGroup>
 | 
			
		||||
    <ProjectReference Include="..\JavaFileStorageBindings\JavaFileStorageBindings.csproj">
 | 
			
		||||
      <Project>{48574278-4779-4b3a-a9e4-9cf1bc285d0b}</Project>
 | 
			
		||||
      <Name>JavaFileStorageBindings</Name>
 | 
			
		||||
    </ProjectReference>
 | 
			
		||||
    <ProjectReference Include="..\KeePassLib2Android\KeePassLib2Android.csproj">
 | 
			
		||||
      <Project>{545B4A6B-8BBA-4FBE-92FC-4AC060122A54}</Project>
 | 
			
		||||
      <Name>KeePassLib2Android</Name>
 | 
			
		||||
@@ -136,10 +154,6 @@
 | 
			
		||||
      <Project>{70D3844A-D9FA-4A64-B205-A84C6A822196}</Project>
 | 
			
		||||
      <Name>KP2AKdbLibraryBinding</Name>
 | 
			
		||||
    </ProjectReference>
 | 
			
		||||
    <ProjectReference Include="..\netftpandroid\System.Net.FtpClient\System.Net.FtpClient.Android.csproj">
 | 
			
		||||
      <Project>{146FD497-BA03-4740-B6C5-5C84EA8FCDE2}</Project>
 | 
			
		||||
      <Name>System.Net.FtpClient.Android</Name>
 | 
			
		||||
    </ProjectReference>
 | 
			
		||||
    <ProjectReference Include="..\TwofishCipher\TwofishCipher.csproj">
 | 
			
		||||
      <Project>{5CF675A5-9BEE-4720-BED9-D5BF14A2EBF9}</Project>
 | 
			
		||||
      <Name>TwofishCipher</Name>
 | 
			
		||||
@@ -148,7 +162,35 @@
 | 
			
		||||
  <ItemGroup>
 | 
			
		||||
    <Folder Include="Resources\" />
 | 
			
		||||
  </ItemGroup>
 | 
			
		||||
  <ItemGroup>
 | 
			
		||||
    <None Include="packages.config" />
 | 
			
		||||
  </ItemGroup>
 | 
			
		||||
  <Import Project="$(MSBuildExtensionsPath)\Xamarin\Android\Xamarin.Android.CSharp.targets" />
 | 
			
		||||
  <Import Project="..\packages\Xamarin.Android.Support.Annotations.26.1.0.1\build\MonoAndroid80\Xamarin.Android.Support.Annotations.targets" Condition="Exists('..\packages\Xamarin.Android.Support.Annotations.26.1.0.1\build\MonoAndroid80\Xamarin.Android.Support.Annotations.targets')" />
 | 
			
		||||
  <Target Name="EnsureNuGetPackageBuildImports" BeforeTargets="PrepareForBuild">
 | 
			
		||||
    <PropertyGroup>
 | 
			
		||||
      <ErrorText>Dieses Projekt verweist auf mindestens ein NuGet-Paket, das auf diesem Computer fehlt. Verwenden Sie die Wiederherstellung von NuGet-Paketen, um die fehlenden Dateien herunterzuladen. Weitere Informationen finden Sie unter "http://go.microsoft.com/fwlink/?LinkID=322105". Die fehlende Datei ist "{0}".</ErrorText>
 | 
			
		||||
    </PropertyGroup>
 | 
			
		||||
    <Error Condition="!Exists('..\packages\Xamarin.Android.Support.Annotations.26.1.0.1\build\MonoAndroid80\Xamarin.Android.Support.Annotations.targets')" Text="$([System.String]::Format('$(ErrorText)', '..\packages\Xamarin.Android.Support.Annotations.26.1.0.1\build\MonoAndroid80\Xamarin.Android.Support.Annotations.targets'))" />
 | 
			
		||||
    <Error Condition="!Exists('..\packages\Xamarin.Android.Arch.Core.Common.1.0.0\build\MonoAndroid80\Xamarin.Android.Arch.Core.Common.targets')" Text="$([System.String]::Format('$(ErrorText)', '..\packages\Xamarin.Android.Arch.Core.Common.1.0.0\build\MonoAndroid80\Xamarin.Android.Arch.Core.Common.targets'))" />
 | 
			
		||||
    <Error Condition="!Exists('..\packages\Xamarin.Android.Arch.Lifecycle.Common.1.0.1\build\MonoAndroid80\Xamarin.Android.Arch.Lifecycle.Common.targets')" Text="$([System.String]::Format('$(ErrorText)', '..\packages\Xamarin.Android.Arch.Lifecycle.Common.1.0.1\build\MonoAndroid80\Xamarin.Android.Arch.Lifecycle.Common.targets'))" />
 | 
			
		||||
    <Error Condition="!Exists('..\packages\Xamarin.Android.Arch.Lifecycle.Runtime.1.0.0\build\MonoAndroid80\Xamarin.Android.Arch.Lifecycle.Runtime.targets')" Text="$([System.String]::Format('$(ErrorText)', '..\packages\Xamarin.Android.Arch.Lifecycle.Runtime.1.0.0\build\MonoAndroid80\Xamarin.Android.Arch.Lifecycle.Runtime.targets'))" />
 | 
			
		||||
    <Error Condition="!Exists('..\packages\Xamarin.Android.Support.Compat.26.1.0.1\build\MonoAndroid80\Xamarin.Android.Support.Compat.targets')" Text="$([System.String]::Format('$(ErrorText)', '..\packages\Xamarin.Android.Support.Compat.26.1.0.1\build\MonoAndroid80\Xamarin.Android.Support.Compat.targets'))" />
 | 
			
		||||
    <Error Condition="!Exists('..\packages\Xamarin.Android.Support.Core.UI.26.1.0.1\build\MonoAndroid80\Xamarin.Android.Support.Core.UI.targets')" Text="$([System.String]::Format('$(ErrorText)', '..\packages\Xamarin.Android.Support.Core.UI.26.1.0.1\build\MonoAndroid80\Xamarin.Android.Support.Core.UI.targets'))" />
 | 
			
		||||
    <Error Condition="!Exists('..\packages\Xamarin.Android.Support.Core.Utils.26.1.0.1\build\MonoAndroid80\Xamarin.Android.Support.Core.Utils.targets')" Text="$([System.String]::Format('$(ErrorText)', '..\packages\Xamarin.Android.Support.Core.Utils.26.1.0.1\build\MonoAndroid80\Xamarin.Android.Support.Core.Utils.targets'))" />
 | 
			
		||||
    <Error Condition="!Exists('..\packages\Xamarin.Android.Support.Fragment.26.1.0.1\build\MonoAndroid80\Xamarin.Android.Support.Fragment.targets')" Text="$([System.String]::Format('$(ErrorText)', '..\packages\Xamarin.Android.Support.Fragment.26.1.0.1\build\MonoAndroid80\Xamarin.Android.Support.Fragment.targets'))" />
 | 
			
		||||
    <Error Condition="!Exists('..\packages\Xamarin.Android.Support.Media.Compat.26.1.0.1\build\MonoAndroid80\Xamarin.Android.Support.Media.Compat.targets')" Text="$([System.String]::Format('$(ErrorText)', '..\packages\Xamarin.Android.Support.Media.Compat.26.1.0.1\build\MonoAndroid80\Xamarin.Android.Support.Media.Compat.targets'))" />
 | 
			
		||||
    <Error Condition="!Exists('..\packages\Xamarin.Android.Support.v13.26.1.0.1\build\MonoAndroid80\Xamarin.Android.Support.v13.targets')" Text="$([System.String]::Format('$(ErrorText)', '..\packages\Xamarin.Android.Support.v13.26.1.0.1\build\MonoAndroid80\Xamarin.Android.Support.v13.targets'))" />
 | 
			
		||||
  </Target>
 | 
			
		||||
  <Import Project="..\packages\Xamarin.Android.Arch.Core.Common.1.0.0\build\MonoAndroid80\Xamarin.Android.Arch.Core.Common.targets" Condition="Exists('..\packages\Xamarin.Android.Arch.Core.Common.1.0.0\build\MonoAndroid80\Xamarin.Android.Arch.Core.Common.targets')" />
 | 
			
		||||
  <Import Project="..\packages\Xamarin.Android.Arch.Lifecycle.Common.1.0.1\build\MonoAndroid80\Xamarin.Android.Arch.Lifecycle.Common.targets" Condition="Exists('..\packages\Xamarin.Android.Arch.Lifecycle.Common.1.0.1\build\MonoAndroid80\Xamarin.Android.Arch.Lifecycle.Common.targets')" />
 | 
			
		||||
  <Import Project="..\packages\Xamarin.Android.Arch.Lifecycle.Runtime.1.0.0\build\MonoAndroid80\Xamarin.Android.Arch.Lifecycle.Runtime.targets" Condition="Exists('..\packages\Xamarin.Android.Arch.Lifecycle.Runtime.1.0.0\build\MonoAndroid80\Xamarin.Android.Arch.Lifecycle.Runtime.targets')" />
 | 
			
		||||
  <Import Project="..\packages\Xamarin.Android.Support.Compat.26.1.0.1\build\MonoAndroid80\Xamarin.Android.Support.Compat.targets" Condition="Exists('..\packages\Xamarin.Android.Support.Compat.26.1.0.1\build\MonoAndroid80\Xamarin.Android.Support.Compat.targets')" />
 | 
			
		||||
  <Import Project="..\packages\Xamarin.Android.Support.Core.UI.26.1.0.1\build\MonoAndroid80\Xamarin.Android.Support.Core.UI.targets" Condition="Exists('..\packages\Xamarin.Android.Support.Core.UI.26.1.0.1\build\MonoAndroid80\Xamarin.Android.Support.Core.UI.targets')" />
 | 
			
		||||
  <Import Project="..\packages\Xamarin.Android.Support.Core.Utils.26.1.0.1\build\MonoAndroid80\Xamarin.Android.Support.Core.Utils.targets" Condition="Exists('..\packages\Xamarin.Android.Support.Core.Utils.26.1.0.1\build\MonoAndroid80\Xamarin.Android.Support.Core.Utils.targets')" />
 | 
			
		||||
  <Import Project="..\packages\Xamarin.Android.Support.Fragment.26.1.0.1\build\MonoAndroid80\Xamarin.Android.Support.Fragment.targets" Condition="Exists('..\packages\Xamarin.Android.Support.Fragment.26.1.0.1\build\MonoAndroid80\Xamarin.Android.Support.Fragment.targets')" />
 | 
			
		||||
  <Import Project="..\packages\Xamarin.Android.Support.Media.Compat.26.1.0.1\build\MonoAndroid80\Xamarin.Android.Support.Media.Compat.targets" Condition="Exists('..\packages\Xamarin.Android.Support.Media.Compat.26.1.0.1\build\MonoAndroid80\Xamarin.Android.Support.Media.Compat.targets')" />
 | 
			
		||||
  <Import Project="..\packages\Xamarin.Android.Support.v13.26.1.0.1\build\MonoAndroid80\Xamarin.Android.Support.v13.targets" Condition="Exists('..\packages\Xamarin.Android.Support.v13.26.1.0.1\build\MonoAndroid80\Xamarin.Android.Support.v13.targets')" />
 | 
			
		||||
  <!-- To modify your build process, add your task inside one of the targets below and uncomment it. 
 | 
			
		||||
       Other similar extension points exist, see Microsoft.Common.targets.
 | 
			
		||||
  <Target Name="BeforeBuild">
 | 
			
		||||
 
 | 
			
		||||
@@ -63,7 +63,8 @@ namespace keepass2android
 | 
			
		||||
		AskDeletePermanentlyItems,
 | 
			
		||||
		AskDeletePermanentlyItemsNoRecycle,
 | 
			
		||||
		InOfflineMode,
 | 
			
		||||
		DuplicateTitle,
 | 
			
		||||
        DocumentAccessRevoked,
 | 
			
		||||
        DuplicateTitle,
 | 
			
		||||
		TemplateTitle_IdCard,
 | 
			
		||||
		TemplateField_IdCard_Name,
 | 
			
		||||
		TemplateField_IdCard_PlaceOfIssue,
 | 
			
		||||
@@ -84,6 +85,7 @@ namespace keepass2android
 | 
			
		||||
		AskAddTemplatesMessage,
 | 
			
		||||
		ReadOnlyReason_PreKitKat,
 | 
			
		||||
		ReadOnlyReason_ReadOnlyFlag,
 | 
			
		||||
		ReadOnlyReason_ReadOnlyKitKat
 | 
			
		||||
		ReadOnlyReason_ReadOnlyKitKat,
 | 
			
		||||
        ReadOnlyReason_LocalBackup
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -152,27 +152,20 @@ namespace keepass2android
 | 
			
		||||
			set { _databaseFormat = value; }
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		public static string GetFingerprintPrefKey(IOConnectionInfo ioc)
 | 
			
		||||
		{
 | 
			
		||||
			var iocAsHexString = IocAsHexString(ioc);
 | 
			
		||||
	    public string IocAsHexString()
 | 
			
		||||
	    {
 | 
			
		||||
	        return IoUtil.IocAsHexString(Ioc);
 | 
			
		||||
	    }
 | 
			
		||||
 | 
			
		||||
			return "kp2a_ioc_" + iocAsHexString;
 | 
			
		||||
		}
 | 
			
		||||
        public static string GetFingerprintPrefKey(IOConnectionInfo ioc)
 | 
			
		||||
	    {
 | 
			
		||||
	        var iocAsHexString = IoUtil.IocAsHexString(ioc);
 | 
			
		||||
 | 
			
		||||
		public string IocAsHexString()
 | 
			
		||||
		{
 | 
			
		||||
			return IocAsHexString(Ioc);
 | 
			
		||||
		}
 | 
			
		||||
	        return "kp2a_ioc_" + iocAsHexString;
 | 
			
		||||
	    }
 | 
			
		||||
 | 
			
		||||
		private static string IocAsHexString(IOConnectionInfo ioc)
 | 
			
		||||
		{
 | 
			
		||||
			SHA256Managed sha256 = new SHA256Managed();
 | 
			
		||||
			string iocAsHexString =
 | 
			
		||||
				MemUtil.ByteArrayToHexString(sha256.ComputeHash(Encoding.Unicode.GetBytes(ioc.Path.ToCharArray())));
 | 
			
		||||
			return iocAsHexString;
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		public static string GetFingerprintModePrefKey(IOConnectionInfo ioc)
 | 
			
		||||
        public static string GetFingerprintModePrefKey(IOConnectionInfo ioc)
 | 
			
		||||
		{
 | 
			
		||||
			return GetFingerprintPrefKey(ioc) + "_mode";
 | 
			
		||||
		}
 | 
			
		||||
 
 | 
			
		||||
@@ -18,6 +18,7 @@ This file is part of Keepass2Android, Copyright 2013 Philipp Crocoll. This file
 | 
			
		||||
using System;
 | 
			
		||||
using System.IO;
 | 
			
		||||
using System.Linq;
 | 
			
		||||
using System.Threading;
 | 
			
		||||
using System.Threading.Tasks;
 | 
			
		||||
using KeePassLib;
 | 
			
		||||
using KeePassLib.Keys;
 | 
			
		||||
@@ -53,9 +54,11 @@ namespace keepass2android
 | 
			
		||||
			{
 | 
			
		||||
				try
 | 
			
		||||
				{
 | 
			
		||||
                    //make sure the file data is stored in the recent files list even if loading fails
 | 
			
		||||
				    SaveFileData(_ioc, _keyfileOrProvider);
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
					StatusLogger.UpdateMessage(UiStringKey.loading_database);
 | 
			
		||||
                    StatusLogger.UpdateMessage(UiStringKey.loading_database);
 | 
			
		||||
					//get the stream data into a single stream variable (databaseStream) regardless whether its preloaded or not:
 | 
			
		||||
					MemoryStream preloadedMemoryStream = _databaseData == null ? null : _databaseData.Result;
 | 
			
		||||
					MemoryStream databaseStream;
 | 
			
		||||
@@ -134,10 +137,14 @@ namespace keepass2android
 | 
			
		||||
			//now let's go:
 | 
			
		||||
			try
 | 
			
		||||
			{
 | 
			
		||||
				_app.LoadDatabase(_ioc, workingCopy, _compositeKey, StatusLogger, _format);
 | 
			
		||||
				SaveFileData(_ioc, _keyfileOrProvider);
 | 
			
		||||
                _app.LoadDatabase(_ioc, workingCopy, _compositeKey, StatusLogger, _format);
 | 
			
		||||
				Kp2aLog.Log("LoadDB OK");
 | 
			
		||||
				Finish(true, _format.SuccessMessage);
 | 
			
		||||
 | 
			
		||||
			    //make sure the stored access time for the actual file is more recent than that of its backup
 | 
			
		||||
			    Thread.Sleep(10);
 | 
			
		||||
                SaveFileData(_ioc, _keyfileOrProvider);
 | 
			
		||||
 | 
			
		||||
                Finish(true, _format.SuccessMessage);
 | 
			
		||||
			}
 | 
			
		||||
			catch (OldFormatException)
 | 
			
		||||
			{
 | 
			
		||||
 
 | 
			
		||||
@@ -1,4 +1,14 @@
 | 
			
		||||
<?xml version="1.0" encoding="utf-8"?>
 | 
			
		||||
<packages>
 | 
			
		||||
  <package id="Xamarin.Android.Arch.Core.Common" version="1.0.0" targetFramework="monoandroid81" />
 | 
			
		||||
  <package id="Xamarin.Android.Arch.Lifecycle.Common" version="1.0.1" targetFramework="monoandroid81" />
 | 
			
		||||
  <package id="Xamarin.Android.Arch.Lifecycle.Runtime" version="1.0.0" targetFramework="monoandroid81" />
 | 
			
		||||
  <package id="Xamarin.Android.Support.Annotations" version="26.1.0.1" targetFramework="monoandroid81" />
 | 
			
		||||
  <package id="Xamarin.Android.Support.Compat" version="26.1.0.1" targetFramework="monoandroid81" />
 | 
			
		||||
  <package id="Xamarin.Android.Support.Core.UI" version="26.1.0.1" targetFramework="monoandroid81" />
 | 
			
		||||
  <package id="Xamarin.Android.Support.Core.Utils" version="26.1.0.1" targetFramework="monoandroid81" />
 | 
			
		||||
  <package id="Xamarin.Android.Support.Fragment" version="26.1.0.1" targetFramework="monoandroid81" />
 | 
			
		||||
  <package id="Xamarin.Android.Support.Media.Compat" version="26.1.0.1" targetFramework="monoandroid81" />
 | 
			
		||||
  <package id="Xamarin.Android.Support.v13" version="26.1.0.1" targetFramework="monoandroid81" />
 | 
			
		||||
  <package id="Xamarin.Android.Support.v4" version="23.1.1.0" targetFramework="MonoAndroid50" />
 | 
			
		||||
</packages>
 | 
			
		||||
@@ -11,7 +11,7 @@
 | 
			
		||||
    <MonoAndroidResourcePrefix>Resources</MonoAndroidResourcePrefix>
 | 
			
		||||
    <AssemblyName>Kp2aKeyboardBinding</AssemblyName>
 | 
			
		||||
    <AndroidUseLatestPlatformSdk>True</AndroidUseLatestPlatformSdk>
 | 
			
		||||
    <TargetFrameworkVersion>v8.0</TargetFrameworkVersion>
 | 
			
		||||
    <TargetFrameworkVersion>v8.1</TargetFrameworkVersion>
 | 
			
		||||
  </PropertyGroup>
 | 
			
		||||
  <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
 | 
			
		||||
    <DebugSymbols>True</DebugSymbols>
 | 
			
		||||
@@ -63,8 +63,6 @@
 | 
			
		||||
    <TransformFile Include="Transforms\EnumMethods.xml" />
 | 
			
		||||
    <TransformFile Include="Transforms\Metadata.xml" />
 | 
			
		||||
  </ItemGroup>
 | 
			
		||||
  <ItemGroup>
 | 
			
		||||
    <Folder Include="libs\" />
 | 
			
		||||
  </ItemGroup>
 | 
			
		||||
  <ItemGroup />
 | 
			
		||||
  <Import Project="$(MSBuildExtensionsPath)\Novell\Xamarin.Android.Bindings.targets" />
 | 
			
		||||
</Project>
 | 
			
		||||
@@ -10,8 +10,8 @@
 | 
			
		||||
    <RootNamespace>PluginSdkBinding</RootNamespace>
 | 
			
		||||
    <AssemblyName>PluginSdkBinding</AssemblyName>
 | 
			
		||||
    <FileAlignment>512</FileAlignment>
 | 
			
		||||
    <AndroidUseLatestPlatformSdk>True</AndroidUseLatestPlatformSdk>
 | 
			
		||||
    <TargetFrameworkVersion>v8.0</TargetFrameworkVersion>
 | 
			
		||||
    <AndroidUseLatestPlatformSdk>false</AndroidUseLatestPlatformSdk>
 | 
			
		||||
    <TargetFrameworkVersion>v8.1</TargetFrameworkVersion>
 | 
			
		||||
  </PropertyGroup>
 | 
			
		||||
  <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
 | 
			
		||||
    <DebugSymbols>true</DebugSymbols>
 | 
			
		||||
 
 | 
			
		||||
 Submodule src/SamsungPass updated: c9dd9b21a5...f3c6bbe224
									
								
							@@ -13,7 +13,7 @@
 | 
			
		||||
    <AndroidResgenFile>Resources\Resource.Designer.cs</AndroidResgenFile>
 | 
			
		||||
    <GenerateSerializationAssemblies>Off</GenerateSerializationAssemblies>
 | 
			
		||||
    <AndroidUseLatestPlatformSdk>True</AndroidUseLatestPlatformSdk>
 | 
			
		||||
    <TargetFrameworkVersion>v8.0</TargetFrameworkVersion>
 | 
			
		||||
    <TargetFrameworkVersion>v8.1</TargetFrameworkVersion>
 | 
			
		||||
  </PropertyGroup>
 | 
			
		||||
  <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
 | 
			
		||||
    <DebugSymbols>true</DebugSymbols>
 | 
			
		||||
 
 | 
			
		||||
@@ -13,7 +13,7 @@
 | 
			
		||||
    <MonoAndroidAssetsPrefix>Assets</MonoAndroidAssetsPrefix>
 | 
			
		||||
    <AndroidUseLatestPlatformSdk>True</AndroidUseLatestPlatformSdk>
 | 
			
		||||
    <AssemblyName>ZlibAndroid</AssemblyName>
 | 
			
		||||
    <TargetFrameworkVersion>v8.0</TargetFrameworkVersion>
 | 
			
		||||
    <TargetFrameworkVersion>v8.1</TargetFrameworkVersion>
 | 
			
		||||
  </PropertyGroup>
 | 
			
		||||
  <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
 | 
			
		||||
    <DebugSymbols>true</DebugSymbols>
 | 
			
		||||
 
 | 
			
		||||
@@ -6,11 +6,11 @@ if exist "DropboxFileStorageKeys.cs" (
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
cd ..\..\keepass2android
 | 
			
		||||
call UseManifestDebug.bat
 | 
			
		||||
call UseManifestNoNet.bat
 | 
			
		||||
cd ..
 | 
			
		||||
 | 
			
		||||
call "C:\Program Files (x86)\Microsoft Visual Studio 12.0\VC\vcvarsall.bat" x86_amd64
 | 
			
		||||
 | 
			
		||||
msbuild KeePass.sln /target:keepass2android /p:BuildProjectReferences=true /p:Configuration="Debug" /p:Platform="Any CPU"
 | 
			
		||||
msbuild KeePass.sln /target:keepass2android /p:BuildProjectReferences=true /p:Configuration="Release" /p:Platform="Any CPU"
 | 
			
		||||
 | 
			
		||||
cd build-scripts
 | 
			
		||||
@@ -32,11 +32,11 @@ dependencies {
 | 
			
		||||
    compile 'com.google.apis:google-api-services-drive:v2-rev102-1.16.0-rc'
 | 
			
		||||
    compile 'com.dropbox.core:dropbox-core-sdk:3.0.3'
 | 
			
		||||
    //onedrive:
 | 
			
		||||
    compile('com.onedrive.sdk:onedrive-sdk-android:1.2+') {
 | 
			
		||||
    compile('com.onedrive.sdk:onedrive-sdk-android:1.2.0') {
 | 
			
		||||
        transitive = false
 | 
			
		||||
    }
 | 
			
		||||
    compile 'com.google.code.gson:gson:2.3.1'
 | 
			
		||||
    compile 'com.microsoft.services.msa:msa-auth:0.8.+'
 | 
			
		||||
    compile 'com.microsoft.aad:adal:1.1.+'
 | 
			
		||||
    compile 'com.microsoft.services.msa:msa-auth:0.8.6'
 | 
			
		||||
    compile 'com.microsoft.aad:adal:1.14.0'
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -1,6 +1,6 @@
 | 
			
		||||
/* -*-mode:java; c-basic-offset:2; indent-tabs-mode:nil -*- */
 | 
			
		||||
/*
 | 
			
		||||
Copyright (c) 2002-2012 ymnk, JCraft,Inc. All rights reserved.
 | 
			
		||||
Copyright (c) 2002-2016 ymnk, JCraft,Inc. All rights reserved.
 | 
			
		||||
 | 
			
		||||
Redistribution and use in source and binary forms, with or without
 | 
			
		||||
modification, are permitted provided that the following conditions are met:
 | 
			
		||||
@@ -213,8 +213,11 @@ public class Buffer{
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  void checkFreeSize(int n){
 | 
			
		||||
    if(buffer.length<index+n){
 | 
			
		||||
      byte[] tmp = new byte[buffer.length*2];
 | 
			
		||||
    int size = index+n+Session.buffer_margin;
 | 
			
		||||
    if(buffer.length<size){
 | 
			
		||||
      int i = buffer.length*2;
 | 
			
		||||
      if(i<size) i = size;
 | 
			
		||||
      byte[] tmp = new byte[i];
 | 
			
		||||
      System.arraycopy(buffer, 0, tmp, 0, index);
 | 
			
		||||
      buffer = tmp;
 | 
			
		||||
    }
 | 
			
		||||
 
 | 
			
		||||
@@ -1,6 +1,6 @@
 | 
			
		||||
/* -*-mode:java; c-basic-offset:2; indent-tabs-mode:nil -*- */
 | 
			
		||||
/*
 | 
			
		||||
Copyright (c) 2002-2012 ymnk, JCraft,Inc. All rights reserved.
 | 
			
		||||
Copyright (c) 2002-2016 ymnk, JCraft,Inc. All rights reserved.
 | 
			
		||||
 | 
			
		||||
Redistribution and use in source and binary forms, with or without
 | 
			
		||||
modification, are permitted provided that the following conditions are met:
 | 
			
		||||
@@ -192,29 +192,38 @@ public abstract class Channel implements Runnable{
 | 
			
		||||
    io.setExtOutputStream(out, dontclose);
 | 
			
		||||
  }
 | 
			
		||||
  public InputStream getInputStream() throws IOException {
 | 
			
		||||
    PipedInputStream in=
 | 
			
		||||
    int max_input_buffer_size = 32*1024;
 | 
			
		||||
    try {
 | 
			
		||||
      max_input_buffer_size =
 | 
			
		||||
        Integer.parseInt(getSession().getConfig("max_input_buffer_size"));
 | 
			
		||||
    }
 | 
			
		||||
    catch(Exception e){}
 | 
			
		||||
    PipedInputStream in =
 | 
			
		||||
      new MyPipedInputStream(
 | 
			
		||||
                             32*1024  // this value should be customizable.
 | 
			
		||||
                             32*1024,  // this value should be customizable.
 | 
			
		||||
                             max_input_buffer_size
 | 
			
		||||
                             );
 | 
			
		||||
    io.setOutputStream(new PassiveOutputStream(in), false);
 | 
			
		||||
    boolean resizable = 32*1024<max_input_buffer_size;
 | 
			
		||||
    io.setOutputStream(new PassiveOutputStream(in, resizable), false);
 | 
			
		||||
    return in;
 | 
			
		||||
  }
 | 
			
		||||
  public InputStream getExtInputStream() throws IOException {
 | 
			
		||||
    PipedInputStream in=
 | 
			
		||||
    int max_input_buffer_size = 32*1024;
 | 
			
		||||
    try {
 | 
			
		||||
      max_input_buffer_size =
 | 
			
		||||
        Integer.parseInt(getSession().getConfig("max_input_buffer_size"));
 | 
			
		||||
    }
 | 
			
		||||
    catch(Exception e){}
 | 
			
		||||
    PipedInputStream in =
 | 
			
		||||
      new MyPipedInputStream(
 | 
			
		||||
                             32*1024  // this value should be customizable.
 | 
			
		||||
                             32*1024,  // this value should be customizable.
 | 
			
		||||
                             max_input_buffer_size
 | 
			
		||||
                             );
 | 
			
		||||
    io.setExtOutputStream(new PassiveOutputStream(in), false);
 | 
			
		||||
    boolean resizable = 32*1024<max_input_buffer_size;
 | 
			
		||||
    io.setExtOutputStream(new PassiveOutputStream(in, resizable), false);
 | 
			
		||||
    return in;
 | 
			
		||||
  }
 | 
			
		||||
  public OutputStream getOutputStream() throws IOException {
 | 
			
		||||
    /*
 | 
			
		||||
    PipedOutputStream out=new PipedOutputStream();
 | 
			
		||||
    io.setInputStream(new PassiveInputStream(out
 | 
			
		||||
                                             , 32*1024
 | 
			
		||||
                                             ), false);
 | 
			
		||||
    return out;
 | 
			
		||||
    */
 | 
			
		||||
 | 
			
		||||
    final Channel channel=this;
 | 
			
		||||
    OutputStream out=new OutputStream(){
 | 
			
		||||
@@ -317,15 +326,24 @@ public abstract class Channel implements Runnable{
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  class MyPipedInputStream extends PipedInputStream{
 | 
			
		||||
    private int BUFFER_SIZE = 1024;
 | 
			
		||||
    private int max_buffer_size = BUFFER_SIZE;
 | 
			
		||||
    MyPipedInputStream() throws IOException{ super(); }
 | 
			
		||||
    MyPipedInputStream(int size) throws IOException{
 | 
			
		||||
      super();
 | 
			
		||||
      buffer=new byte[size];
 | 
			
		||||
      BUFFER_SIZE = size;
 | 
			
		||||
      max_buffer_size = size;
 | 
			
		||||
    }
 | 
			
		||||
    MyPipedInputStream(int size, int max_buffer_size) throws IOException{
 | 
			
		||||
      this(size);
 | 
			
		||||
      this.max_buffer_size = max_buffer_size;
 | 
			
		||||
    }
 | 
			
		||||
    MyPipedInputStream(PipedOutputStream out) throws IOException{ super(out); }
 | 
			
		||||
    MyPipedInputStream(PipedOutputStream out, int size) throws IOException{
 | 
			
		||||
      super(out);
 | 
			
		||||
      buffer=new byte[size];
 | 
			
		||||
      BUFFER_SIZE=size;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /*
 | 
			
		||||
@@ -343,12 +361,66 @@ public abstract class Channel implements Runnable{
 | 
			
		||||
      buffer[in++] = 0;
 | 
			
		||||
      read();
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    private int freeSpace(){
 | 
			
		||||
      int size = 0;
 | 
			
		||||
      if(out < in) {
 | 
			
		||||
        size = buffer.length-in;
 | 
			
		||||
      }
 | 
			
		||||
      else if(in < out){
 | 
			
		||||
        if(in == -1) size = buffer.length;
 | 
			
		||||
        else size = out - in;
 | 
			
		||||
      }
 | 
			
		||||
      return size;
 | 
			
		||||
    } 
 | 
			
		||||
    synchronized void checkSpace(int len) throws IOException {
 | 
			
		||||
      int size = freeSpace();
 | 
			
		||||
      if(size<len){
 | 
			
		||||
        int datasize=buffer.length-size;
 | 
			
		||||
        int foo = buffer.length;
 | 
			
		||||
        while((foo - datasize) < len){
 | 
			
		||||
          foo*=2;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        if(foo > max_buffer_size){
 | 
			
		||||
          foo = max_buffer_size;
 | 
			
		||||
        }
 | 
			
		||||
        if((foo - datasize) < len) return;
 | 
			
		||||
 | 
			
		||||
        byte[] tmp = new byte[foo];
 | 
			
		||||
        if(out < in) {
 | 
			
		||||
          System.arraycopy(buffer, 0, tmp, 0, buffer.length);
 | 
			
		||||
        }
 | 
			
		||||
        else if(in < out){
 | 
			
		||||
          if(in == -1) {
 | 
			
		||||
          }
 | 
			
		||||
          else {
 | 
			
		||||
            System.arraycopy(buffer, 0, tmp, 0, in);
 | 
			
		||||
            System.arraycopy(buffer, out, 
 | 
			
		||||
                             tmp, tmp.length-(buffer.length-out),
 | 
			
		||||
                             (buffer.length-out));
 | 
			
		||||
            out = tmp.length-(buffer.length-out);
 | 
			
		||||
          }
 | 
			
		||||
        }
 | 
			
		||||
        else if(in == out){
 | 
			
		||||
          System.arraycopy(buffer, 0, tmp, 0, buffer.length);
 | 
			
		||||
          in=buffer.length;
 | 
			
		||||
        }
 | 
			
		||||
        buffer=tmp;
 | 
			
		||||
      }
 | 
			
		||||
      else if(buffer.length == size && size > BUFFER_SIZE) { 
 | 
			
		||||
        int  i = size/2;
 | 
			
		||||
        if(i<BUFFER_SIZE) i = BUFFER_SIZE;
 | 
			
		||||
        byte[] tmp = new byte[i];
 | 
			
		||||
        buffer=tmp;
 | 
			
		||||
      }
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
  void setLocalWindowSizeMax(int foo){ this.lwsize_max=foo; }
 | 
			
		||||
  void setLocalWindowSize(int foo){ this.lwsize=foo; }
 | 
			
		||||
  void setLocalPacketSize(int foo){ this.lmpsize=foo; }
 | 
			
		||||
  synchronized void setRemoteWindowSize(long foo){ this.rwsize=foo; }
 | 
			
		||||
  synchronized void addRemoteWindowSize(int foo){ 
 | 
			
		||||
  synchronized void addRemoteWindowSize(long foo){ 
 | 
			
		||||
    this.rwsize+=foo; 
 | 
			
		||||
    if(notifyme>0)
 | 
			
		||||
      notifyAll();
 | 
			
		||||
@@ -384,12 +456,15 @@ public abstract class Channel implements Runnable{
 | 
			
		||||
    if(eof_local)return;
 | 
			
		||||
    eof_local=true;
 | 
			
		||||
 | 
			
		||||
    int i = getRecipient();
 | 
			
		||||
    if(i == -1) return;
 | 
			
		||||
 | 
			
		||||
    try{
 | 
			
		||||
      Buffer buf=new Buffer(100);
 | 
			
		||||
      Packet packet=new Packet(buf);
 | 
			
		||||
      packet.reset();
 | 
			
		||||
      buf.putByte((byte)Session.SSH_MSG_CHANNEL_EOF);
 | 
			
		||||
      buf.putInt(getRecipient());
 | 
			
		||||
      buf.putInt(i);
 | 
			
		||||
      synchronized(this){
 | 
			
		||||
        if(!close)
 | 
			
		||||
          getSession().write(packet);
 | 
			
		||||
@@ -445,12 +520,15 @@ public abstract class Channel implements Runnable{
 | 
			
		||||
    close=true;
 | 
			
		||||
    eof_local=eof_remote=true;
 | 
			
		||||
 | 
			
		||||
    int i = getRecipient();
 | 
			
		||||
    if(i == -1) return;
 | 
			
		||||
 | 
			
		||||
    try{
 | 
			
		||||
      Buffer buf=new Buffer(100);
 | 
			
		||||
      Packet packet=new Packet(buf);
 | 
			
		||||
      packet.reset();
 | 
			
		||||
      buf.putByte((byte)Session.SSH_MSG_CHANNEL_CLOSE);
 | 
			
		||||
      buf.putInt(getRecipient());
 | 
			
		||||
      buf.putInt(i);
 | 
			
		||||
      synchronized(this){
 | 
			
		||||
        getSession().write(packet);
 | 
			
		||||
      }
 | 
			
		||||
@@ -561,8 +639,25 @@ public abstract class Channel implements Runnable{
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
  class PassiveOutputStream extends PipedOutputStream{
 | 
			
		||||
    PassiveOutputStream(PipedInputStream in) throws IOException{
 | 
			
		||||
    private MyPipedInputStream _sink=null;
 | 
			
		||||
    PassiveOutputStream(PipedInputStream in,
 | 
			
		||||
                        boolean resizable_buffer) throws IOException{
 | 
			
		||||
      super(in);
 | 
			
		||||
      if(resizable_buffer && (in instanceof MyPipedInputStream)) {
 | 
			
		||||
        this._sink=(MyPipedInputStream)in;
 | 
			
		||||
      }
 | 
			
		||||
    }
 | 
			
		||||
    public void write(int b) throws IOException {
 | 
			
		||||
      if(_sink != null) {
 | 
			
		||||
        _sink.checkSpace(1);
 | 
			
		||||
      }
 | 
			
		||||
      super.write(b);
 | 
			
		||||
    }
 | 
			
		||||
    public void write(byte[] b, int off, int len) throws IOException {
 | 
			
		||||
      if(_sink != null) {
 | 
			
		||||
        _sink.checkSpace(len);
 | 
			
		||||
      }
 | 
			
		||||
      super.write(b, off, len); 
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
@@ -636,7 +731,7 @@ public abstract class Channel implements Runnable{
 | 
			
		||||
    Packet packet = genChannelOpenPacket();
 | 
			
		||||
    _session.write(packet);
 | 
			
		||||
 | 
			
		||||
    int retry=10;
 | 
			
		||||
    int retry=2000;
 | 
			
		||||
    long start=System.currentTimeMillis();
 | 
			
		||||
    long timeout=connectTimeout;
 | 
			
		||||
    if(timeout!=0L) retry = 1;
 | 
			
		||||
@@ -651,7 +746,7 @@ public abstract class Channel implements Runnable{
 | 
			
		||||
          }
 | 
			
		||||
        }
 | 
			
		||||
        try{
 | 
			
		||||
          long t = timeout==0L ? 5000L : timeout;
 | 
			
		||||
          long t = timeout==0L ? 10L : timeout;
 | 
			
		||||
          this.notifyme=1;
 | 
			
		||||
          wait(t);
 | 
			
		||||
        }
 | 
			
		||||
 
 | 
			
		||||
@@ -1,6 +1,6 @@
 | 
			
		||||
/* -*-mode:java; c-basic-offset:2; indent-tabs-mode:nil -*- */
 | 
			
		||||
/*
 | 
			
		||||
Copyright (c) 2006-2012 ymnk, JCraft,Inc. All rights reserved.
 | 
			
		||||
Copyright (c) 2006-2016 ymnk, JCraft,Inc. All rights reserved.
 | 
			
		||||
 | 
			
		||||
Redistribution and use in source and binary forms, with or without
 | 
			
		||||
modification, are permitted provided that the following conditions are met:
 | 
			
		||||
 
 | 
			
		||||
@@ -1,6 +1,6 @@
 | 
			
		||||
/* -*-mode:java; c-basic-offset:2; indent-tabs-mode:nil -*- */
 | 
			
		||||
/*
 | 
			
		||||
Copyright (c) 2002-2012 ymnk, JCraft,Inc. All rights reserved.
 | 
			
		||||
Copyright (c) 2002-2016 ymnk, JCraft,Inc. All rights reserved.
 | 
			
		||||
 | 
			
		||||
Redistribution and use in source and binary forms, with or without
 | 
			
		||||
modification, are permitted provided that the following conditions are met:
 | 
			
		||||
@@ -120,7 +120,16 @@ public class ChannelDirectTCPIP extends Channel{
 | 
			
		||||
      }
 | 
			
		||||
    }
 | 
			
		||||
    catch(Exception e){
 | 
			
		||||
      // Whenever an exception is thrown by sendChannelOpen(),
 | 
			
		||||
      // 'connected' is false.
 | 
			
		||||
      if(!connected){
 | 
			
		||||
        connected=true;
 | 
			
		||||
      }
 | 
			
		||||
      disconnect();
 | 
			
		||||
      return;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    eof();
 | 
			
		||||
    disconnect();
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -1,6 +1,6 @@
 | 
			
		||||
/* -*-mode:java; c-basic-offset:2; indent-tabs-mode:nil -*- */
 | 
			
		||||
/*
 | 
			
		||||
Copyright (c) 2002-2012 ymnk, JCraft,Inc. All rights reserved.
 | 
			
		||||
Copyright (c) 2002-2016 ymnk, JCraft,Inc. All rights reserved.
 | 
			
		||||
 | 
			
		||||
Redistribution and use in source and binary forms, with or without
 | 
			
		||||
modification, are permitted provided that the following conditions are met:
 | 
			
		||||
 
 | 
			
		||||
@@ -1,6 +1,6 @@
 | 
			
		||||
/* -*-mode:java; c-basic-offset:2; indent-tabs-mode:nil -*- */
 | 
			
		||||
/*
 | 
			
		||||
Copyright (c) 2002-2012 ymnk, JCraft,Inc. All rights reserved.
 | 
			
		||||
Copyright (c) 2002-2016 ymnk, JCraft,Inc. All rights reserved.
 | 
			
		||||
 | 
			
		||||
Redistribution and use in source and binary forms, with or without
 | 
			
		||||
modification, are permitted provided that the following conditions are met:
 | 
			
		||||
 
 | 
			
		||||
@@ -1,6 +1,6 @@
 | 
			
		||||
/* -*-mode:java; c-basic-offset:2; indent-tabs-mode:nil -*- */
 | 
			
		||||
/*
 | 
			
		||||
Copyright (c) 2002-2012 ymnk, JCraft,Inc. All rights reserved.
 | 
			
		||||
Copyright (c) 2002-2016 ymnk, JCraft,Inc. All rights reserved.
 | 
			
		||||
 | 
			
		||||
Redistribution and use in source and binary forms, with or without
 | 
			
		||||
modification, are permitted provided that the following conditions are met:
 | 
			
		||||
 
 | 
			
		||||
@@ -1,6 +1,6 @@
 | 
			
		||||
/* -*-mode:java; c-basic-offset:2; indent-tabs-mode:nil -*- */
 | 
			
		||||
/*
 | 
			
		||||
Copyright (c) 2002-2012 ymnk, JCraft,Inc. All rights reserved.
 | 
			
		||||
Copyright (c) 2002-2016 ymnk, JCraft,Inc. All rights reserved.
 | 
			
		||||
 | 
			
		||||
Redistribution and use in source and binary forms, with or without
 | 
			
		||||
modification, are permitted provided that the following conditions are met:
 | 
			
		||||
@@ -648,7 +648,6 @@ public class ChannelSftp extends ChannelSession{
 | 
			
		||||
          if((seq-1)==startid ||
 | 
			
		||||
             ((seq-startid)-ackcount)>=bulk_requests){
 | 
			
		||||
            while(((seq-startid)-ackcount)>=bulk_requests){
 | 
			
		||||
              if(this.rwsize>=foo) break;
 | 
			
		||||
              if(checkStatus(ackid, header)){
 | 
			
		||||
                int _ackid = ackid[0];
 | 
			
		||||
                if(startid>_ackid || _ackid>seq-1){
 | 
			
		||||
@@ -666,7 +665,16 @@ public class ChannelSftp extends ChannelSession{
 | 
			
		||||
              }
 | 
			
		||||
            }
 | 
			
		||||
          }
 | 
			
		||||
          foo-=sendWRITE(handle, offset, data, 0, foo);
 | 
			
		||||
          if(dontcopy){
 | 
			
		||||
            foo-=sendWRITE(handle, offset, data, 0, foo);
 | 
			
		||||
            if(data!=obuf.buffer){
 | 
			
		||||
              data=obuf.buffer;
 | 
			
		||||
              _datalen=obuf.buffer.length-_s-Session.buffer_margin;
 | 
			
		||||
            }
 | 
			
		||||
          }
 | 
			
		||||
          else {
 | 
			
		||||
            foo-=sendWRITE(handle, offset, data, _s, foo);
 | 
			
		||||
          }
 | 
			
		||||
        }
 | 
			
		||||
        offset+=count;
 | 
			
		||||
	if(monitor!=null && !monitor.count(count)){
 | 
			
		||||
@@ -736,6 +744,12 @@ public class ChannelSftp extends ChannelSession{
 | 
			
		||||
	}
 | 
			
		||||
      }
 | 
			
		||||
 | 
			
		||||
      if(monitor!=null){
 | 
			
		||||
        monitor.init(SftpProgressMonitor.PUT,
 | 
			
		||||
                     "-", dst,
 | 
			
		||||
                     SftpProgressMonitor.UNKNOWN_SIZE);
 | 
			
		||||
      }
 | 
			
		||||
 | 
			
		||||
      if(mode==OVERWRITE){ sendOPENW(dstb); }
 | 
			
		||||
      else{ sendOPENA(dstb); }
 | 
			
		||||
 | 
			
		||||
@@ -923,6 +937,15 @@ public class ChannelSftp extends ChannelSession{
 | 
			
		||||
	  if(i==-1) dstsb.append(_src);
 | 
			
		||||
	  else dstsb.append(_src.substring(i + 1));
 | 
			
		||||
          _dst=dstsb.toString();
 | 
			
		||||
          if(_dst.indexOf("..")!=-1){
 | 
			
		||||
            String dstc = (new java.io.File(dst)).getCanonicalPath();
 | 
			
		||||
            String _dstc = (new java.io.File(_dst)).getCanonicalPath();
 | 
			
		||||
            if(!(_dstc.length()>dstc.length() &&
 | 
			
		||||
                 _dstc.substring(0, dstc.length()+1).equals(dstc+file_separator))){
 | 
			
		||||
              throw new SftpException(SSH_FX_FAILURE,
 | 
			
		||||
                                      "writing to an unexpected file "+_src);
 | 
			
		||||
            }
 | 
			
		||||
          }
 | 
			
		||||
          dstsb.delete(dst.length(), _dst.length());
 | 
			
		||||
	}
 | 
			
		||||
        else{
 | 
			
		||||
@@ -1375,7 +1398,10 @@ public class ChannelSftp extends ChannelSession{
 | 
			
		||||
               len=1024; 
 | 
			
		||||
             }
 | 
			
		||||
 | 
			
		||||
             if(rq.count()==0) {
 | 
			
		||||
             if(rq.count()==0
 | 
			
		||||
                || true // working around slow transfer speed for
 | 
			
		||||
                        // some sftp servers including Titan FTP.
 | 
			
		||||
               ) {
 | 
			
		||||
               int request_len = buf.buffer.length-13;
 | 
			
		||||
               if(server_version==0){ request_len=1024; }
 | 
			
		||||
 | 
			
		||||
@@ -1782,10 +1808,17 @@ public class ChannelSftp extends ChannelSession{
 | 
			
		||||
     try{
 | 
			
		||||
       ((MyPipedInputStream)io_in).updateReadSide();
 | 
			
		||||
 | 
			
		||||
       oldpath=remoteAbsolutePath(oldpath);
 | 
			
		||||
       String _oldpath=remoteAbsolutePath(oldpath);
 | 
			
		||||
       newpath=remoteAbsolutePath(newpath);
 | 
			
		||||
 | 
			
		||||
       oldpath=isUnique(oldpath);
 | 
			
		||||
       _oldpath=isUnique(_oldpath);
 | 
			
		||||
       if(oldpath.charAt(0)!='/'){ // relative path
 | 
			
		||||
         String cwd=getCwd();
 | 
			
		||||
         oldpath=_oldpath.substring(cwd.length()+(cwd.endsWith("/")?0:1));
 | 
			
		||||
       }
 | 
			
		||||
       else {
 | 
			
		||||
         oldpath=_oldpath;
 | 
			
		||||
       }
 | 
			
		||||
 | 
			
		||||
       if(isPattern(newpath)){
 | 
			
		||||
         throw new SftpException(SSH_FX_FAILURE, newpath);
 | 
			
		||||
@@ -1827,10 +1860,17 @@ public class ChannelSftp extends ChannelSession{
 | 
			
		||||
     try{
 | 
			
		||||
       ((MyPipedInputStream)io_in).updateReadSide();
 | 
			
		||||
 | 
			
		||||
       oldpath=remoteAbsolutePath(oldpath);
 | 
			
		||||
       String _oldpath=remoteAbsolutePath(oldpath);
 | 
			
		||||
       newpath=remoteAbsolutePath(newpath);
 | 
			
		||||
 | 
			
		||||
       oldpath=isUnique(oldpath);
 | 
			
		||||
       _oldpath=isUnique(_oldpath);
 | 
			
		||||
       if(oldpath.charAt(0)!='/'){ // relative path
 | 
			
		||||
         String cwd=getCwd();
 | 
			
		||||
         oldpath=_oldpath.substring(cwd.length()+(cwd.endsWith("/")?0:1));
 | 
			
		||||
       }
 | 
			
		||||
       else {
 | 
			
		||||
         oldpath=_oldpath;
 | 
			
		||||
       }
 | 
			
		||||
 | 
			
		||||
       if(isPattern(newpath)){
 | 
			
		||||
         throw new SftpException(SSH_FX_FAILURE, newpath);
 | 
			
		||||
 
 | 
			
		||||
@@ -1,6 +1,6 @@
 | 
			
		||||
/* -*-mode:java; c-basic-offset:2; indent-tabs-mode:nil -*- */
 | 
			
		||||
/*
 | 
			
		||||
Copyright (c) 2002-2012 ymnk, JCraft,Inc. All rights reserved.
 | 
			
		||||
Copyright (c) 2002-2016 ymnk, JCraft,Inc. All rights reserved.
 | 
			
		||||
 | 
			
		||||
Redistribution and use in source and binary forms, with or without
 | 
			
		||||
modification, are permitted provided that the following conditions are met:
 | 
			
		||||
 
 | 
			
		||||
@@ -1,6 +1,6 @@
 | 
			
		||||
/* -*-mode:java; c-basic-offset:2; indent-tabs-mode:nil -*- */
 | 
			
		||||
/*
 | 
			
		||||
Copyright (c) 2005-2012 ymnk, JCraft,Inc. All rights reserved.
 | 
			
		||||
Copyright (c) 2005-2016 ymnk, JCraft,Inc. All rights reserved.
 | 
			
		||||
 | 
			
		||||
Redistribution and use in source and binary forms, with or without
 | 
			
		||||
modification, are permitted provided that the following conditions are met:
 | 
			
		||||
 
 | 
			
		||||
@@ -1,6 +1,6 @@
 | 
			
		||||
/* -*-mode:java; c-basic-offset:2; indent-tabs-mode:nil -*- */
 | 
			
		||||
/*
 | 
			
		||||
Copyright (c) 2002-2012 ymnk, JCraft,Inc. All rights reserved.
 | 
			
		||||
Copyright (c) 2002-2016 ymnk, JCraft,Inc. All rights reserved.
 | 
			
		||||
 | 
			
		||||
Redistribution and use in source and binary forms, with or without
 | 
			
		||||
modification, are permitted provided that the following conditions are met:
 | 
			
		||||
 
 | 
			
		||||
@@ -1,6 +1,6 @@
 | 
			
		||||
/* -*-mode:java; c-basic-offset:2; indent-tabs-mode:nil -*- */
 | 
			
		||||
/*
 | 
			
		||||
Copyright (c) 2002-2012 ymnk, JCraft,Inc. All rights reserved.
 | 
			
		||||
Copyright (c) 2002-2016 ymnk, JCraft,Inc. All rights reserved.
 | 
			
		||||
 | 
			
		||||
Redistribution and use in source and binary forms, with or without
 | 
			
		||||
modification, are permitted provided that the following conditions are met:
 | 
			
		||||
 
 | 
			
		||||
@@ -1,6 +1,6 @@
 | 
			
		||||
/* -*-mode:java; c-basic-offset:2; indent-tabs-mode:nil -*- */
 | 
			
		||||
/*
 | 
			
		||||
Copyright (c) 2002-2012 ymnk, JCraft,Inc. All rights reserved.
 | 
			
		||||
Copyright (c) 2002-2016 ymnk, JCraft,Inc. All rights reserved.
 | 
			
		||||
 | 
			
		||||
Redistribution and use in source and binary forms, with or without
 | 
			
		||||
modification, are permitted provided that the following conditions are met:
 | 
			
		||||
 
 | 
			
		||||
@@ -1,6 +1,6 @@
 | 
			
		||||
/* -*-mode:java; c-basic-offset:2; indent-tabs-mode:nil -*- */
 | 
			
		||||
/*
 | 
			
		||||
Copyright (c) 2002-2012 ymnk, JCraft,Inc. All rights reserved.
 | 
			
		||||
Copyright (c) 2002-2016 ymnk, JCraft,Inc. All rights reserved.
 | 
			
		||||
 | 
			
		||||
Redistribution and use in source and binary forms, with or without
 | 
			
		||||
modification, are permitted provided that the following conditions are met:
 | 
			
		||||
 
 | 
			
		||||
@@ -1,6 +1,6 @@
 | 
			
		||||
/* -*-mode:java; c-basic-offset:2; indent-tabs-mode:nil -*- */
 | 
			
		||||
/*
 | 
			
		||||
Copyright (c) 2013 ymnk, JCraft,Inc. All rights reserved.
 | 
			
		||||
Copyright (c) 2013-2016 ymnk, JCraft,Inc. All rights reserved.
 | 
			
		||||
 | 
			
		||||
Redistribution and use in source and binary forms, with or without
 | 
			
		||||
modification, are permitted provided that the following conditions are met:
 | 
			
		||||
 
 | 
			
		||||
@@ -1,6 +1,6 @@
 | 
			
		||||
/* -*-mode:java; c-basic-offset:2; indent-tabs-mode:nil -*- */
 | 
			
		||||
/*
 | 
			
		||||
Copyright (c) 2002-2012 ymnk, JCraft,Inc. All rights reserved.
 | 
			
		||||
Copyright (c) 2002-2016 ymnk, JCraft,Inc. All rights reserved.
 | 
			
		||||
 | 
			
		||||
Redistribution and use in source and binary forms, with or without
 | 
			
		||||
modification, are permitted provided that the following conditions are met:
 | 
			
		||||
@@ -36,4 +36,8 @@ public interface DH{
 | 
			
		||||
  byte[] getE() throws Exception;
 | 
			
		||||
  void setF(byte[] f);
 | 
			
		||||
  byte[] getK() throws Exception;
 | 
			
		||||
 | 
			
		||||
  // checkRange() will check if e and f are in [1,p-1]
 | 
			
		||||
  // as defined at https://tools.ietf.org/html/rfc4253#section-8
 | 
			
		||||
  void checkRange() throws Exception;
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -0,0 +1,37 @@
 | 
			
		||||
/* -*-mode:java; c-basic-offset:2; indent-tabs-mode:nil -*- */
 | 
			
		||||
/*
 | 
			
		||||
Copyright (c) 2015-2016 ymnk, JCraft,Inc. All rights reserved.
 | 
			
		||||
 | 
			
		||||
Redistribution and use in source and binary forms, with or without
 | 
			
		||||
modification, are permitted provided that the following conditions are met:
 | 
			
		||||
 | 
			
		||||
  1. Redistributions of source code must retain the above copyright notice,
 | 
			
		||||
     this list of conditions and the following disclaimer.
 | 
			
		||||
 | 
			
		||||
  2. Redistributions in binary form must reproduce the above copyright 
 | 
			
		||||
     notice, this list of conditions and the following disclaimer in 
 | 
			
		||||
     the documentation and/or other materials provided with the distribution.
 | 
			
		||||
 | 
			
		||||
  3. The names of the authors may not be used to endorse or promote products
 | 
			
		||||
     derived from this software without specific prior written permission.
 | 
			
		||||
 | 
			
		||||
THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES,
 | 
			
		||||
INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
 | 
			
		||||
FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JCRAFT,
 | 
			
		||||
INC. OR ANY CONTRIBUTORS TO THIS SOFTWARE BE LIABLE FOR ANY DIRECT, INDIRECT,
 | 
			
		||||
INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
 | 
			
		||||
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
 | 
			
		||||
OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
 | 
			
		||||
LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
 | 
			
		||||
NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
 | 
			
		||||
EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 | 
			
		||||
*/
 | 
			
		||||
 | 
			
		||||
package com.jcraft.jsch;
 | 
			
		||||
 | 
			
		||||
public class DHEC256 extends DHECN {
 | 
			
		||||
  public DHEC256(){
 | 
			
		||||
    sha_name="sha-256";
 | 
			
		||||
    key_size=256;
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
@@ -0,0 +1,37 @@
 | 
			
		||||
/* -*-mode:java; c-basic-offset:2; indent-tabs-mode:nil -*- */
 | 
			
		||||
/*
 | 
			
		||||
Copyright (c) 2015-2016 ymnk, JCraft,Inc. All rights reserved.
 | 
			
		||||
 | 
			
		||||
Redistribution and use in source and binary forms, with or without
 | 
			
		||||
modification, are permitted provided that the following conditions are met:
 | 
			
		||||
 | 
			
		||||
  1. Redistributions of source code must retain the above copyright notice,
 | 
			
		||||
     this list of conditions and the following disclaimer.
 | 
			
		||||
 | 
			
		||||
  2. Redistributions in binary form must reproduce the above copyright 
 | 
			
		||||
     notice, this list of conditions and the following disclaimer in 
 | 
			
		||||
     the documentation and/or other materials provided with the distribution.
 | 
			
		||||
 | 
			
		||||
  3. The names of the authors may not be used to endorse or promote products
 | 
			
		||||
     derived from this software without specific prior written permission.
 | 
			
		||||
 | 
			
		||||
THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES,
 | 
			
		||||
INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
 | 
			
		||||
FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JCRAFT,
 | 
			
		||||
INC. OR ANY CONTRIBUTORS TO THIS SOFTWARE BE LIABLE FOR ANY DIRECT, INDIRECT,
 | 
			
		||||
INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
 | 
			
		||||
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
 | 
			
		||||
OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
 | 
			
		||||
LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
 | 
			
		||||
NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
 | 
			
		||||
EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 | 
			
		||||
*/
 | 
			
		||||
 | 
			
		||||
package com.jcraft.jsch;
 | 
			
		||||
 | 
			
		||||
public class DHEC384 extends DHECN {
 | 
			
		||||
  public DHEC384(){
 | 
			
		||||
    sha_name="sha-384";
 | 
			
		||||
    key_size=384;
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
@@ -0,0 +1,37 @@
 | 
			
		||||
/* -*-mode:java; c-basic-offset:2; indent-tabs-mode:nil -*- */
 | 
			
		||||
/*
 | 
			
		||||
Copyright (c) 2015-2016 ymnk, JCraft,Inc. All rights reserved.
 | 
			
		||||
 | 
			
		||||
Redistribution and use in source and binary forms, with or without
 | 
			
		||||
modification, are permitted provided that the following conditions are met:
 | 
			
		||||
 | 
			
		||||
  1. Redistributions of source code must retain the above copyright notice,
 | 
			
		||||
     this list of conditions and the following disclaimer.
 | 
			
		||||
 | 
			
		||||
  2. Redistributions in binary form must reproduce the above copyright 
 | 
			
		||||
     notice, this list of conditions and the following disclaimer in 
 | 
			
		||||
     the documentation and/or other materials provided with the distribution.
 | 
			
		||||
 | 
			
		||||
  3. The names of the authors may not be used to endorse or promote products
 | 
			
		||||
     derived from this software without specific prior written permission.
 | 
			
		||||
 | 
			
		||||
THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES,
 | 
			
		||||
INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
 | 
			
		||||
FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JCRAFT,
 | 
			
		||||
INC. OR ANY CONTRIBUTORS TO THIS SOFTWARE BE LIABLE FOR ANY DIRECT, INDIRECT,
 | 
			
		||||
INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
 | 
			
		||||
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
 | 
			
		||||
OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
 | 
			
		||||
LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
 | 
			
		||||
NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
 | 
			
		||||
EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 | 
			
		||||
*/
 | 
			
		||||
 | 
			
		||||
package com.jcraft.jsch;
 | 
			
		||||
 | 
			
		||||
public class DHEC521 extends DHECN {
 | 
			
		||||
  public DHEC521(){
 | 
			
		||||
    sha_name="sha-512";
 | 
			
		||||
    key_size=521;
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
@@ -0,0 +1,187 @@
 | 
			
		||||
/* -*-mode:java; c-basic-offset:2; indent-tabs-mode:nil -*- */
 | 
			
		||||
/*
 | 
			
		||||
Copyright (c) 2015-2016 ymnk, JCraft,Inc. All rights reserved.
 | 
			
		||||
 | 
			
		||||
Redistribution and use in source and binary forms, with or without
 | 
			
		||||
modification, are permitted provided that the following conditions are met:
 | 
			
		||||
 | 
			
		||||
  1. Redistributions of source code must retain the above copyright notice,
 | 
			
		||||
     this list of conditions and the following disclaimer.
 | 
			
		||||
 | 
			
		||||
  2. Redistributions in binary form must reproduce the above copyright 
 | 
			
		||||
     notice, this list of conditions and the following disclaimer in 
 | 
			
		||||
     the documentation and/or other materials provided with the distribution.
 | 
			
		||||
 | 
			
		||||
  3. The names of the authors may not be used to endorse or promote products
 | 
			
		||||
     derived from this software without specific prior written permission.
 | 
			
		||||
 | 
			
		||||
THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES,
 | 
			
		||||
INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
 | 
			
		||||
FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JCRAFT,
 | 
			
		||||
INC. OR ANY CONTRIBUTORS TO THIS SOFTWARE BE LIABLE FOR ANY DIRECT, INDIRECT,
 | 
			
		||||
INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
 | 
			
		||||
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
 | 
			
		||||
OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
 | 
			
		||||
LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
 | 
			
		||||
NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
 | 
			
		||||
EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 | 
			
		||||
*/
 | 
			
		||||
 | 
			
		||||
package com.jcraft.jsch;
 | 
			
		||||
 | 
			
		||||
public abstract class DHECN extends KeyExchange{
 | 
			
		||||
 | 
			
		||||
  private static final int SSH_MSG_KEX_ECDH_INIT =                 30;
 | 
			
		||||
  private static final int SSH_MSG_KEX_ECDH_REPLY=                 31;
 | 
			
		||||
  private int state;
 | 
			
		||||
 | 
			
		||||
  byte[] Q_C;
 | 
			
		||||
 | 
			
		||||
  byte[] V_S;
 | 
			
		||||
  byte[] V_C;
 | 
			
		||||
  byte[] I_S;
 | 
			
		||||
  byte[] I_C;
 | 
			
		||||
 | 
			
		||||
  byte[] e;
 | 
			
		||||
 | 
			
		||||
  private Buffer buf;
 | 
			
		||||
  private Packet packet;
 | 
			
		||||
 | 
			
		||||
  private ECDH ecdh;
 | 
			
		||||
 | 
			
		||||
  protected String sha_name; 
 | 
			
		||||
  protected int key_size;
 | 
			
		||||
 | 
			
		||||
  public void init(Session session,
 | 
			
		||||
		   byte[] V_S, byte[] V_C, byte[] I_S, byte[] I_C) throws Exception{
 | 
			
		||||
    this.session=session;
 | 
			
		||||
    this.V_S=V_S;      
 | 
			
		||||
    this.V_C=V_C;      
 | 
			
		||||
    this.I_S=I_S;      
 | 
			
		||||
    this.I_C=I_C;      
 | 
			
		||||
 | 
			
		||||
    try{
 | 
			
		||||
      Class c=Class.forName(session.getConfig(sha_name));
 | 
			
		||||
      sha=(HASH)(c.newInstance());
 | 
			
		||||
      sha.init();
 | 
			
		||||
    }
 | 
			
		||||
    catch(Exception e){
 | 
			
		||||
      System.err.println(e);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    buf=new Buffer();
 | 
			
		||||
    packet=new Packet(buf);
 | 
			
		||||
 | 
			
		||||
    packet.reset();
 | 
			
		||||
    buf.putByte((byte)SSH_MSG_KEX_ECDH_INIT);
 | 
			
		||||
 | 
			
		||||
    try{
 | 
			
		||||
      Class c=Class.forName(session.getConfig("ecdh-sha2-nistp"));
 | 
			
		||||
      ecdh=(ECDH)(c.newInstance());
 | 
			
		||||
      ecdh.init(key_size);
 | 
			
		||||
 | 
			
		||||
      Q_C = ecdh.getQ();
 | 
			
		||||
      buf.putString(Q_C);
 | 
			
		||||
    }
 | 
			
		||||
    catch(Exception e){
 | 
			
		||||
      if(e instanceof Throwable)
 | 
			
		||||
        throw new JSchException(e.toString(), (Throwable)e);
 | 
			
		||||
      throw new JSchException(e.toString());
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    if(V_S==null){  // This is a really ugly hack for Session.checkKexes ;-(
 | 
			
		||||
      return;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    session.write(packet);
 | 
			
		||||
 | 
			
		||||
    if(JSch.getLogger().isEnabled(Logger.INFO)){
 | 
			
		||||
      JSch.getLogger().log(Logger.INFO, 
 | 
			
		||||
                           "SSH_MSG_KEX_ECDH_INIT sent");
 | 
			
		||||
      JSch.getLogger().log(Logger.INFO, 
 | 
			
		||||
                           "expecting SSH_MSG_KEX_ECDH_REPLY");
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    state=SSH_MSG_KEX_ECDH_REPLY;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  public boolean next(Buffer _buf) throws Exception{
 | 
			
		||||
    int i,j;
 | 
			
		||||
    switch(state){
 | 
			
		||||
    case SSH_MSG_KEX_ECDH_REPLY:
 | 
			
		||||
      // The server responds with:
 | 
			
		||||
      // byte     SSH_MSG_KEX_ECDH_REPLY
 | 
			
		||||
      // string   K_S, server's public host key
 | 
			
		||||
      // string   Q_S, server's ephemeral public key octet string
 | 
			
		||||
      // string   the signature on the exchange hash
 | 
			
		||||
      j=_buf.getInt();
 | 
			
		||||
      j=_buf.getByte();
 | 
			
		||||
      j=_buf.getByte();
 | 
			
		||||
      if(j!=31){
 | 
			
		||||
	System.err.println("type: must be 31 "+j);
 | 
			
		||||
	return false;
 | 
			
		||||
      }
 | 
			
		||||
 | 
			
		||||
      K_S=_buf.getString();
 | 
			
		||||
 | 
			
		||||
      byte[] Q_S=_buf.getString();
 | 
			
		||||
 | 
			
		||||
      byte[][] r_s = KeyPairECDSA.fromPoint(Q_S);
 | 
			
		||||
 | 
			
		||||
      // RFC 5656,
 | 
			
		||||
      // 4. ECDH Key Exchange
 | 
			
		||||
      //   All elliptic curve public keys MUST be validated after they are
 | 
			
		||||
      //   received.  An example of a validation algorithm can be found in
 | 
			
		||||
      //   Section 3.2.2 of [SEC1].  If a key fails validation,
 | 
			
		||||
      //   the key exchange MUST fail.
 | 
			
		||||
      if(!ecdh.validate(r_s[0], r_s[1])){
 | 
			
		||||
	return false;
 | 
			
		||||
      }
 | 
			
		||||
 | 
			
		||||
      K = ecdh.getSecret(r_s[0], r_s[1]);
 | 
			
		||||
      K=normalize(K);
 | 
			
		||||
 | 
			
		||||
      byte[] sig_of_H=_buf.getString();
 | 
			
		||||
 | 
			
		||||
      //The hash H is computed as the HASH hash of the concatenation of the
 | 
			
		||||
      //following:
 | 
			
		||||
      // string   V_C, client's identification string (CR and LF excluded)
 | 
			
		||||
      // string   V_S, server's identification string (CR and LF excluded)
 | 
			
		||||
      // string   I_C, payload of the client's SSH_MSG_KEXINIT
 | 
			
		||||
      // string   I_S, payload of the server's SSH_MSG_KEXINIT
 | 
			
		||||
      // string   K_S, server's public host key
 | 
			
		||||
      // string   Q_C, client's ephemeral public key octet string
 | 
			
		||||
      // string   Q_S, server's ephemeral public key octet string
 | 
			
		||||
      // mpint    K,   shared secret
 | 
			
		||||
 | 
			
		||||
      // This value is called the exchange hash, and it is used to authenti-
 | 
			
		||||
      // cate the key exchange.
 | 
			
		||||
      buf.reset();
 | 
			
		||||
      buf.putString(V_C); buf.putString(V_S);
 | 
			
		||||
      buf.putString(I_C); buf.putString(I_S);
 | 
			
		||||
      buf.putString(K_S);
 | 
			
		||||
      buf.putString(Q_C); buf.putString(Q_S);
 | 
			
		||||
      buf.putMPInt(K);
 | 
			
		||||
      byte[] foo=new byte[buf.getLength()];
 | 
			
		||||
      buf.getByte(foo);
 | 
			
		||||
 | 
			
		||||
      sha.update(foo, 0, foo.length);
 | 
			
		||||
      H=sha.digest();
 | 
			
		||||
 | 
			
		||||
      i=0;
 | 
			
		||||
      j=0;
 | 
			
		||||
      j=((K_S[i++]<<24)&0xff000000)|((K_S[i++]<<16)&0x00ff0000)|
 | 
			
		||||
	((K_S[i++]<<8)&0x0000ff00)|((K_S[i++])&0x000000ff);
 | 
			
		||||
      String alg=Util.byte2str(K_S, i, j);
 | 
			
		||||
      i+=j;
 | 
			
		||||
 | 
			
		||||
      boolean result = verify(alg, K_S, i, sig_of_H);
 | 
			
		||||
 | 
			
		||||
      state=STATE_END;
 | 
			
		||||
      return result;
 | 
			
		||||
    }
 | 
			
		||||
    return false;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  public int getState(){return state; }
 | 
			
		||||
}
 | 
			
		||||
@@ -1,6 +1,6 @@
 | 
			
		||||
/* -*-mode:java; c-basic-offset:2; indent-tabs-mode:nil -*- */
 | 
			
		||||
/*
 | 
			
		||||
Copyright (c) 2002-2012 ymnk, JCraft,Inc. All rights reserved.
 | 
			
		||||
Copyright (c) 2002-2016 ymnk, JCraft,Inc. All rights reserved.
 | 
			
		||||
 | 
			
		||||
Redistribution and use in source and binary forms, with or without
 | 
			
		||||
modification, are permitted provided that the following conditions are met:
 | 
			
		||||
@@ -55,25 +55,15 @@ public class DHG1 extends KeyExchange{
 | 
			
		||||
  private static final int SSH_MSG_KEXDH_INIT=                     30;
 | 
			
		||||
  private static final int SSH_MSG_KEXDH_REPLY=                    31;
 | 
			
		||||
 | 
			
		||||
  static final int RSA=0;
 | 
			
		||||
  static final int DSS=1;
 | 
			
		||||
  private int type=0;
 | 
			
		||||
 | 
			
		||||
  private int state;
 | 
			
		||||
 | 
			
		||||
  DH dh;
 | 
			
		||||
//  HASH sha;
 | 
			
		||||
 | 
			
		||||
//  byte[] K;
 | 
			
		||||
//  byte[] H;
 | 
			
		||||
 | 
			
		||||
  byte[] V_S;
 | 
			
		||||
  byte[] V_C;
 | 
			
		||||
  byte[] I_S;
 | 
			
		||||
  byte[] I_C;
 | 
			
		||||
 | 
			
		||||
//  byte[] K_S;
 | 
			
		||||
 | 
			
		||||
  byte[] e;
 | 
			
		||||
 | 
			
		||||
  private Buffer buf;
 | 
			
		||||
@@ -87,8 +77,6 @@ public class DHG1 extends KeyExchange{
 | 
			
		||||
    this.I_S=I_S;      
 | 
			
		||||
    this.I_C=I_C;      
 | 
			
		||||
 | 
			
		||||
//    sha=new SHA1();
 | 
			
		||||
//    sha.init();
 | 
			
		||||
    try{
 | 
			
		||||
      Class c=Class.forName(session.getConfig("sha-1"));
 | 
			
		||||
      sha=(HASH)(c.newInstance());
 | 
			
		||||
@@ -155,24 +143,14 @@ public class DHG1 extends KeyExchange{
 | 
			
		||||
      }
 | 
			
		||||
 | 
			
		||||
      K_S=_buf.getString();
 | 
			
		||||
      // K_S is server_key_blob, which includes ....
 | 
			
		||||
      // string ssh-dss
 | 
			
		||||
      // impint p of dsa
 | 
			
		||||
      // impint q of dsa
 | 
			
		||||
      // impint g of dsa
 | 
			
		||||
      // impint pub_key of dsa
 | 
			
		||||
      //System.err.print("K_S: "); //dump(K_S, 0, K_S.length);
 | 
			
		||||
 | 
			
		||||
      byte[] f=_buf.getMPInt();
 | 
			
		||||
      byte[] sig_of_H=_buf.getString();
 | 
			
		||||
      /*
 | 
			
		||||
for(int ii=0; ii<sig_of_H.length;ii++){
 | 
			
		||||
  System.err.print(Integer.toHexString(sig_of_H[ii]&0xff));
 | 
			
		||||
  System.err.print(": ");
 | 
			
		||||
}
 | 
			
		||||
System.err.println("");
 | 
			
		||||
      */
 | 
			
		||||
 | 
			
		||||
      dh.setF(f);
 | 
			
		||||
 | 
			
		||||
      dh.checkRange();
 | 
			
		||||
 | 
			
		||||
      K=normalize(dh.getK());
 | 
			
		||||
 | 
			
		||||
      //The hash H is computed as the HASH hash of the concatenation of the
 | 
			
		||||
@@ -206,105 +184,13 @@ System.err.println("");
 | 
			
		||||
      String alg=Util.byte2str(K_S, i, j);
 | 
			
		||||
      i+=j;
 | 
			
		||||
 | 
			
		||||
      boolean result=false;
 | 
			
		||||
      boolean result = verify(alg, K_S, i, sig_of_H);
 | 
			
		||||
 | 
			
		||||
      if(alg.equals("ssh-rsa")){
 | 
			
		||||
	byte[] tmp;
 | 
			
		||||
	byte[] ee;
 | 
			
		||||
	byte[] n;
 | 
			
		||||
 | 
			
		||||
	type=RSA;
 | 
			
		||||
 | 
			
		||||
	j=((K_S[i++]<<24)&0xff000000)|((K_S[i++]<<16)&0x00ff0000)|
 | 
			
		||||
	  ((K_S[i++]<<8)&0x0000ff00)|((K_S[i++])&0x000000ff);
 | 
			
		||||
	tmp=new byte[j]; System.arraycopy(K_S, i, tmp, 0, j); i+=j;
 | 
			
		||||
	ee=tmp;
 | 
			
		||||
	j=((K_S[i++]<<24)&0xff000000)|((K_S[i++]<<16)&0x00ff0000)|
 | 
			
		||||
	  ((K_S[i++]<<8)&0x0000ff00)|((K_S[i++])&0x000000ff);
 | 
			
		||||
	tmp=new byte[j]; System.arraycopy(K_S, i, tmp, 0, j); i+=j;
 | 
			
		||||
	n=tmp;
 | 
			
		||||
	
 | 
			
		||||
//	SignatureRSA sig=new SignatureRSA();
 | 
			
		||||
//	sig.init();
 | 
			
		||||
 | 
			
		||||
	SignatureRSA sig=null;
 | 
			
		||||
	try{
 | 
			
		||||
	  Class c=Class.forName(session.getConfig("signature.rsa"));
 | 
			
		||||
	  sig=(SignatureRSA)(c.newInstance());
 | 
			
		||||
	  sig.init();
 | 
			
		||||
	}
 | 
			
		||||
	catch(Exception e){
 | 
			
		||||
	  System.err.println(e);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	sig.setPubKey(ee, n);   
 | 
			
		||||
	sig.update(H);
 | 
			
		||||
	result=sig.verify(sig_of_H);
 | 
			
		||||
 | 
			
		||||
        if(JSch.getLogger().isEnabled(Logger.INFO)){
 | 
			
		||||
          JSch.getLogger().log(Logger.INFO, 
 | 
			
		||||
                               "ssh_rsa_verify: signature "+result);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
      }
 | 
			
		||||
      else if(alg.equals("ssh-dss")){
 | 
			
		||||
	byte[] q=null;
 | 
			
		||||
	byte[] tmp;
 | 
			
		||||
	byte[] p;
 | 
			
		||||
	byte[] g;
 | 
			
		||||
      
 | 
			
		||||
	type=DSS;
 | 
			
		||||
 | 
			
		||||
	j=((K_S[i++]<<24)&0xff000000)|((K_S[i++]<<16)&0x00ff0000)|
 | 
			
		||||
	  ((K_S[i++]<<8)&0x0000ff00)|((K_S[i++])&0x000000ff);
 | 
			
		||||
	tmp=new byte[j]; System.arraycopy(K_S, i, tmp, 0, j); i+=j;
 | 
			
		||||
	p=tmp;
 | 
			
		||||
	j=((K_S[i++]<<24)&0xff000000)|((K_S[i++]<<16)&0x00ff0000)|
 | 
			
		||||
	  ((K_S[i++]<<8)&0x0000ff00)|((K_S[i++])&0x000000ff);
 | 
			
		||||
	tmp=new byte[j]; System.arraycopy(K_S, i, tmp, 0, j); i+=j;
 | 
			
		||||
	q=tmp;
 | 
			
		||||
	j=((K_S[i++]<<24)&0xff000000)|((K_S[i++]<<16)&0x00ff0000)|
 | 
			
		||||
	  ((K_S[i++]<<8)&0x0000ff00)|((K_S[i++])&0x000000ff);
 | 
			
		||||
	tmp=new byte[j]; System.arraycopy(K_S, i, tmp, 0, j); i+=j;
 | 
			
		||||
	g=tmp;
 | 
			
		||||
	j=((K_S[i++]<<24)&0xff000000)|((K_S[i++]<<16)&0x00ff0000)|
 | 
			
		||||
	  ((K_S[i++]<<8)&0x0000ff00)|((K_S[i++])&0x000000ff);
 | 
			
		||||
	tmp=new byte[j]; System.arraycopy(K_S, i, tmp, 0, j); i+=j;
 | 
			
		||||
	f=tmp;
 | 
			
		||||
//	SignatureDSA sig=new SignatureDSA();
 | 
			
		||||
//	sig.init();
 | 
			
		||||
	SignatureDSA sig=null;
 | 
			
		||||
	try{
 | 
			
		||||
	  Class c=Class.forName(session.getConfig("signature.dss"));
 | 
			
		||||
	  sig=(SignatureDSA)(c.newInstance());
 | 
			
		||||
	  sig.init();
 | 
			
		||||
	}
 | 
			
		||||
	catch(Exception e){
 | 
			
		||||
	  System.err.println(e);
 | 
			
		||||
	}
 | 
			
		||||
	sig.setPubKey(f, p, q, g);   
 | 
			
		||||
	sig.update(H);
 | 
			
		||||
	result=sig.verify(sig_of_H);
 | 
			
		||||
 | 
			
		||||
        if(JSch.getLogger().isEnabled(Logger.INFO)){
 | 
			
		||||
          JSch.getLogger().log(Logger.INFO, 
 | 
			
		||||
                               "ssh_dss_verify: signature "+result);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
      }
 | 
			
		||||
      else{
 | 
			
		||||
	System.err.println("unknown alg");
 | 
			
		||||
      }	    
 | 
			
		||||
      state=STATE_END;
 | 
			
		||||
      return result;
 | 
			
		||||
    }
 | 
			
		||||
    return false;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  public String getKeyType(){
 | 
			
		||||
    if(type==DSS) return "DSA";
 | 
			
		||||
    return "RSA";
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  public int getState(){return state; }
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -1,6 +1,6 @@
 | 
			
		||||
/* -*-mode:java; c-basic-offset:2; indent-tabs-mode:nil -*- */
 | 
			
		||||
/*
 | 
			
		||||
Copyright (c) 2002-2012 ymnk, JCraft,Inc. All rights reserved.
 | 
			
		||||
Copyright (c) 2002-2016 ymnk, JCraft,Inc. All rights reserved.
 | 
			
		||||
 | 
			
		||||
Redistribution and use in source and binary forms, with or without
 | 
			
		||||
modification, are permitted provided that the following conditions are met:
 | 
			
		||||
@@ -71,10 +71,6 @@ public class DHG14 extends KeyExchange{
 | 
			
		||||
  private static final int SSH_MSG_KEXDH_INIT=                     30;
 | 
			
		||||
  private static final int SSH_MSG_KEXDH_REPLY=                    31;
 | 
			
		||||
 | 
			
		||||
  static final int RSA=0;
 | 
			
		||||
  static final int DSS=1;
 | 
			
		||||
  private int type=0;
 | 
			
		||||
 | 
			
		||||
  private int state;
 | 
			
		||||
 | 
			
		||||
  DH dh;
 | 
			
		||||
@@ -166,17 +162,14 @@ public class DHG14 extends KeyExchange{
 | 
			
		||||
      }
 | 
			
		||||
 | 
			
		||||
      K_S=_buf.getString();
 | 
			
		||||
      // K_S is server_key_blob, which includes ....
 | 
			
		||||
      // string ssh-dss
 | 
			
		||||
      // impint p of dsa
 | 
			
		||||
      // impint q of dsa
 | 
			
		||||
      // impint g of dsa
 | 
			
		||||
      // impint pub_key of dsa
 | 
			
		||||
      //System.err.print("K_S: "); //dump(K_S, 0, K_S.length);
 | 
			
		||||
 | 
			
		||||
      byte[] f=_buf.getMPInt();
 | 
			
		||||
      byte[] sig_of_H=_buf.getString();
 | 
			
		||||
 | 
			
		||||
      dh.setF(f);
 | 
			
		||||
 | 
			
		||||
      dh.checkRange();
 | 
			
		||||
 | 
			
		||||
      K=normalize(dh.getK());
 | 
			
		||||
 | 
			
		||||
      //The hash H is computed as the HASH hash of the concatenation of the
 | 
			
		||||
@@ -210,101 +203,13 @@ public class DHG14 extends KeyExchange{
 | 
			
		||||
      String alg=Util.byte2str(K_S, i, j);
 | 
			
		||||
      i+=j;
 | 
			
		||||
 | 
			
		||||
      boolean result=false;
 | 
			
		||||
      boolean result = verify(alg, K_S, i, sig_of_H);
 | 
			
		||||
 | 
			
		||||
      if(alg.equals("ssh-rsa")){
 | 
			
		||||
	byte[] tmp;
 | 
			
		||||
	byte[] ee;
 | 
			
		||||
	byte[] n;
 | 
			
		||||
 | 
			
		||||
	type=RSA;
 | 
			
		||||
 | 
			
		||||
	j=((K_S[i++]<<24)&0xff000000)|((K_S[i++]<<16)&0x00ff0000)|
 | 
			
		||||
	  ((K_S[i++]<<8)&0x0000ff00)|((K_S[i++])&0x000000ff);
 | 
			
		||||
	tmp=new byte[j]; System.arraycopy(K_S, i, tmp, 0, j); i+=j;
 | 
			
		||||
	ee=tmp;
 | 
			
		||||
	j=((K_S[i++]<<24)&0xff000000)|((K_S[i++]<<16)&0x00ff0000)|
 | 
			
		||||
	  ((K_S[i++]<<8)&0x0000ff00)|((K_S[i++])&0x000000ff);
 | 
			
		||||
	tmp=new byte[j]; System.arraycopy(K_S, i, tmp, 0, j); i+=j;
 | 
			
		||||
	n=tmp;
 | 
			
		||||
	
 | 
			
		||||
	SignatureRSA sig=null;
 | 
			
		||||
	try{
 | 
			
		||||
	  Class c=Class.forName(session.getConfig("signature.rsa"));
 | 
			
		||||
	  sig=(SignatureRSA)(c.newInstance());
 | 
			
		||||
	  sig.init();
 | 
			
		||||
	}
 | 
			
		||||
	catch(Exception e){
 | 
			
		||||
	  System.err.println(e);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	sig.setPubKey(ee, n);   
 | 
			
		||||
	sig.update(H);
 | 
			
		||||
	result=sig.verify(sig_of_H);
 | 
			
		||||
 | 
			
		||||
        if(JSch.getLogger().isEnabled(Logger.INFO)){
 | 
			
		||||
          JSch.getLogger().log(Logger.INFO, 
 | 
			
		||||
                               "ssh_rsa_verify: signature "+result);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
      }
 | 
			
		||||
      else if(alg.equals("ssh-dss")){
 | 
			
		||||
	byte[] q=null;
 | 
			
		||||
	byte[] tmp;
 | 
			
		||||
	byte[] p;
 | 
			
		||||
	byte[] g;
 | 
			
		||||
      
 | 
			
		||||
	type=DSS;
 | 
			
		||||
 | 
			
		||||
	j=((K_S[i++]<<24)&0xff000000)|((K_S[i++]<<16)&0x00ff0000)|
 | 
			
		||||
	  ((K_S[i++]<<8)&0x0000ff00)|((K_S[i++])&0x000000ff);
 | 
			
		||||
	tmp=new byte[j]; System.arraycopy(K_S, i, tmp, 0, j); i+=j;
 | 
			
		||||
	p=tmp;
 | 
			
		||||
	j=((K_S[i++]<<24)&0xff000000)|((K_S[i++]<<16)&0x00ff0000)|
 | 
			
		||||
	  ((K_S[i++]<<8)&0x0000ff00)|((K_S[i++])&0x000000ff);
 | 
			
		||||
	tmp=new byte[j]; System.arraycopy(K_S, i, tmp, 0, j); i+=j;
 | 
			
		||||
	q=tmp;
 | 
			
		||||
	j=((K_S[i++]<<24)&0xff000000)|((K_S[i++]<<16)&0x00ff0000)|
 | 
			
		||||
	  ((K_S[i++]<<8)&0x0000ff00)|((K_S[i++])&0x000000ff);
 | 
			
		||||
	tmp=new byte[j]; System.arraycopy(K_S, i, tmp, 0, j); i+=j;
 | 
			
		||||
	g=tmp;
 | 
			
		||||
	j=((K_S[i++]<<24)&0xff000000)|((K_S[i++]<<16)&0x00ff0000)|
 | 
			
		||||
	  ((K_S[i++]<<8)&0x0000ff00)|((K_S[i++])&0x000000ff);
 | 
			
		||||
	tmp=new byte[j]; System.arraycopy(K_S, i, tmp, 0, j); i+=j;
 | 
			
		||||
	f=tmp;
 | 
			
		||||
 | 
			
		||||
	SignatureDSA sig=null;
 | 
			
		||||
	try{
 | 
			
		||||
	  Class c=Class.forName(session.getConfig("signature.dss"));
 | 
			
		||||
	  sig=(SignatureDSA)(c.newInstance());
 | 
			
		||||
	  sig.init();
 | 
			
		||||
	}
 | 
			
		||||
	catch(Exception e){
 | 
			
		||||
	  System.err.println(e);
 | 
			
		||||
	}
 | 
			
		||||
	sig.setPubKey(f, p, q, g);   
 | 
			
		||||
	sig.update(H);
 | 
			
		||||
	result=sig.verify(sig_of_H);
 | 
			
		||||
 | 
			
		||||
        if(JSch.getLogger().isEnabled(Logger.INFO)){
 | 
			
		||||
          JSch.getLogger().log(Logger.INFO, 
 | 
			
		||||
                               "ssh_dss_verify: signature "+result);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
      }
 | 
			
		||||
      else{
 | 
			
		||||
	System.err.println("unknown alg");
 | 
			
		||||
      }	    
 | 
			
		||||
      state=STATE_END;
 | 
			
		||||
      return result;
 | 
			
		||||
    }
 | 
			
		||||
    return false;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  public String getKeyType(){
 | 
			
		||||
    if(type==DSS) return "DSA";
 | 
			
		||||
    return "RSA";
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  public int getState(){return state; }
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -1,6 +1,6 @@
 | 
			
		||||
/* -*-mode:java; c-basic-offset:2; indent-tabs-mode:nil -*- */
 | 
			
		||||
/*
 | 
			
		||||
Copyright (c) 2002-2012 ymnk, JCraft,Inc. All rights reserved.
 | 
			
		||||
Copyright (c) 2002-2016 ymnk, JCraft,Inc. All rights reserved.
 | 
			
		||||
 | 
			
		||||
Redistribution and use in source and binary forms, with or without
 | 
			
		||||
modification, are permitted provided that the following conditions are met:
 | 
			
		||||
@@ -37,21 +37,11 @@ public class DHGEX extends KeyExchange{
 | 
			
		||||
  private static final int SSH_MSG_KEX_DH_GEX_REQUEST=             34;
 | 
			
		||||
 | 
			
		||||
  static int min=1024;
 | 
			
		||||
 | 
			
		||||
//  static int min=512;
 | 
			
		||||
  static int preferred=1024;
 | 
			
		||||
  static int max=1024;
 | 
			
		||||
 | 
			
		||||
//  static int preferred=1024;
 | 
			
		||||
//  static int max=2000;
 | 
			
		||||
 | 
			
		||||
  static final int RSA=0;
 | 
			
		||||
  static final int DSS=1;
 | 
			
		||||
  private int type=0;
 | 
			
		||||
  int max=1024;
 | 
			
		||||
 | 
			
		||||
  private int state;
 | 
			
		||||
 | 
			
		||||
//  com.jcraft.jsch.DH dh;
 | 
			
		||||
  DH dh;
 | 
			
		||||
 | 
			
		||||
  byte[] V_S;
 | 
			
		||||
@@ -65,7 +55,8 @@ public class DHGEX extends KeyExchange{
 | 
			
		||||
  private byte[] p;
 | 
			
		||||
  private byte[] g;
 | 
			
		||||
  private byte[] e;
 | 
			
		||||
  //private byte[] f;
 | 
			
		||||
 | 
			
		||||
  protected String hash="sha-1";
 | 
			
		||||
 | 
			
		||||
  public void init(Session session,
 | 
			
		||||
		   byte[] V_S, byte[] V_C, byte[] I_S, byte[] I_C) throws Exception{
 | 
			
		||||
@@ -76,7 +67,7 @@ public class DHGEX extends KeyExchange{
 | 
			
		||||
    this.I_C=I_C;      
 | 
			
		||||
 | 
			
		||||
    try{
 | 
			
		||||
      Class c=Class.forName(session.getConfig("sha-1"));
 | 
			
		||||
      Class c=Class.forName(session.getConfig(hash));
 | 
			
		||||
      sha=(HASH)(c.newInstance());
 | 
			
		||||
      sha.init();
 | 
			
		||||
    }
 | 
			
		||||
@@ -89,11 +80,13 @@ public class DHGEX extends KeyExchange{
 | 
			
		||||
 | 
			
		||||
    try{
 | 
			
		||||
      Class c=Class.forName(session.getConfig("dh"));
 | 
			
		||||
      // Since JDK8, SunJCE has lifted the keysize restrictions
 | 
			
		||||
      // from 1024 to 2048 for DH.
 | 
			
		||||
      preferred = max = check2048(c, max); 
 | 
			
		||||
      dh=(com.jcraft.jsch.DH)(c.newInstance());
 | 
			
		||||
      dh.init();
 | 
			
		||||
    }
 | 
			
		||||
    catch(Exception e){
 | 
			
		||||
//      System.err.println(e);
 | 
			
		||||
      throw e;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
@@ -131,18 +124,9 @@ public class DHGEX extends KeyExchange{
 | 
			
		||||
 | 
			
		||||
      p=_buf.getMPInt();
 | 
			
		||||
      g=_buf.getMPInt();
 | 
			
		||||
      /*
 | 
			
		||||
for(int iii=0; iii<p.length; iii++){
 | 
			
		||||
System.err.println("0x"+Integer.toHexString(p[iii]&0xff)+",");
 | 
			
		||||
}
 | 
			
		||||
System.err.println("");
 | 
			
		||||
for(int iii=0; iii<g.length; iii++){
 | 
			
		||||
System.err.println("0x"+Integer.toHexString(g[iii]&0xff)+",");
 | 
			
		||||
}
 | 
			
		||||
      */
 | 
			
		||||
 | 
			
		||||
      dh.setP(p);
 | 
			
		||||
      dh.setG(g);
 | 
			
		||||
 | 
			
		||||
      // The client responds with:
 | 
			
		||||
      // byte  SSH_MSG_KEX_DH_GEX_INIT(32)
 | 
			
		||||
      // mpint e <- g^x mod p
 | 
			
		||||
@@ -181,18 +165,14 @@ System.err.println("0x"+Integer.toHexString(g[iii]&0xff)+",");
 | 
			
		||||
      }
 | 
			
		||||
 | 
			
		||||
      K_S=_buf.getString();
 | 
			
		||||
      // K_S is server_key_blob, which includes ....
 | 
			
		||||
      // string ssh-dss
 | 
			
		||||
      // impint p of dsa
 | 
			
		||||
      // impint q of dsa
 | 
			
		||||
      // impint g of dsa
 | 
			
		||||
      // impint pub_key of dsa
 | 
			
		||||
      //System.err.print("K_S: "); dump(K_S, 0, K_S.length);
 | 
			
		||||
 | 
			
		||||
      byte[] f=_buf.getMPInt();
 | 
			
		||||
      byte[] sig_of_H=_buf.getString();
 | 
			
		||||
 | 
			
		||||
      dh.setF(f);
 | 
			
		||||
 | 
			
		||||
      dh.checkRange();
 | 
			
		||||
 | 
			
		||||
      K=normalize(dh.getK());
 | 
			
		||||
 | 
			
		||||
      //The hash H is computed as the HASH hash of the concatenation of the
 | 
			
		||||
@@ -236,105 +216,30 @@ System.err.println("0x"+Integer.toHexString(g[iii]&0xff)+",");
 | 
			
		||||
      String alg=Util.byte2str(K_S, i, j);
 | 
			
		||||
      i+=j;
 | 
			
		||||
 | 
			
		||||
      boolean result=false;
 | 
			
		||||
      if(alg.equals("ssh-rsa")){
 | 
			
		||||
	byte[] tmp;
 | 
			
		||||
	byte[] ee;
 | 
			
		||||
	byte[] n;
 | 
			
		||||
	
 | 
			
		||||
	type=RSA;
 | 
			
		||||
      boolean result = verify(alg, K_S, i, sig_of_H);
 | 
			
		||||
 | 
			
		||||
	j=((K_S[i++]<<24)&0xff000000)|((K_S[i++]<<16)&0x00ff0000)|
 | 
			
		||||
	  ((K_S[i++]<<8)&0x0000ff00)|((K_S[i++])&0x000000ff);
 | 
			
		||||
	tmp=new byte[j]; System.arraycopy(K_S, i, tmp, 0, j); i+=j;
 | 
			
		||||
	ee=tmp;
 | 
			
		||||
	j=((K_S[i++]<<24)&0xff000000)|((K_S[i++]<<16)&0x00ff0000)|
 | 
			
		||||
	  ((K_S[i++]<<8)&0x0000ff00)|((K_S[i++])&0x000000ff);
 | 
			
		||||
	tmp=new byte[j]; System.arraycopy(K_S, i, tmp, 0, j); i+=j;
 | 
			
		||||
	n=tmp;
 | 
			
		||||
 | 
			
		||||
//	SignatureRSA sig=new SignatureRSA();
 | 
			
		||||
//	sig.init();
 | 
			
		||||
 | 
			
		||||
	SignatureRSA sig=null;
 | 
			
		||||
	try{
 | 
			
		||||
	  Class c=Class.forName(session.getConfig("signature.rsa"));
 | 
			
		||||
	  sig=(SignatureRSA)(c.newInstance());
 | 
			
		||||
	  sig.init();
 | 
			
		||||
	}
 | 
			
		||||
	catch(Exception e){
 | 
			
		||||
	  System.err.println(e);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	sig.setPubKey(ee, n);   
 | 
			
		||||
	sig.update(H);
 | 
			
		||||
	result=sig.verify(sig_of_H);
 | 
			
		||||
 | 
			
		||||
        if(JSch.getLogger().isEnabled(Logger.INFO)){
 | 
			
		||||
          JSch.getLogger().log(Logger.INFO, 
 | 
			
		||||
                               "ssh_rsa_verify: signature "+result);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
      }
 | 
			
		||||
      else if(alg.equals("ssh-dss")){
 | 
			
		||||
	byte[] q=null;
 | 
			
		||||
	byte[] tmp;
 | 
			
		||||
 | 
			
		||||
	type=DSS;
 | 
			
		||||
 | 
			
		||||
	j=((K_S[i++]<<24)&0xff000000)|((K_S[i++]<<16)&0x00ff0000)|
 | 
			
		||||
	  ((K_S[i++]<<8)&0x0000ff00)|((K_S[i++])&0x000000ff);
 | 
			
		||||
	tmp=new byte[j]; System.arraycopy(K_S, i, tmp, 0, j); i+=j;
 | 
			
		||||
	p=tmp;
 | 
			
		||||
	j=((K_S[i++]<<24)&0xff000000)|((K_S[i++]<<16)&0x00ff0000)|
 | 
			
		||||
	  ((K_S[i++]<<8)&0x0000ff00)|((K_S[i++])&0x000000ff);
 | 
			
		||||
	tmp=new byte[j]; System.arraycopy(K_S, i, tmp, 0, j); i+=j;
 | 
			
		||||
	q=tmp;
 | 
			
		||||
	j=((K_S[i++]<<24)&0xff000000)|((K_S[i++]<<16)&0x00ff0000)|
 | 
			
		||||
	  ((K_S[i++]<<8)&0x0000ff00)|((K_S[i++])&0x000000ff);
 | 
			
		||||
	tmp=new byte[j]; System.arraycopy(K_S, i, tmp, 0, j); i+=j;
 | 
			
		||||
	g=tmp;
 | 
			
		||||
	j=((K_S[i++]<<24)&0xff000000)|((K_S[i++]<<16)&0x00ff0000)|
 | 
			
		||||
	  ((K_S[i++]<<8)&0x0000ff00)|((K_S[i++])&0x000000ff);
 | 
			
		||||
	tmp=new byte[j]; System.arraycopy(K_S, i, tmp, 0, j); i+=j;
 | 
			
		||||
	f=tmp;
 | 
			
		||||
	
 | 
			
		||||
//	SignatureDSA sig=new SignatureDSA();
 | 
			
		||||
//	sig.init();
 | 
			
		||||
 | 
			
		||||
	SignatureDSA sig=null;
 | 
			
		||||
	try{
 | 
			
		||||
	  Class c=Class.forName(session.getConfig("signature.dss"));
 | 
			
		||||
	  sig=(SignatureDSA)(c.newInstance());
 | 
			
		||||
	  sig.init();
 | 
			
		||||
	}
 | 
			
		||||
	catch(Exception e){
 | 
			
		||||
	  System.err.println(e);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	sig.setPubKey(f, p, q, g);   
 | 
			
		||||
	sig.update(H);
 | 
			
		||||
	result=sig.verify(sig_of_H);
 | 
			
		||||
 | 
			
		||||
        if(JSch.getLogger().isEnabled(Logger.INFO)){
 | 
			
		||||
          JSch.getLogger().log(Logger.INFO, 
 | 
			
		||||
                               "ssh_dss_verify: signature "+result);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
      }
 | 
			
		||||
      else{
 | 
			
		||||
	System.err.println("unknown alg");
 | 
			
		||||
      }	    
 | 
			
		||||
      state=STATE_END;
 | 
			
		||||
      return result;
 | 
			
		||||
    }
 | 
			
		||||
    return false;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  public String getKeyType(){
 | 
			
		||||
    if(type==DSS) return "DSA";
 | 
			
		||||
    return "RSA";
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  public int getState(){return state; }
 | 
			
		||||
 | 
			
		||||
  protected int check2048(Class c, int _max) throws Exception {
 | 
			
		||||
    DH dh=(com.jcraft.jsch.DH)(c.newInstance());
 | 
			
		||||
    dh.init();
 | 
			
		||||
    byte[] foo = new byte[257];
 | 
			
		||||
    foo[1]=(byte)0xdd;
 | 
			
		||||
    foo[256]=0x73;
 | 
			
		||||
    dh.setP(foo);
 | 
			
		||||
    byte[] bar = {(byte)0x02};
 | 
			
		||||
    dh.setG(bar);
 | 
			
		||||
    try {
 | 
			
		||||
      dh.getE();
 | 
			
		||||
      _max=2048;
 | 
			
		||||
    }
 | 
			
		||||
    catch(Exception e){ }
 | 
			
		||||
    return _max;
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -1,6 +1,6 @@
 | 
			
		||||
/* -*-mode:java; c-basic-offset:2; indent-tabs-mode:nil -*- */
 | 
			
		||||
/*
 | 
			
		||||
Copyright (c) 2002-2012 ymnk, JCraft,Inc. All rights reserved.
 | 
			
		||||
Copyright (c) 2002-2016 ymnk, JCraft,Inc. All rights reserved.
 | 
			
		||||
 | 
			
		||||
Redistribution and use in source and binary forms, with or without
 | 
			
		||||
modification, are permitted provided that the following conditions are met:
 | 
			
		||||
@@ -29,312 +29,8 @@ EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 | 
			
		||||
 | 
			
		||||
package com.jcraft.jsch;
 | 
			
		||||
 | 
			
		||||
public class DHGEX256 extends KeyExchange{
 | 
			
		||||
 | 
			
		||||
  private static final int SSH_MSG_KEX_DH_GEX_GROUP=               31;
 | 
			
		||||
  private static final int SSH_MSG_KEX_DH_GEX_INIT=                32;
 | 
			
		||||
  private static final int SSH_MSG_KEX_DH_GEX_REPLY=               33;
 | 
			
		||||
  private static final int SSH_MSG_KEX_DH_GEX_REQUEST=             34;
 | 
			
		||||
 | 
			
		||||
  static int min=1024;
 | 
			
		||||
 | 
			
		||||
//  static int min=512;
 | 
			
		||||
  static int preferred=1024;
 | 
			
		||||
  static int max=1024;
 | 
			
		||||
 | 
			
		||||
//  static int preferred=1024;
 | 
			
		||||
//  static int max=2000;
 | 
			
		||||
 | 
			
		||||
  static final int RSA=0;
 | 
			
		||||
  static final int DSS=1;
 | 
			
		||||
  private int type=0;
 | 
			
		||||
 | 
			
		||||
  private int state;
 | 
			
		||||
 | 
			
		||||
//  com.jcraft.jsch.DH dh;
 | 
			
		||||
  DH dh;
 | 
			
		||||
 | 
			
		||||
  byte[] V_S;
 | 
			
		||||
  byte[] V_C;
 | 
			
		||||
  byte[] I_S;
 | 
			
		||||
  byte[] I_C;
 | 
			
		||||
 | 
			
		||||
  private Buffer buf;
 | 
			
		||||
  private Packet packet;
 | 
			
		||||
 | 
			
		||||
  private byte[] p;
 | 
			
		||||
  private byte[] g;
 | 
			
		||||
  private byte[] e;
 | 
			
		||||
  //private byte[] f;
 | 
			
		||||
 | 
			
		||||
  public void init(Session session,
 | 
			
		||||
		   byte[] V_S, byte[] V_C, byte[] I_S, byte[] I_C) throws Exception{
 | 
			
		||||
    this.session=session;
 | 
			
		||||
    this.V_S=V_S;      
 | 
			
		||||
    this.V_C=V_C;      
 | 
			
		||||
    this.I_S=I_S;      
 | 
			
		||||
    this.I_C=I_C;      
 | 
			
		||||
 | 
			
		||||
    try{
 | 
			
		||||
      Class c=Class.forName(session.getConfig("sha-256"));
 | 
			
		||||
      sha=(HASH)(c.newInstance());
 | 
			
		||||
      sha.init();
 | 
			
		||||
    }
 | 
			
		||||
    catch(Exception e){
 | 
			
		||||
      System.err.println(e);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    buf=new Buffer();
 | 
			
		||||
    packet=new Packet(buf);
 | 
			
		||||
 | 
			
		||||
    try{
 | 
			
		||||
      Class c=Class.forName(session.getConfig("dh"));
 | 
			
		||||
      dh=(com.jcraft.jsch.DH)(c.newInstance());
 | 
			
		||||
      dh.init();
 | 
			
		||||
    }
 | 
			
		||||
    catch(Exception e){
 | 
			
		||||
//      System.err.println(e);
 | 
			
		||||
      throw e;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    packet.reset();
 | 
			
		||||
    buf.putByte((byte)SSH_MSG_KEX_DH_GEX_REQUEST);
 | 
			
		||||
    buf.putInt(min);
 | 
			
		||||
    buf.putInt(preferred);
 | 
			
		||||
    buf.putInt(max);
 | 
			
		||||
    session.write(packet); 
 | 
			
		||||
 | 
			
		||||
    if(JSch.getLogger().isEnabled(Logger.INFO)){
 | 
			
		||||
      JSch.getLogger().log(Logger.INFO, 
 | 
			
		||||
                           "SSH_MSG_KEX_DH_GEX_REQUEST("+min+"<"+preferred+"<"+max+") sent");
 | 
			
		||||
      JSch.getLogger().log(Logger.INFO, 
 | 
			
		||||
                           "expecting SSH_MSG_KEX_DH_GEX_GROUP");
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    state=SSH_MSG_KEX_DH_GEX_GROUP;
 | 
			
		||||
public class DHGEX256 extends DHGEX {
 | 
			
		||||
  DHGEX256(){
 | 
			
		||||
    hash="sha-256";
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  public boolean next(Buffer _buf) throws Exception{
 | 
			
		||||
    int i,j;
 | 
			
		||||
    switch(state){
 | 
			
		||||
    case SSH_MSG_KEX_DH_GEX_GROUP:
 | 
			
		||||
      // byte  SSH_MSG_KEX_DH_GEX_GROUP(31)
 | 
			
		||||
      // mpint p, safe prime
 | 
			
		||||
      // mpint g, generator for subgroup in GF (p)
 | 
			
		||||
      _buf.getInt();
 | 
			
		||||
      _buf.getByte();
 | 
			
		||||
      j=_buf.getByte();
 | 
			
		||||
      if(j!=SSH_MSG_KEX_DH_GEX_GROUP){
 | 
			
		||||
	System.err.println("type: must be SSH_MSG_KEX_DH_GEX_GROUP "+j);
 | 
			
		||||
	return false;
 | 
			
		||||
      }
 | 
			
		||||
 | 
			
		||||
      p=_buf.getMPInt();
 | 
			
		||||
      g=_buf.getMPInt();
 | 
			
		||||
      /*
 | 
			
		||||
for(int iii=0; iii<p.length; iii++){
 | 
			
		||||
System.err.println("0x"+Integer.toHexString(p[iii]&0xff)+",");
 | 
			
		||||
}
 | 
			
		||||
System.err.println("");
 | 
			
		||||
for(int iii=0; iii<g.length; iii++){
 | 
			
		||||
System.err.println("0x"+Integer.toHexString(g[iii]&0xff)+",");
 | 
			
		||||
}
 | 
			
		||||
      */
 | 
			
		||||
      dh.setP(p);
 | 
			
		||||
      dh.setG(g);
 | 
			
		||||
 | 
			
		||||
      // The client responds with:
 | 
			
		||||
      // byte  SSH_MSG_KEX_DH_GEX_INIT(32)
 | 
			
		||||
      // mpint e <- g^x mod p
 | 
			
		||||
      //         x is a random number (1 < x < (p-1)/2)
 | 
			
		||||
 | 
			
		||||
      e=dh.getE();
 | 
			
		||||
 | 
			
		||||
      packet.reset();
 | 
			
		||||
      buf.putByte((byte)SSH_MSG_KEX_DH_GEX_INIT);
 | 
			
		||||
      buf.putMPInt(e);
 | 
			
		||||
      session.write(packet);
 | 
			
		||||
 | 
			
		||||
      if(JSch.getLogger().isEnabled(Logger.INFO)){
 | 
			
		||||
        JSch.getLogger().log(Logger.INFO, 
 | 
			
		||||
                             "SSH_MSG_KEX_DH_GEX_INIT sent");
 | 
			
		||||
        JSch.getLogger().log(Logger.INFO, 
 | 
			
		||||
                             "expecting SSH_MSG_KEX_DH_GEX_REPLY");
 | 
			
		||||
      }
 | 
			
		||||
 | 
			
		||||
      state=SSH_MSG_KEX_DH_GEX_REPLY;
 | 
			
		||||
      return true;
 | 
			
		||||
      //break;
 | 
			
		||||
 | 
			
		||||
    case SSH_MSG_KEX_DH_GEX_REPLY:
 | 
			
		||||
      // The server responds with:
 | 
			
		||||
      // byte      SSH_MSG_KEX_DH_GEX_REPLY(33)
 | 
			
		||||
      // string    server public host key and certificates (K_S)
 | 
			
		||||
      // mpint     f
 | 
			
		||||
      // string    signature of H
 | 
			
		||||
      j=_buf.getInt();
 | 
			
		||||
      j=_buf.getByte();
 | 
			
		||||
      j=_buf.getByte();
 | 
			
		||||
      if(j!=SSH_MSG_KEX_DH_GEX_REPLY){
 | 
			
		||||
	System.err.println("type: must be SSH_MSG_KEX_DH_GEX_REPLY "+j);
 | 
			
		||||
	return false;
 | 
			
		||||
      }
 | 
			
		||||
 | 
			
		||||
      K_S=_buf.getString();
 | 
			
		||||
      // K_S is server_key_blob, which includes ....
 | 
			
		||||
      // string ssh-dss
 | 
			
		||||
      // impint p of dsa
 | 
			
		||||
      // impint q of dsa
 | 
			
		||||
      // impint g of dsa
 | 
			
		||||
      // impint pub_key of dsa
 | 
			
		||||
      //System.err.print("K_S: "); dump(K_S, 0, K_S.length);
 | 
			
		||||
 | 
			
		||||
      byte[] f=_buf.getMPInt();
 | 
			
		||||
      byte[] sig_of_H=_buf.getString();
 | 
			
		||||
 | 
			
		||||
      dh.setF(f);
 | 
			
		||||
      K=normalize(dh.getK());
 | 
			
		||||
 | 
			
		||||
      //The hash H is computed as the HASH hash of the concatenation of the
 | 
			
		||||
      //following:
 | 
			
		||||
      // string    V_C, the client's version string (CR and NL excluded)
 | 
			
		||||
      // string    V_S, the server's version string (CR and NL excluded)
 | 
			
		||||
      // string    I_C, the payload of the client's SSH_MSG_KEXINIT
 | 
			
		||||
      // string    I_S, the payload of the server's SSH_MSG_KEXINIT
 | 
			
		||||
      // string    K_S, the host key
 | 
			
		||||
      // uint32    min, minimal size in bits of an acceptable group
 | 
			
		||||
      // uint32   n, preferred size in bits of the group the server should send
 | 
			
		||||
      // uint32    max, maximal size in bits of an acceptable group
 | 
			
		||||
      // mpint     p, safe prime
 | 
			
		||||
      // mpint     g, generator for subgroup
 | 
			
		||||
      // mpint     e, exchange value sent by the client
 | 
			
		||||
      // mpint     f, exchange value sent by the server
 | 
			
		||||
      // mpint     K, the shared secret
 | 
			
		||||
      // This value is called the exchange hash, and it is used to authenti-
 | 
			
		||||
      // cate the key exchange.
 | 
			
		||||
 | 
			
		||||
      buf.reset();
 | 
			
		||||
      buf.putString(V_C); buf.putString(V_S);
 | 
			
		||||
      buf.putString(I_C); buf.putString(I_S);
 | 
			
		||||
      buf.putString(K_S);
 | 
			
		||||
      buf.putInt(min); buf.putInt(preferred); buf.putInt(max);
 | 
			
		||||
      buf.putMPInt(p); buf.putMPInt(g); buf.putMPInt(e); buf.putMPInt(f);
 | 
			
		||||
      buf.putMPInt(K);
 | 
			
		||||
 | 
			
		||||
      byte[] foo=new byte[buf.getLength()];
 | 
			
		||||
      buf.getByte(foo);
 | 
			
		||||
      sha.update(foo, 0, foo.length);
 | 
			
		||||
 | 
			
		||||
      H=sha.digest();
 | 
			
		||||
 | 
			
		||||
      // System.err.print("H -> "); dump(H, 0, H.length);
 | 
			
		||||
 | 
			
		||||
      i=0;
 | 
			
		||||
      j=0;
 | 
			
		||||
      j=((K_S[i++]<<24)&0xff000000)|((K_S[i++]<<16)&0x00ff0000)|
 | 
			
		||||
	((K_S[i++]<<8)&0x0000ff00)|((K_S[i++])&0x000000ff);
 | 
			
		||||
      String alg=Util.byte2str(K_S, i, j);
 | 
			
		||||
      i+=j;
 | 
			
		||||
 | 
			
		||||
      boolean result=false;
 | 
			
		||||
      if(alg.equals("ssh-rsa")){
 | 
			
		||||
	byte[] tmp;
 | 
			
		||||
	byte[] ee;
 | 
			
		||||
	byte[] n;
 | 
			
		||||
	
 | 
			
		||||
	type=RSA;
 | 
			
		||||
 | 
			
		||||
	j=((K_S[i++]<<24)&0xff000000)|((K_S[i++]<<16)&0x00ff0000)|
 | 
			
		||||
	  ((K_S[i++]<<8)&0x0000ff00)|((K_S[i++])&0x000000ff);
 | 
			
		||||
	tmp=new byte[j]; System.arraycopy(K_S, i, tmp, 0, j); i+=j;
 | 
			
		||||
	ee=tmp;
 | 
			
		||||
	j=((K_S[i++]<<24)&0xff000000)|((K_S[i++]<<16)&0x00ff0000)|
 | 
			
		||||
	  ((K_S[i++]<<8)&0x0000ff00)|((K_S[i++])&0x000000ff);
 | 
			
		||||
	tmp=new byte[j]; System.arraycopy(K_S, i, tmp, 0, j); i+=j;
 | 
			
		||||
	n=tmp;
 | 
			
		||||
 | 
			
		||||
//	SignatureRSA sig=new SignatureRSA();
 | 
			
		||||
//	sig.init();
 | 
			
		||||
 | 
			
		||||
	SignatureRSA sig=null;
 | 
			
		||||
	try{
 | 
			
		||||
	  Class c=Class.forName(session.getConfig("signature.rsa"));
 | 
			
		||||
	  sig=(SignatureRSA)(c.newInstance());
 | 
			
		||||
	  sig.init();
 | 
			
		||||
	}
 | 
			
		||||
	catch(Exception e){
 | 
			
		||||
	  System.err.println(e);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	sig.setPubKey(ee, n);   
 | 
			
		||||
	sig.update(H);
 | 
			
		||||
	result=sig.verify(sig_of_H);
 | 
			
		||||
 | 
			
		||||
        if(JSch.getLogger().isEnabled(Logger.INFO)){
 | 
			
		||||
          JSch.getLogger().log(Logger.INFO, 
 | 
			
		||||
                               "ssh_rsa_verify: signature "+result);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
      }
 | 
			
		||||
      else if(alg.equals("ssh-dss")){
 | 
			
		||||
	byte[] q=null;
 | 
			
		||||
	byte[] tmp;
 | 
			
		||||
 | 
			
		||||
	type=DSS;
 | 
			
		||||
 | 
			
		||||
	j=((K_S[i++]<<24)&0xff000000)|((K_S[i++]<<16)&0x00ff0000)|
 | 
			
		||||
	  ((K_S[i++]<<8)&0x0000ff00)|((K_S[i++])&0x000000ff);
 | 
			
		||||
	tmp=new byte[j]; System.arraycopy(K_S, i, tmp, 0, j); i+=j;
 | 
			
		||||
	p=tmp;
 | 
			
		||||
	j=((K_S[i++]<<24)&0xff000000)|((K_S[i++]<<16)&0x00ff0000)|
 | 
			
		||||
	  ((K_S[i++]<<8)&0x0000ff00)|((K_S[i++])&0x000000ff);
 | 
			
		||||
	tmp=new byte[j]; System.arraycopy(K_S, i, tmp, 0, j); i+=j;
 | 
			
		||||
	q=tmp;
 | 
			
		||||
	j=((K_S[i++]<<24)&0xff000000)|((K_S[i++]<<16)&0x00ff0000)|
 | 
			
		||||
	  ((K_S[i++]<<8)&0x0000ff00)|((K_S[i++])&0x000000ff);
 | 
			
		||||
	tmp=new byte[j]; System.arraycopy(K_S, i, tmp, 0, j); i+=j;
 | 
			
		||||
	g=tmp;
 | 
			
		||||
	j=((K_S[i++]<<24)&0xff000000)|((K_S[i++]<<16)&0x00ff0000)|
 | 
			
		||||
	  ((K_S[i++]<<8)&0x0000ff00)|((K_S[i++])&0x000000ff);
 | 
			
		||||
	tmp=new byte[j]; System.arraycopy(K_S, i, tmp, 0, j); i+=j;
 | 
			
		||||
	f=tmp;
 | 
			
		||||
	
 | 
			
		||||
//	SignatureDSA sig=new SignatureDSA();
 | 
			
		||||
//	sig.init();
 | 
			
		||||
 | 
			
		||||
	SignatureDSA sig=null;
 | 
			
		||||
	try{
 | 
			
		||||
	  Class c=Class.forName(session.getConfig("signature.dss"));
 | 
			
		||||
	  sig=(SignatureDSA)(c.newInstance());
 | 
			
		||||
	  sig.init();
 | 
			
		||||
	}
 | 
			
		||||
	catch(Exception e){
 | 
			
		||||
	  System.err.println(e);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	sig.setPubKey(f, p, q, g);   
 | 
			
		||||
	sig.update(H);
 | 
			
		||||
	result=sig.verify(sig_of_H);
 | 
			
		||||
 | 
			
		||||
        if(JSch.getLogger().isEnabled(Logger.INFO)){
 | 
			
		||||
          JSch.getLogger().log(Logger.INFO, 
 | 
			
		||||
                               "ssh_dss_verify: signature "+result);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
      }
 | 
			
		||||
      else{
 | 
			
		||||
	System.err.println("unknown alg");
 | 
			
		||||
      }	    
 | 
			
		||||
      state=STATE_END;
 | 
			
		||||
      return result;
 | 
			
		||||
    }
 | 
			
		||||
    return false;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  public String getKeyType(){
 | 
			
		||||
    if(type==DSS) return "DSA";
 | 
			
		||||
    return "RSA";
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  public int getState(){return state; }
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -0,0 +1,37 @@
 | 
			
		||||
/* -*-mode:java; c-basic-offset:2; indent-tabs-mode:nil -*- */
 | 
			
		||||
/*
 | 
			
		||||
Copyright (c) 2015-2016 ymnk, JCraft,Inc. All rights reserved.
 | 
			
		||||
 | 
			
		||||
Redistribution and use in source and binary forms, with or without
 | 
			
		||||
modification, are permitted provided that the following conditions are met:
 | 
			
		||||
 | 
			
		||||
  1. Redistributions of source code must retain the above copyright notice,
 | 
			
		||||
     this list of conditions and the following disclaimer.
 | 
			
		||||
 | 
			
		||||
  2. Redistributions in binary form must reproduce the above copyright 
 | 
			
		||||
     notice, this list of conditions and the following disclaimer in 
 | 
			
		||||
     the documentation and/or other materials provided with the distribution.
 | 
			
		||||
 | 
			
		||||
  3. The names of the authors may not be used to endorse or promote products
 | 
			
		||||
     derived from this software without specific prior written permission.
 | 
			
		||||
 | 
			
		||||
THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES,
 | 
			
		||||
INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
 | 
			
		||||
FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JCRAFT,
 | 
			
		||||
INC. OR ANY CONTRIBUTORS TO THIS SOFTWARE BE LIABLE FOR ANY DIRECT, INDIRECT,
 | 
			
		||||
INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
 | 
			
		||||
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
 | 
			
		||||
OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
 | 
			
		||||
LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
 | 
			
		||||
NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
 | 
			
		||||
EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 | 
			
		||||
*/
 | 
			
		||||
 | 
			
		||||
package com.jcraft.jsch;
 | 
			
		||||
 | 
			
		||||
public interface ECDH {
 | 
			
		||||
  void init(int size) throws Exception;
 | 
			
		||||
  byte[] getSecret(byte[] r, byte[] s) throws Exception;
 | 
			
		||||
  byte[] getQ() throws Exception;
 | 
			
		||||
  boolean validate(byte[] r, byte[] s) throws Exception;
 | 
			
		||||
}
 | 
			
		||||
@@ -1,6 +1,6 @@
 | 
			
		||||
/* -*-mode:java; c-basic-offset:2; indent-tabs-mode:nil -*- */
 | 
			
		||||
/*
 | 
			
		||||
Copyright (c) 2002-2012 ymnk, JCraft,Inc. All rights reserved.
 | 
			
		||||
Copyright (c) 2002-2016 ymnk, JCraft,Inc. All rights reserved.
 | 
			
		||||
 | 
			
		||||
Redistribution and use in source and binary forms, with or without
 | 
			
		||||
modification, are permitted provided that the following conditions are met:
 | 
			
		||||
 
 | 
			
		||||
@@ -1,6 +1,6 @@
 | 
			
		||||
/* -*-mode:java; c-basic-offset:2; indent-tabs-mode:nil -*- */
 | 
			
		||||
/*
 | 
			
		||||
Copyright (c) 2004-2012 ymnk, JCraft,Inc. All rights reserved.
 | 
			
		||||
Copyright (c) 2004-2016 ymnk, JCraft,Inc. All rights reserved.
 | 
			
		||||
 | 
			
		||||
Redistribution and use in source and binary forms, with or without
 | 
			
		||||
modification, are permitted provided that the following conditions are met:
 | 
			
		||||
 
 | 
			
		||||
@@ -1,6 +1,6 @@
 | 
			
		||||
/* -*-mode:java; c-basic-offset:2; indent-tabs-mode:nil -*- */
 | 
			
		||||
/*
 | 
			
		||||
Copyright (c) 2002-2012 ymnk, JCraft,Inc. All rights reserved.
 | 
			
		||||
Copyright (c) 2002-2016 ymnk, JCraft,Inc. All rights reserved.
 | 
			
		||||
 | 
			
		||||
Redistribution and use in source and binary forms, with or without
 | 
			
		||||
modification, are permitted provided that the following conditions are met:
 | 
			
		||||
 
 | 
			
		||||
@@ -1,6 +1,6 @@
 | 
			
		||||
/* -*-mode:java; c-basic-offset:2; indent-tabs-mode:nil -*- */
 | 
			
		||||
/*
 | 
			
		||||
Copyright (c) 2002-2012 ymnk, JCraft,Inc. All rights reserved.
 | 
			
		||||
Copyright (c) 2002-2016 ymnk, JCraft,Inc. All rights reserved.
 | 
			
		||||
 | 
			
		||||
Redistribution and use in source and binary forms, with or without
 | 
			
		||||
modification, are permitted provided that the following conditions are met:
 | 
			
		||||
@@ -30,13 +30,22 @@ EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 | 
			
		||||
package com.jcraft.jsch;
 | 
			
		||||
 | 
			
		||||
public class HostKey{
 | 
			
		||||
  private static final byte[] sshdss=Util.str2byte("ssh-dss");
 | 
			
		||||
  private static final byte[] sshrsa=Util.str2byte("ssh-rsa");
 | 
			
		||||
 | 
			
		||||
  private static final byte[][] names = {
 | 
			
		||||
    Util.str2byte("ssh-dss"),
 | 
			
		||||
    Util.str2byte("ssh-rsa"),
 | 
			
		||||
    Util.str2byte("ecdsa-sha2-nistp256"),
 | 
			
		||||
    Util.str2byte("ecdsa-sha2-nistp384"),
 | 
			
		||||
    Util.str2byte("ecdsa-sha2-nistp521")
 | 
			
		||||
  };
 | 
			
		||||
 | 
			
		||||
  protected static final int GUESS=0;
 | 
			
		||||
  public static final int SSHDSS=1;
 | 
			
		||||
  public static final int SSHRSA=2;
 | 
			
		||||
  static final int UNKNOWN=3;
 | 
			
		||||
  public static final int ECDSA256=3;
 | 
			
		||||
  public static final int ECDSA384=4;
 | 
			
		||||
  public static final int ECDSA521=5;
 | 
			
		||||
  static final int UNKNOWN=6;
 | 
			
		||||
 | 
			
		||||
  protected String marker;
 | 
			
		||||
  protected String host;
 | 
			
		||||
@@ -60,6 +69,9 @@ public class HostKey{
 | 
			
		||||
    if(type==GUESS){
 | 
			
		||||
      if(key[8]=='d'){ this.type=SSHDSS; }
 | 
			
		||||
      else if(key[8]=='r'){ this.type=SSHRSA; }
 | 
			
		||||
      else if(key[8]=='a' && key[20]=='2'){ this.type=ECDSA256; }
 | 
			
		||||
      else if(key[8]=='a' && key[20]=='3'){ this.type=ECDSA384; }
 | 
			
		||||
      else if(key[8]=='a' && key[20]=='5'){ this.type=ECDSA521; }
 | 
			
		||||
      else { throw new JSchException("invalid key type");}
 | 
			
		||||
    }
 | 
			
		||||
    else{
 | 
			
		||||
@@ -71,10 +83,23 @@ public class HostKey{
 | 
			
		||||
 | 
			
		||||
  public String getHost(){ return host; }
 | 
			
		||||
  public String getType(){
 | 
			
		||||
    if(type==SSHDSS){ return Util.byte2str(sshdss); }
 | 
			
		||||
    if(type==SSHRSA){ return Util.byte2str(sshrsa);}
 | 
			
		||||
    if(type==SSHDSS ||
 | 
			
		||||
       type==SSHRSA ||
 | 
			
		||||
       type==ECDSA256 ||
 | 
			
		||||
       type==ECDSA384 ||
 | 
			
		||||
       type==ECDSA521){
 | 
			
		||||
      return Util.byte2str(names[type-1]);
 | 
			
		||||
    }
 | 
			
		||||
    return "UNKNOWN";
 | 
			
		||||
  }
 | 
			
		||||
  protected static int name2type(String name){
 | 
			
		||||
    for(int i = 0; i < names.length; i++){
 | 
			
		||||
      if(Util.byte2str(names[i]).equals(name)){
 | 
			
		||||
        return i + 1;
 | 
			
		||||
      }
 | 
			
		||||
    }
 | 
			
		||||
    return UNKNOWN;
 | 
			
		||||
  }
 | 
			
		||||
  public String getKey(){
 | 
			
		||||
    return Util.byte2str(Util.toBase64(key, 0, key.length));
 | 
			
		||||
  }
 | 
			
		||||
 
 | 
			
		||||
@@ -1,6 +1,6 @@
 | 
			
		||||
/* -*-mode:java; c-basic-offset:2; indent-tabs-mode:nil -*- */
 | 
			
		||||
/*
 | 
			
		||||
Copyright (c) 2004-2012 ymnk, JCraft,Inc. All rights reserved.
 | 
			
		||||
Copyright (c) 2004-2016 ymnk, JCraft,Inc. All rights reserved.
 | 
			
		||||
 | 
			
		||||
Redistribution and use in source and binary forms, with or without
 | 
			
		||||
modification, are permitted provided that the following conditions are met:
 | 
			
		||||
@@ -34,11 +34,61 @@ public interface HostKeyRepository{
 | 
			
		||||
  final int NOT_INCLUDED=1;
 | 
			
		||||
  final int CHANGED=2;
 | 
			
		||||
 | 
			
		||||
  /**
 | 
			
		||||
   * Checks if <code>host</code> is included with the <code>key</code>. 
 | 
			
		||||
   * 
 | 
			
		||||
   * @return #NOT_INCLUDED, #OK or #CHANGED
 | 
			
		||||
   * @see #NOT_INCLUDED
 | 
			
		||||
   * @see #OK
 | 
			
		||||
   * @see #CHANGED
 | 
			
		||||
   */
 | 
			
		||||
  int check(String host, byte[] key);
 | 
			
		||||
 | 
			
		||||
  /**
 | 
			
		||||
   * Adds a host key <code>hostkey</code>
 | 
			
		||||
   *
 | 
			
		||||
   * @param hostkey a host key to be added
 | 
			
		||||
   * @param ui a user interface for showing messages or promping inputs.
 | 
			
		||||
   * @see UserInfo
 | 
			
		||||
   */
 | 
			
		||||
  void add(HostKey hostkey, UserInfo ui);
 | 
			
		||||
 | 
			
		||||
  /**
 | 
			
		||||
   * Removes a host key if there exists mached key with
 | 
			
		||||
   * <code>host</code>, <code>type</code>.
 | 
			
		||||
   *
 | 
			
		||||
   * @see #remove(String host, String type, byte[] key)
 | 
			
		||||
   */
 | 
			
		||||
  void remove(String host, String type);
 | 
			
		||||
 | 
			
		||||
  /**
 | 
			
		||||
   * Removes a host key if there exists a matched key with
 | 
			
		||||
   * <code>host</code>, <code>type</code> and <code>key</code>.
 | 
			
		||||
   */
 | 
			
		||||
  void remove(String host, String type, byte[] key);
 | 
			
		||||
 | 
			
		||||
  /**
 | 
			
		||||
   * Returns id of this repository.
 | 
			
		||||
   *
 | 
			
		||||
   * @return identity in String
 | 
			
		||||
   */
 | 
			
		||||
  String getKnownHostsRepositoryID();
 | 
			
		||||
 | 
			
		||||
  /**
 | 
			
		||||
   * Retuns a list for host keys managed in this repository.
 | 
			
		||||
   *
 | 
			
		||||
   * @see #getHostKey(String host, String type)
 | 
			
		||||
   */
 | 
			
		||||
  HostKey[] getHostKey();
 | 
			
		||||
 | 
			
		||||
  /**
 | 
			
		||||
   * Retuns a list for host keys managed in this repository.
 | 
			
		||||
   *
 | 
			
		||||
   * @param host a hostname used in searching host keys.
 | 
			
		||||
   *        If <code>null</code> is given, every host key will be listed.
 | 
			
		||||
   * @param type a key type used in searching host keys,
 | 
			
		||||
   *        and it should be "ssh-dss" or "ssh-rsa".
 | 
			
		||||
   *        If <code>null</code> is given, a key type type will not be ignored.
 | 
			
		||||
   */
 | 
			
		||||
  HostKey[] getHostKey(String host, String type);
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -1,6 +1,6 @@
 | 
			
		||||
/* -*-mode:java; c-basic-offset:2; indent-tabs-mode:nil -*- */
 | 
			
		||||
/*
 | 
			
		||||
Copyright (c) 2002-2012 ymnk, JCraft,Inc. All rights reserved.
 | 
			
		||||
Copyright (c) 2002-2016 ymnk, JCraft,Inc. All rights reserved.
 | 
			
		||||
 | 
			
		||||
Redistribution and use in source and binary forms, with or without
 | 
			
		||||
modification, are permitted provided that the following conditions are met:
 | 
			
		||||
 
 | 
			
		||||
@@ -1,6 +1,6 @@
 | 
			
		||||
/* -*-mode:java; c-basic-offset:2; indent-tabs-mode:nil -*- */
 | 
			
		||||
/*
 | 
			
		||||
Copyright (c) 2002-2012 ymnk, JCraft,Inc. All rights reserved.
 | 
			
		||||
Copyright (c) 2002-2016 ymnk, JCraft,Inc. All rights reserved.
 | 
			
		||||
 | 
			
		||||
Redistribution and use in source and binary forms, with or without
 | 
			
		||||
modification, are permitted provided that the following conditions are met:
 | 
			
		||||
 
 | 
			
		||||
@@ -1,6 +1,6 @@
 | 
			
		||||
/* -*-mode:java; c-basic-offset:2; indent-tabs-mode:nil -*- */
 | 
			
		||||
/*
 | 
			
		||||
Copyright (c) 2002-2012 ymnk, JCraft,Inc. All rights reserved.
 | 
			
		||||
Copyright (c) 2002-2016 ymnk, JCraft,Inc. All rights reserved.
 | 
			
		||||
 | 
			
		||||
Redistribution and use in source and binary forms, with or without
 | 
			
		||||
modification, are permitted provided that the following conditions are met:
 | 
			
		||||
@@ -42,6 +42,7 @@ class IdentityFile implements Identity{
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  static IdentityFile newInstance(String name, byte[] prvkey, byte[] pubkey, JSch jsch) throws JSchException{
 | 
			
		||||
 | 
			
		||||
    KeyPair kpair = KeyPair.load(jsch, prvkey, pubkey);
 | 
			
		||||
    return new IdentityFile(jsch, name, kpair);
 | 
			
		||||
  }
 | 
			
		||||
 
 | 
			
		||||
@@ -1,6 +1,6 @@
 | 
			
		||||
/* -*-mode:java; c-basic-offset:2; indent-tabs-mode:nil -*- */
 | 
			
		||||
/*
 | 
			
		||||
Copyright (c) 2012 ymnk, JCraft,Inc. All rights reserved.
 | 
			
		||||
Copyright (c) 2012-2016 ymnk, JCraft,Inc. All rights reserved.
 | 
			
		||||
 | 
			
		||||
Redistribution and use in source and binary forms, with or without
 | 
			
		||||
modification, are permitted provided that the following conditions are met:
 | 
			
		||||
 
 | 
			
		||||
@@ -1,6 +1,6 @@
 | 
			
		||||
/* -*-mode:java; c-basic-offset:2; indent-tabs-mode:nil -*- */
 | 
			
		||||
/*
 | 
			
		||||
Copyright (c) 2002-2012 ymnk, JCraft,Inc. All rights reserved.
 | 
			
		||||
Copyright (c) 2002-2016 ymnk, JCraft,Inc. All rights reserved.
 | 
			
		||||
 | 
			
		||||
Redistribution and use in source and binary forms, with or without
 | 
			
		||||
modification, are permitted provided that the following conditions are met:
 | 
			
		||||
@@ -36,17 +36,16 @@ public class JSch{
 | 
			
		||||
  /**
 | 
			
		||||
   * The version number.
 | 
			
		||||
   */
 | 
			
		||||
  public static final String VERSION  = "0.1.50";
 | 
			
		||||
  public static final String VERSION  = "0.1.54";
 | 
			
		||||
 | 
			
		||||
  static java.util.Hashtable config=new java.util.Hashtable();
 | 
			
		||||
  static{
 | 
			
		||||
    config.put("kex", "diffie-hellman-group1-sha1,diffie-hellman-group14-sha1,diffie-hellman-group-exchange-sha1");
 | 
			
		||||
    config.put("server_host_key", "ssh-rsa,ssh-dss");
 | 
			
		||||
 | 
			
		||||
    config.put("kex", "ecdh-sha2-nistp256,ecdh-sha2-nistp384,ecdh-sha2-nistp521,diffie-hellman-group14-sha1,diffie-hellman-group-exchange-sha256,diffie-hellman-group-exchange-sha1,diffie-hellman-group1-sha1");
 | 
			
		||||
    config.put("server_host_key", "ssh-rsa,ssh-dss,ecdsa-sha2-nistp256,ecdsa-sha2-nistp384,ecdsa-sha2-nistp521");
 | 
			
		||||
    config.put("cipher.s2c", 
 | 
			
		||||
               "aes128-ctr,aes128-cbc,3des-ctr,3des-cbc,blowfish-cbc,aes192-cbc,aes256-cbc");
 | 
			
		||||
               "aes128-ctr,aes128-cbc,3des-ctr,3des-cbc,blowfish-cbc,aes192-ctr,aes192-cbc,aes256-ctr,aes256-cbc");
 | 
			
		||||
    config.put("cipher.c2s",
 | 
			
		||||
               "aes128-ctr,aes128-cbc,3des-ctr,3des-cbc,blowfish-cbc,aes192-cbc,aes256-cbc");
 | 
			
		||||
               "aes128-ctr,aes128-cbc,3des-ctr,3des-cbc,blowfish-cbc,aes192-ctr,aes192-cbc,aes256-ctr,aes256-cbc");
 | 
			
		||||
 | 
			
		||||
    config.put("mac.s2c", "hmac-md5,hmac-sha1,hmac-sha2-256,hmac-sha1-96,hmac-md5-96");
 | 
			
		||||
    config.put("mac.c2s", "hmac-md5,hmac-sha1,hmac-sha2-256,hmac-sha1-96,hmac-md5-96");
 | 
			
		||||
@@ -63,9 +62,19 @@ public class JSch{
 | 
			
		||||
    config.put("diffie-hellman-group1-sha1", 
 | 
			
		||||
	                        "com.jcraft.jsch.DHG1");
 | 
			
		||||
    config.put("diffie-hellman-group14-sha1", 
 | 
			
		||||
	                        "com.jcraft.jsch.DHG14");
 | 
			
		||||
               "com.jcraft.jsch.DHG14");    // available since JDK8.
 | 
			
		||||
    config.put("diffie-hellman-group-exchange-sha256", 
 | 
			
		||||
               "com.jcraft.jsch.DHGEX256"); // avaibale since JDK1.4.2.
 | 
			
		||||
               "com.jcraft.jsch.DHGEX256"); // available since JDK1.4.2.
 | 
			
		||||
                                            // On JDK8, 2048bits will be used.
 | 
			
		||||
    config.put("ecdsa-sha2-nistp256", "com.jcraft.jsch.jce.SignatureECDSA");
 | 
			
		||||
    config.put("ecdsa-sha2-nistp384", "com.jcraft.jsch.jce.SignatureECDSA");
 | 
			
		||||
    config.put("ecdsa-sha2-nistp521", "com.jcraft.jsch.jce.SignatureECDSA");
 | 
			
		||||
 | 
			
		||||
    config.put("ecdh-sha2-nistp256", "com.jcraft.jsch.DHEC256");
 | 
			
		||||
    config.put("ecdh-sha2-nistp384", "com.jcraft.jsch.DHEC384");
 | 
			
		||||
    config.put("ecdh-sha2-nistp521", "com.jcraft.jsch.DHEC521");
 | 
			
		||||
 | 
			
		||||
    config.put("ecdh-sha2-nistp", "com.jcraft.jsch.jce.ECDHN");
 | 
			
		||||
 | 
			
		||||
    config.put("dh",            "com.jcraft.jsch.jce.DH");
 | 
			
		||||
    config.put("3des-cbc",      "com.jcraft.jsch.jce.TripleDESCBC");
 | 
			
		||||
@@ -80,11 +89,15 @@ public class JSch{
 | 
			
		||||
    config.put("hmac-md5-96",   "com.jcraft.jsch.jce.HMACMD596");
 | 
			
		||||
    config.put("sha-1",         "com.jcraft.jsch.jce.SHA1");
 | 
			
		||||
    config.put("sha-256",         "com.jcraft.jsch.jce.SHA256");
 | 
			
		||||
    config.put("sha-384",         "com.jcraft.jsch.jce.SHA384");
 | 
			
		||||
    config.put("sha-512",         "com.jcraft.jsch.jce.SHA512");
 | 
			
		||||
    config.put("md5",           "com.jcraft.jsch.jce.MD5");
 | 
			
		||||
    config.put("signature.dss", "com.jcraft.jsch.jce.SignatureDSA");
 | 
			
		||||
    config.put("signature.rsa", "com.jcraft.jsch.jce.SignatureRSA");
 | 
			
		||||
    config.put("signature.ecdsa", "com.jcraft.jsch.jce.SignatureECDSA");
 | 
			
		||||
    config.put("keypairgen.dsa",   "com.jcraft.jsch.jce.KeyPairGenDSA");
 | 
			
		||||
    config.put("keypairgen.rsa",   "com.jcraft.jsch.jce.KeyPairGenRSA");
 | 
			
		||||
    config.put("keypairgen.ecdsa", "com.jcraft.jsch.jce.KeyPairGenECDSA");
 | 
			
		||||
    config.put("random",        "com.jcraft.jsch.jce.Random");
 | 
			
		||||
 | 
			
		||||
    config.put("none",           "com.jcraft.jsch.CipherNone");
 | 
			
		||||
@@ -111,13 +124,16 @@ public class JSch{
 | 
			
		||||
    config.put("zlib",             "com.jcraft.jsch.jcraft.Compression");
 | 
			
		||||
    config.put("zlib@openssh.com", "com.jcraft.jsch.jcraft.Compression");
 | 
			
		||||
 | 
			
		||||
    config.put("pbkdf", "com.jcraft.jsch.jce.PBKDF");
 | 
			
		||||
 | 
			
		||||
    config.put("StrictHostKeyChecking",  "ask");
 | 
			
		||||
    config.put("HashKnownHosts",  "no");
 | 
			
		||||
 | 
			
		||||
    config.put("PreferredAuthentications", "gssapi-with-mic,publickey,keyboard-interactive,password");
 | 
			
		||||
 | 
			
		||||
    config.put("CheckCiphers", "aes256-ctr,aes192-ctr,aes128-ctr,aes256-cbc,aes192-cbc,aes128-cbc,3des-ctr,arcfour,arcfour128,arcfour256");
 | 
			
		||||
    config.put("CheckKexes", "diffie-hellman-group14-sha1");
 | 
			
		||||
    config.put("CheckKexes", "diffie-hellman-group14-sha1,ecdh-sha2-nistp256,ecdh-sha2-nistp384,ecdh-sha2-nistp521");
 | 
			
		||||
    config.put("CheckSignatures", "ecdsa-sha2-nistp256,ecdsa-sha2-nistp384,ecdsa-sha2-nistp521");
 | 
			
		||||
 | 
			
		||||
    config.put("MaxAuthTries", "6");
 | 
			
		||||
    config.put("ClearAllForwardings", "no");
 | 
			
		||||
@@ -171,7 +187,9 @@ public class JSch{
 | 
			
		||||
  static Logger logger=DEVNULL;
 | 
			
		||||
 | 
			
		||||
  public JSch(){
 | 
			
		||||
 | 
			
		||||
    /*
 | 
			
		||||
    // The JCE of Sun's Java5 on Mac OS X has the resource leak bug
 | 
			
		||||
    // in calculating HMAC, so we need to use our own implementations.
 | 
			
		||||
    try{
 | 
			
		||||
      String osname=(String)(System.getProperties().get("os.name"));
 | 
			
		||||
      if(osname!=null && osname.equals("Mac OS X")){
 | 
			
		||||
@@ -183,7 +201,7 @@ public class JSch{
 | 
			
		||||
    }
 | 
			
		||||
    catch(Exception e){
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    */
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  /**
 | 
			
		||||
 
 | 
			
		||||
@@ -1,6 +1,6 @@
 | 
			
		||||
/* -*-mode:java; c-basic-offset:2; indent-tabs-mode:nil -*- */
 | 
			
		||||
/*
 | 
			
		||||
Copyright (c) 2002-2012 ymnk, JCraft,Inc. All rights reserved.
 | 
			
		||||
Copyright (c) 2002-2016 ymnk, JCraft,Inc. All rights reserved.
 | 
			
		||||
 | 
			
		||||
Redistribution and use in source and binary forms, with or without
 | 
			
		||||
modification, are permitted provided that the following conditions are met:
 | 
			
		||||
 
 | 
			
		||||
@@ -1,6 +1,6 @@
 | 
			
		||||
/* -*-mode:java; c-basic-offset:2; indent-tabs-mode:nil -*- */
 | 
			
		||||
/*
 | 
			
		||||
Copyright (c) 2002-2012 ymnk, JCraft,Inc. All rights reserved.
 | 
			
		||||
Copyright (c) 2002-2016 ymnk, JCraft,Inc. All rights reserved.
 | 
			
		||||
 | 
			
		||||
Redistribution and use in source and binary forms, with or without
 | 
			
		||||
modification, are permitted provided that the following conditions are met:
 | 
			
		||||
 
 | 
			
		||||
@@ -1,6 +1,6 @@
 | 
			
		||||
/* -*-mode:java; c-basic-offset:2; indent-tabs-mode:nil -*- */
 | 
			
		||||
/*
 | 
			
		||||
Copyright (c) 2002-2012 ymnk, JCraft,Inc. All rights reserved.
 | 
			
		||||
Copyright (c) 2002-2016 ymnk, JCraft,Inc. All rights reserved.
 | 
			
		||||
 | 
			
		||||
Redistribution and use in source and binary forms, with or without
 | 
			
		||||
modification, are permitted provided that the following conditions are met:
 | 
			
		||||
 
 | 
			
		||||
@@ -1,6 +1,6 @@
 | 
			
		||||
/* -*-mode:java; c-basic-offset:2; indent-tabs-mode:nil -*- */
 | 
			
		||||
/*
 | 
			
		||||
Copyright (c) 2002-2012 ymnk, JCraft,Inc. All rights reserved.
 | 
			
		||||
Copyright (c) 2002-2016 ymnk, JCraft,Inc. All rights reserved.
 | 
			
		||||
 | 
			
		||||
Redistribution and use in source and binary forms, with or without
 | 
			
		||||
modification, are permitted provided that the following conditions are met:
 | 
			
		||||
@@ -70,19 +70,24 @@ public abstract class KeyExchange{
 | 
			
		||||
  public abstract void init(Session session, 
 | 
			
		||||
			    byte[] V_S, byte[] V_C, byte[] I_S, byte[] I_C) throws Exception;
 | 
			
		||||
  public abstract boolean next(Buffer buf) throws Exception;
 | 
			
		||||
  public abstract String getKeyType();
 | 
			
		||||
 | 
			
		||||
  public abstract int getState();
 | 
			
		||||
 | 
			
		||||
  /*
 | 
			
		||||
  void dump(byte[] foo){
 | 
			
		||||
    for(int i=0; i<foo.length; i++){
 | 
			
		||||
      if((foo[i]&0xf0)==0)System.err.print("0");
 | 
			
		||||
      System.err.print(Integer.toHexString(foo[i]&0xff));
 | 
			
		||||
      if(i%16==15){System.err.println(""); continue;}
 | 
			
		||||
      if(i%2==1)System.err.print(" ");
 | 
			
		||||
    }
 | 
			
		||||
  } 
 | 
			
		||||
  */
 | 
			
		||||
  protected final int RSA=0;
 | 
			
		||||
  protected final int DSS=1;
 | 
			
		||||
  protected final int ECDSA=2;
 | 
			
		||||
  private int type=0;
 | 
			
		||||
  private String key_alg_name = "";
 | 
			
		||||
 | 
			
		||||
  public String getKeyType() {
 | 
			
		||||
    if(type==DSS) return "DSA";
 | 
			
		||||
    if(type==RSA) return "RSA";
 | 
			
		||||
    return "ECDSA";
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  public String getKeyAlgorithName() {
 | 
			
		||||
    return key_alg_name;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  protected static String[] guess(byte[]I_S, byte[]I_C){
 | 
			
		||||
    String[] guess=new String[PROPOSAL_MAX];
 | 
			
		||||
@@ -176,8 +181,145 @@ public abstract class KeyExchange{
 | 
			
		||||
       secret[0] == 0 && (secret[1]&0x80) == 0) {
 | 
			
		||||
      byte[] tmp=new byte[secret.length-1];
 | 
			
		||||
      System.arraycopy(secret, 1, tmp, 0, tmp.length);
 | 
			
		||||
      secret=tmp;
 | 
			
		||||
      return normalize(tmp);
 | 
			
		||||
    }
 | 
			
		||||
    else {
 | 
			
		||||
      return secret;
 | 
			
		||||
    }
 | 
			
		||||
    return secret;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  protected boolean verify(String alg, byte[] K_S, int index,
 | 
			
		||||
                           byte[] sig_of_H) throws Exception {
 | 
			
		||||
    int i,j;
 | 
			
		||||
 | 
			
		||||
    i=index;
 | 
			
		||||
    boolean result=false;
 | 
			
		||||
 | 
			
		||||
    if(alg.equals("ssh-rsa")){
 | 
			
		||||
      byte[] tmp;
 | 
			
		||||
      byte[] ee;
 | 
			
		||||
      byte[] n;
 | 
			
		||||
 | 
			
		||||
      type=RSA;
 | 
			
		||||
      key_alg_name=alg;
 | 
			
		||||
      
 | 
			
		||||
      j=((K_S[i++]<<24)&0xff000000)|((K_S[i++]<<16)&0x00ff0000)|
 | 
			
		||||
        ((K_S[i++]<<8)&0x0000ff00)|((K_S[i++])&0x000000ff);
 | 
			
		||||
      tmp=new byte[j]; System.arraycopy(K_S, i, tmp, 0, j); i+=j;
 | 
			
		||||
      ee=tmp;
 | 
			
		||||
      j=((K_S[i++]<<24)&0xff000000)|((K_S[i++]<<16)&0x00ff0000)|
 | 
			
		||||
        ((K_S[i++]<<8)&0x0000ff00)|((K_S[i++])&0x000000ff);
 | 
			
		||||
      tmp=new byte[j]; System.arraycopy(K_S, i, tmp, 0, j); i+=j;
 | 
			
		||||
      n=tmp;
 | 
			
		||||
	
 | 
			
		||||
      SignatureRSA sig=null;
 | 
			
		||||
      try{
 | 
			
		||||
        Class c=Class.forName(session.getConfig("signature.rsa"));
 | 
			
		||||
        sig=(SignatureRSA)(c.newInstance());
 | 
			
		||||
        sig.init();
 | 
			
		||||
      }
 | 
			
		||||
      catch(Exception e){
 | 
			
		||||
        System.err.println(e);
 | 
			
		||||
      }
 | 
			
		||||
      sig.setPubKey(ee, n);   
 | 
			
		||||
      sig.update(H);
 | 
			
		||||
      result=sig.verify(sig_of_H);
 | 
			
		||||
 | 
			
		||||
      if(JSch.getLogger().isEnabled(Logger.INFO)){
 | 
			
		||||
        JSch.getLogger().log(Logger.INFO, 
 | 
			
		||||
                             "ssh_rsa_verify: signature "+result);
 | 
			
		||||
      }
 | 
			
		||||
    }
 | 
			
		||||
    else if(alg.equals("ssh-dss")){
 | 
			
		||||
      byte[] q=null;
 | 
			
		||||
      byte[] tmp;
 | 
			
		||||
      byte[] p;
 | 
			
		||||
      byte[] g;
 | 
			
		||||
      byte[] f;
 | 
			
		||||
      
 | 
			
		||||
      type=DSS;
 | 
			
		||||
      key_alg_name=alg;
 | 
			
		||||
 | 
			
		||||
      j=((K_S[i++]<<24)&0xff000000)|((K_S[i++]<<16)&0x00ff0000)|
 | 
			
		||||
	  ((K_S[i++]<<8)&0x0000ff00)|((K_S[i++])&0x000000ff);
 | 
			
		||||
      tmp=new byte[j]; System.arraycopy(K_S, i, tmp, 0, j); i+=j;
 | 
			
		||||
      p=tmp;
 | 
			
		||||
      j=((K_S[i++]<<24)&0xff000000)|((K_S[i++]<<16)&0x00ff0000)|
 | 
			
		||||
        ((K_S[i++]<<8)&0x0000ff00)|((K_S[i++])&0x000000ff);
 | 
			
		||||
      tmp=new byte[j]; System.arraycopy(K_S, i, tmp, 0, j); i+=j;
 | 
			
		||||
      q=tmp;
 | 
			
		||||
      j=((K_S[i++]<<24)&0xff000000)|((K_S[i++]<<16)&0x00ff0000)|
 | 
			
		||||
	  ((K_S[i++]<<8)&0x0000ff00)|((K_S[i++])&0x000000ff);
 | 
			
		||||
      tmp=new byte[j]; System.arraycopy(K_S, i, tmp, 0, j); i+=j;
 | 
			
		||||
      g=tmp;
 | 
			
		||||
      j=((K_S[i++]<<24)&0xff000000)|((K_S[i++]<<16)&0x00ff0000)|
 | 
			
		||||
        ((K_S[i++]<<8)&0x0000ff00)|((K_S[i++])&0x000000ff);
 | 
			
		||||
      tmp=new byte[j]; System.arraycopy(K_S, i, tmp, 0, j); i+=j;
 | 
			
		||||
      f=tmp;
 | 
			
		||||
 | 
			
		||||
      SignatureDSA sig=null;
 | 
			
		||||
      try{
 | 
			
		||||
        Class c=Class.forName(session.getConfig("signature.dss"));
 | 
			
		||||
        sig=(SignatureDSA)(c.newInstance());
 | 
			
		||||
        sig.init();
 | 
			
		||||
      }
 | 
			
		||||
      catch(Exception e){
 | 
			
		||||
        System.err.println(e);
 | 
			
		||||
      }
 | 
			
		||||
      sig.setPubKey(f, p, q, g);   
 | 
			
		||||
      sig.update(H);
 | 
			
		||||
      result=sig.verify(sig_of_H);
 | 
			
		||||
 | 
			
		||||
      if(JSch.getLogger().isEnabled(Logger.INFO)){
 | 
			
		||||
        JSch.getLogger().log(Logger.INFO, 
 | 
			
		||||
                             "ssh_dss_verify: signature "+result);
 | 
			
		||||
      }
 | 
			
		||||
    }
 | 
			
		||||
    else if(alg.equals("ecdsa-sha2-nistp256") ||
 | 
			
		||||
            alg.equals("ecdsa-sha2-nistp384") ||
 | 
			
		||||
            alg.equals("ecdsa-sha2-nistp521")) {
 | 
			
		||||
      byte[] tmp;
 | 
			
		||||
      byte[] r;
 | 
			
		||||
      byte[] s;
 | 
			
		||||
 | 
			
		||||
      // RFC 5656, 
 | 
			
		||||
      type=ECDSA;
 | 
			
		||||
      key_alg_name=alg;
 | 
			
		||||
 | 
			
		||||
      j=((K_S[i++]<<24)&0xff000000)|((K_S[i++]<<16)&0x00ff0000)|
 | 
			
		||||
        ((K_S[i++]<<8)&0x0000ff00)|((K_S[i++])&0x000000ff);
 | 
			
		||||
      tmp=new byte[j]; System.arraycopy(K_S, i, tmp, 0, j); i+=j;
 | 
			
		||||
      j=((K_S[i++]<<24)&0xff000000)|((K_S[i++]<<16)&0x00ff0000)|
 | 
			
		||||
        ((K_S[i++]<<8)&0x0000ff00)|((K_S[i++])&0x000000ff);
 | 
			
		||||
      i++;
 | 
			
		||||
      tmp=new byte[(j-1)/2];
 | 
			
		||||
      System.arraycopy(K_S, i, tmp, 0, tmp.length); i+=(j-1)/2;
 | 
			
		||||
      r=tmp;
 | 
			
		||||
      tmp=new byte[(j-1)/2];
 | 
			
		||||
      System.arraycopy(K_S, i, tmp, 0, tmp.length); i+=(j-1)/2;
 | 
			
		||||
      s=tmp;
 | 
			
		||||
 | 
			
		||||
      SignatureECDSA sig=null;
 | 
			
		||||
      try{
 | 
			
		||||
        Class c=Class.forName(session.getConfig("signature.ecdsa"));
 | 
			
		||||
        sig=(SignatureECDSA)(c.newInstance());
 | 
			
		||||
        sig.init();
 | 
			
		||||
      }
 | 
			
		||||
      catch(Exception e){
 | 
			
		||||
        System.err.println(e);
 | 
			
		||||
      }
 | 
			
		||||
 | 
			
		||||
      sig.setPubKey(r, s);
 | 
			
		||||
 | 
			
		||||
      sig.update(H);
 | 
			
		||||
 | 
			
		||||
      result=sig.verify(sig_of_H);
 | 
			
		||||
    }
 | 
			
		||||
    else{
 | 
			
		||||
      System.err.println("unknown alg");
 | 
			
		||||
    }	    
 | 
			
		||||
 | 
			
		||||
    return result;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -1,6 +1,6 @@
 | 
			
		||||
/* -*-mode:java; c-basic-offset:2; indent-tabs-mode:nil -*- */
 | 
			
		||||
/*
 | 
			
		||||
Copyright (c) 2002-2012 ymnk, JCraft,Inc. All rights reserved.
 | 
			
		||||
Copyright (c) 2002-2016 ymnk, JCraft,Inc. All rights reserved.
 | 
			
		||||
 | 
			
		||||
Redistribution and use in source and binary forms, with or without
 | 
			
		||||
modification, are permitted provided that the following conditions are met:
 | 
			
		||||
@@ -38,11 +38,13 @@ public abstract class KeyPair{
 | 
			
		||||
  public static final int ERROR=0;
 | 
			
		||||
  public static final int DSA=1;
 | 
			
		||||
  public static final int RSA=2;
 | 
			
		||||
  public static final int UNKNOWN=3;
 | 
			
		||||
  public static final int ECDSA=3;
 | 
			
		||||
  public static final int UNKNOWN=4;
 | 
			
		||||
 | 
			
		||||
  static final int VENDOR_OPENSSH=0;
 | 
			
		||||
  static final int VENDOR_FSECURE=1;
 | 
			
		||||
  static final int VENDOR_PUTTY=2;
 | 
			
		||||
  static final int VENDOR_PKCS8=3;
 | 
			
		||||
 | 
			
		||||
  int vendor=VENDOR_OPENSSH;
 | 
			
		||||
 | 
			
		||||
@@ -55,6 +57,7 @@ public abstract class KeyPair{
 | 
			
		||||
    KeyPair kpair=null;
 | 
			
		||||
    if(type==DSA){ kpair=new KeyPairDSA(jsch); }
 | 
			
		||||
    else if(type==RSA){ kpair=new KeyPairRSA(jsch); }
 | 
			
		||||
    else if(type==ECDSA){ kpair=new KeyPairECDSA(jsch); }
 | 
			
		||||
    if(kpair!=null){
 | 
			
		||||
      kpair.generate(key_size);
 | 
			
		||||
    }
 | 
			
		||||
@@ -338,6 +341,22 @@ public abstract class KeyPair{
 | 
			
		||||
    return index;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  int writeOCTETSTRING(byte[] buf, int index, byte[] data){
 | 
			
		||||
    buf[index++]=0x04;
 | 
			
		||||
    index=writeLength(buf, index, data.length);
 | 
			
		||||
    System.arraycopy(data, 0, buf, index, data.length);
 | 
			
		||||
    index+=data.length;
 | 
			
		||||
    return index;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
 int writeDATA(byte[] buf, byte n, int index, byte[] data){
 | 
			
		||||
    buf[index++]=n;
 | 
			
		||||
    index=writeLength(buf, index, data.length);
 | 
			
		||||
    System.arraycopy(data, 0, buf, index, data.length);
 | 
			
		||||
    index+=data.length;
 | 
			
		||||
    return index;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  int countLength(int len){
 | 
			
		||||
    int i=1;
 | 
			
		||||
    if(len<=0x7f) return i;
 | 
			
		||||
@@ -474,8 +493,8 @@ public abstract class KeyPair{
 | 
			
		||||
    this.passphrase=passphrase;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  private boolean encrypted=false;
 | 
			
		||||
  private byte[] data=null;
 | 
			
		||||
  protected boolean encrypted=false;
 | 
			
		||||
  protected byte[] data=null;
 | 
			
		||||
  private byte[] iv=null;
 | 
			
		||||
  private byte[] publickeyblob=null;
 | 
			
		||||
 | 
			
		||||
@@ -563,7 +582,8 @@ public abstract class KeyPair{
 | 
			
		||||
    if(pubkey==null &&
 | 
			
		||||
       prvkey!=null && 
 | 
			
		||||
       (prvkey.length>11 &&
 | 
			
		||||
        prvkey[0]==0 && prvkey[1]==0 && prvkey[2]==0 && prvkey[3]==7)){
 | 
			
		||||
        prvkey[0]==0 && prvkey[1]==0 && prvkey[2]==0 &&
 | 
			
		||||
        (prvkey[3]==7 || prvkey[3]==19))){
 | 
			
		||||
 | 
			
		||||
      Buffer buf=new Buffer(prvkey);
 | 
			
		||||
      buf.skip(prvkey.length);  // for using Buffer#available()
 | 
			
		||||
@@ -577,6 +597,11 @@ public abstract class KeyPair{
 | 
			
		||||
      else if(_type.equals("ssh-dss")){
 | 
			
		||||
        kpair=KeyPairDSA.fromSSHAgent(jsch, buf);
 | 
			
		||||
      }
 | 
			
		||||
      else if(_type.equals("ecdsa-sha2-nistp256") ||
 | 
			
		||||
              _type.equals("ecdsa-sha2-nistp384") ||
 | 
			
		||||
              _type.equals("ecdsa-sha2-nistp512")){
 | 
			
		||||
        kpair=KeyPairECDSA.fromSSHAgent(jsch, buf);
 | 
			
		||||
      }
 | 
			
		||||
      else{
 | 
			
		||||
        throw new JSchException("privatekey: invalid key "+new String(prvkey, 4, 7));
 | 
			
		||||
      }
 | 
			
		||||
@@ -612,10 +637,29 @@ public abstract class KeyPair{
 | 
			
		||||
	    throw new JSchException("invalid privatekey: "+prvkey);
 | 
			
		||||
          if(buf[i]=='D'&& buf[i+1]=='S'&& buf[i+2]=='A'){ type=DSA; }
 | 
			
		||||
	  else if(buf[i]=='R'&& buf[i+1]=='S'&& buf[i+2]=='A'){ type=RSA; }
 | 
			
		||||
	  else if(buf[i]=='E'&& buf[i+1]=='C'){ type=ECDSA; }
 | 
			
		||||
	  else if(buf[i]=='S'&& buf[i+1]=='S'&& buf[i+2]=='H'){ // FSecure
 | 
			
		||||
	    type=UNKNOWN;
 | 
			
		||||
	    vendor=VENDOR_FSECURE;
 | 
			
		||||
	  }
 | 
			
		||||
	  else if(i+6 < len &&
 | 
			
		||||
                  buf[i]=='P' && buf[i+1]=='R' &&
 | 
			
		||||
                  buf[i+2]=='I' && buf[i+3]=='V' &&
 | 
			
		||||
                  buf[i+4]=='A' && buf[i+5]=='T' && buf[i+6]=='E'){
 | 
			
		||||
	    type=UNKNOWN;
 | 
			
		||||
	    vendor=VENDOR_PKCS8;
 | 
			
		||||
            encrypted=false;
 | 
			
		||||
            i+=3;
 | 
			
		||||
	  }
 | 
			
		||||
	  else if(i+8 < len &&
 | 
			
		||||
                  buf[i]=='E' && buf[i+1]=='N' &&
 | 
			
		||||
                  buf[i+2]=='C' && buf[i+3]=='R' &&
 | 
			
		||||
                  buf[i+4]=='Y' && buf[i+5]=='P' && buf[i+6]=='T' &&
 | 
			
		||||
                  buf[i+7]=='E' && buf[i+8]=='D'){
 | 
			
		||||
	    type=UNKNOWN;
 | 
			
		||||
	    vendor=VENDOR_PKCS8;
 | 
			
		||||
            i+=5;
 | 
			
		||||
	  }
 | 
			
		||||
	  else{
 | 
			
		||||
	    throw new JSchException("invalid privatekey: "+prvkey);
 | 
			
		||||
	  }
 | 
			
		||||
@@ -689,7 +733,8 @@ public abstract class KeyPair{
 | 
			
		||||
	  }
 | 
			
		||||
	  if(!inheader){
 | 
			
		||||
	    i++; 
 | 
			
		||||
	    encrypted=false;    // no passphrase
 | 
			
		||||
	    if(vendor!=VENDOR_PKCS8)
 | 
			
		||||
              encrypted=false;    // no passphrase
 | 
			
		||||
	    break;
 | 
			
		||||
	  }
 | 
			
		||||
	}
 | 
			
		||||
@@ -724,12 +769,8 @@ public abstract class KeyPair{
 | 
			
		||||
        while(i<_len){
 | 
			
		||||
          if(_buf[i]==0x0a){
 | 
			
		||||
            boolean xd=(_buf[i-1]==0x0d);
 | 
			
		||||
            // move 0x0a (or 0x0d0x0a) to the end of '_buf'.
 | 
			
		||||
            System.arraycopy(_buf, i+1, 
 | 
			
		||||
                             _buf, 
 | 
			
		||||
                             i-(xd ? 1 : 0), 
 | 
			
		||||
                             _len-i-1-(xd ? 1 : 0)
 | 
			
		||||
                             );
 | 
			
		||||
            // ignore 0x0a (or 0x0d0x0a)
 | 
			
		||||
            System.arraycopy(_buf, i+1, _buf, i-(xd ? 1 : 0), _len-(i+1));
 | 
			
		||||
            if(xd)_len--;
 | 
			
		||||
            _len--;
 | 
			
		||||
            continue;
 | 
			
		||||
@@ -841,11 +882,32 @@ public abstract class KeyPair{
 | 
			
		||||
              if(i++<len){
 | 
			
		||||
                int start=i;
 | 
			
		||||
                while(i<len){ if(buf[i]=='\n')break; i++;}
 | 
			
		||||
                if(i<len){
 | 
			
		||||
                if(i>0 && buf[i-1]==0x0d) i--;
 | 
			
		||||
                if(start<i){
 | 
			
		||||
                  publicKeyComment = new String(buf, start, i-start);
 | 
			
		||||
                }
 | 
			
		||||
              } 
 | 
			
		||||
	    }
 | 
			
		||||
            else if(buf[0]=='e'&& buf[1]=='c'&& buf[2]=='d' && buf[3]=='s'){
 | 
			
		||||
              if(prvkey==null && buf.length>7){
 | 
			
		||||
               type=ECDSA;
 | 
			
		||||
              }
 | 
			
		||||
              i=0;
 | 
			
		||||
              while(i<len){ if(buf[i]==' ')break; i++;} i++;
 | 
			
		||||
              if(i<len){
 | 
			
		||||
                int start=i;
 | 
			
		||||
                while(i<len){ if(buf[i]==' ')break; i++;}
 | 
			
		||||
                publickeyblob=Util.fromBase64(buf, start, i-start);
 | 
			
		||||
              }
 | 
			
		||||
              if(i++<len){
 | 
			
		||||
                int start=i;
 | 
			
		||||
                while(i<len){ if(buf[i]=='\n')break; i++;}
 | 
			
		||||
                if(i>0 && buf[i-1]==0x0d) i--;
 | 
			
		||||
                if(start<i){
 | 
			
		||||
                  publicKeyComment = new String(buf, start, i-start);
 | 
			
		||||
                }
 | 
			
		||||
              } 
 | 
			
		||||
            }
 | 
			
		||||
	  }
 | 
			
		||||
	}
 | 
			
		||||
	catch(Exception ee){
 | 
			
		||||
@@ -862,6 +924,8 @@ public abstract class KeyPair{
 | 
			
		||||
    KeyPair kpair=null;
 | 
			
		||||
    if(type==DSA){ kpair=new KeyPairDSA(jsch); }
 | 
			
		||||
    else if(type==RSA){ kpair=new KeyPairRSA(jsch); }
 | 
			
		||||
    else if(type==ECDSA){ kpair=new KeyPairECDSA(jsch); }
 | 
			
		||||
    else if(vendor==VENDOR_PKCS8){ kpair = new KeyPairPKCS8(jsch); }
 | 
			
		||||
 | 
			
		||||
    if(kpair!=null){
 | 
			
		||||
      kpair.encrypted=encrypted;
 | 
			
		||||
@@ -1101,4 +1165,91 @@ public abstract class KeyPair{
 | 
			
		||||
 | 
			
		||||
    return (key != null && value != null);
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  void copy(KeyPair kpair){
 | 
			
		||||
    this.publickeyblob=kpair.publickeyblob;
 | 
			
		||||
    this.vendor=kpair.vendor;
 | 
			
		||||
    this.publicKeyComment=kpair.publicKeyComment;
 | 
			
		||||
    this.cipher=kpair.cipher;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  class ASN1Exception extends Exception {
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  class ASN1 {
 | 
			
		||||
    byte[] buf;
 | 
			
		||||
    int start;
 | 
			
		||||
    int length;
 | 
			
		||||
    ASN1(byte[] buf) throws ASN1Exception {
 | 
			
		||||
      this(buf, 0, buf.length);
 | 
			
		||||
    }
 | 
			
		||||
    ASN1(byte[] buf, int start, int length) throws ASN1Exception {
 | 
			
		||||
      this.buf = buf;
 | 
			
		||||
      this.start = start;
 | 
			
		||||
      this.length = length;
 | 
			
		||||
      if(start+length>buf.length)
 | 
			
		||||
        throw new ASN1Exception();
 | 
			
		||||
    }
 | 
			
		||||
    int getType() {
 | 
			
		||||
      return buf[start]&0xff;
 | 
			
		||||
    }
 | 
			
		||||
    boolean isSEQUENCE() {
 | 
			
		||||
      return getType()==(0x30&0xff);
 | 
			
		||||
    }
 | 
			
		||||
    boolean isINTEGER() {
 | 
			
		||||
      return getType()==(0x02&0xff);
 | 
			
		||||
    }
 | 
			
		||||
    boolean isOBJECT() {
 | 
			
		||||
      return getType()==(0x06&0xff);
 | 
			
		||||
    }
 | 
			
		||||
    boolean isOCTETSTRING() {
 | 
			
		||||
      return getType()==(0x04&0xff);
 | 
			
		||||
    }
 | 
			
		||||
    private int getLength(int[] indexp) {
 | 
			
		||||
      int index=indexp[0];
 | 
			
		||||
      int length=buf[index++]&0xff;
 | 
			
		||||
      if((length&0x80)!=0) {
 | 
			
		||||
        int foo=length&0x7f; length=0;
 | 
			
		||||
        while(foo-->0){ length=(length<<8)+(buf[index++]&0xff); }
 | 
			
		||||
      }
 | 
			
		||||
      indexp[0]=index;
 | 
			
		||||
      return length;
 | 
			
		||||
    }
 | 
			
		||||
    byte[] getContent() {
 | 
			
		||||
      int[] indexp=new int[1];
 | 
			
		||||
      indexp[0]=start+1;
 | 
			
		||||
      int length = getLength(indexp);
 | 
			
		||||
      int index=indexp[0];
 | 
			
		||||
      byte[] tmp = new byte[length];
 | 
			
		||||
      System.arraycopy(buf, index, tmp, 0, tmp.length);
 | 
			
		||||
      return tmp;
 | 
			
		||||
    }
 | 
			
		||||
    ASN1[] getContents() throws ASN1Exception {
 | 
			
		||||
      int typ = buf[start];
 | 
			
		||||
      int[] indexp=new int[1];
 | 
			
		||||
      indexp[0]=start+1;
 | 
			
		||||
      int length = getLength(indexp);
 | 
			
		||||
      if(typ == 0x05){
 | 
			
		||||
        return new ASN1[0];
 | 
			
		||||
      }
 | 
			
		||||
      int index=indexp[0];
 | 
			
		||||
      java.util.Vector values = new java.util.Vector();
 | 
			
		||||
      while(length>0) {
 | 
			
		||||
        index++; length--;
 | 
			
		||||
        int tmp=index;
 | 
			
		||||
        indexp[0]=index;
 | 
			
		||||
        int l=getLength(indexp);
 | 
			
		||||
        index=indexp[0];
 | 
			
		||||
        length-=(index-tmp);
 | 
			
		||||
        values.addElement(new ASN1(buf, tmp-1, 1+(index-tmp)+l));
 | 
			
		||||
        index+=l;
 | 
			
		||||
        length-=l;
 | 
			
		||||
      }
 | 
			
		||||
      ASN1[] result = new ASN1[values.size()];
 | 
			
		||||
      for(int  i = 0; i <values.size(); i++) {
 | 
			
		||||
        result[i]=(ASN1)values.elementAt(i);
 | 
			
		||||
      }
 | 
			
		||||
      return result;
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -1,6 +1,6 @@
 | 
			
		||||
/* -*-mode:java; c-basic-offset:2; indent-tabs-mode:nil -*- */
 | 
			
		||||
/*
 | 
			
		||||
Copyright (c) 2002-2012 ymnk, JCraft,Inc. All rights reserved.
 | 
			
		||||
Copyright (c) 2002-2016 ymnk, JCraft,Inc. All rights reserved.
 | 
			
		||||
 | 
			
		||||
Redistribution and use in source and binary forms, with or without
 | 
			
		||||
modification, are permitted provided that the following conditions are met:
 | 
			
		||||
 
 | 
			
		||||
@@ -0,0 +1,391 @@
 | 
			
		||||
/* -*-mode:java; c-basic-offset:2; indent-tabs-mode:nil -*- */
 | 
			
		||||
/*
 | 
			
		||||
Copyright (c) 2015-2016 ymnk, JCraft,Inc. All rights reserved.
 | 
			
		||||
 | 
			
		||||
Redistribution and use in source and binary forms, with or without
 | 
			
		||||
modification, are permitted provided that the following conditions are met:
 | 
			
		||||
 | 
			
		||||
  1. Redistributions of source code must retain the above copyright notice,
 | 
			
		||||
     this list of conditions and the following disclaimer.
 | 
			
		||||
 | 
			
		||||
  2. Redistributions in binary form must reproduce the above copyright 
 | 
			
		||||
     notice, this list of conditions and the following disclaimer in 
 | 
			
		||||
     the documentation and/or other materials provided with the distribution.
 | 
			
		||||
 | 
			
		||||
  3. The names of the authors may not be used to endorse or promote products
 | 
			
		||||
     derived from this software without specific prior written permission.
 | 
			
		||||
 | 
			
		||||
THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES,
 | 
			
		||||
INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
 | 
			
		||||
FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JCRAFT,
 | 
			
		||||
INC. OR ANY CONTRIBUTORS TO THIS SOFTWARE BE LIABLE FOR ANY DIRECT, INDIRECT,
 | 
			
		||||
INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
 | 
			
		||||
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
 | 
			
		||||
OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
 | 
			
		||||
LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
 | 
			
		||||
NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
 | 
			
		||||
EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 | 
			
		||||
*/
 | 
			
		||||
 | 
			
		||||
package com.jcraft.jsch;
 | 
			
		||||
 | 
			
		||||
public class KeyPairECDSA extends KeyPair{
 | 
			
		||||
 | 
			
		||||
  private static byte[][] oids = {
 | 
			
		||||
    {(byte)0x06, (byte)0x08, (byte)0x2a, (byte)0x86, (byte)0x48, // 256
 | 
			
		||||
     (byte)0xce, (byte)0x3d, (byte)0x03, (byte)0x01, (byte)0x07},
 | 
			
		||||
    {(byte)0x06, (byte)0x05, (byte)0x2b, (byte)0x81, (byte)0x04, // 384
 | 
			
		||||
     (byte)0x00, (byte)0x22},
 | 
			
		||||
    {(byte)0x06, (byte)0x05, (byte)0x2b, (byte)0x81, (byte)0x04, //521
 | 
			
		||||
     (byte)0x00, (byte)0x23},
 | 
			
		||||
  };
 | 
			
		||||
 | 
			
		||||
  private static String[] names = {
 | 
			
		||||
    "nistp256", "nistp384", "nistp521"
 | 
			
		||||
  };
 | 
			
		||||
 | 
			
		||||
  private byte[] name=Util.str2byte(names[0]);
 | 
			
		||||
  private byte[] r_array;
 | 
			
		||||
  private byte[] s_array;
 | 
			
		||||
  private byte[] prv_array;
 | 
			
		||||
 | 
			
		||||
  private int key_size=256;
 | 
			
		||||
 | 
			
		||||
  public KeyPairECDSA(JSch jsch){
 | 
			
		||||
    this(jsch, null, null, null, null);
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  public KeyPairECDSA(JSch jsch,
 | 
			
		||||
                      byte[] name,
 | 
			
		||||
                      byte[] r_array,
 | 
			
		||||
                      byte[] s_array,
 | 
			
		||||
                      byte[] prv_array){
 | 
			
		||||
    super(jsch);
 | 
			
		||||
    if(name!=null)
 | 
			
		||||
      this.name = name;
 | 
			
		||||
    this.r_array = r_array;
 | 
			
		||||
    this.s_array = s_array;
 | 
			
		||||
    this.prv_array = prv_array;
 | 
			
		||||
    if(prv_array!=null)
 | 
			
		||||
      key_size = prv_array.length>=64 ? 521 : 
 | 
			
		||||
                  (prv_array.length>=48 ? 384 : 256);
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  void generate(int key_size) throws JSchException{
 | 
			
		||||
    this.key_size=key_size;
 | 
			
		||||
    try{
 | 
			
		||||
      Class c=Class.forName(jsch.getConfig("keypairgen.ecdsa"));
 | 
			
		||||
      KeyPairGenECDSA keypairgen=(KeyPairGenECDSA)(c.newInstance());
 | 
			
		||||
      keypairgen.init(key_size);
 | 
			
		||||
      prv_array=keypairgen.getD();
 | 
			
		||||
      r_array=keypairgen.getR();
 | 
			
		||||
      s_array=keypairgen.getS();
 | 
			
		||||
      name=Util.str2byte(names[prv_array.length>=64 ? 2 :
 | 
			
		||||
                               (prv_array.length>=48 ? 1 : 0)]);
 | 
			
		||||
      keypairgen=null;
 | 
			
		||||
    }
 | 
			
		||||
    catch(Exception e){
 | 
			
		||||
      if(e instanceof Throwable)
 | 
			
		||||
        throw new JSchException(e.toString(), (Throwable)e);
 | 
			
		||||
      throw new JSchException(e.toString());
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  private static final byte[] begin = 
 | 
			
		||||
    Util.str2byte("-----BEGIN EC PRIVATE KEY-----");
 | 
			
		||||
  private static final byte[] end =
 | 
			
		||||
    Util.str2byte("-----END EC PRIVATE KEY-----");
 | 
			
		||||
 | 
			
		||||
  byte[] getBegin(){ return begin; }
 | 
			
		||||
  byte[] getEnd(){ return end; }
 | 
			
		||||
 | 
			
		||||
  byte[] getPrivateKey(){
 | 
			
		||||
 | 
			
		||||
    byte[] tmp = new byte[1]; tmp[0]=1;
 | 
			
		||||
 | 
			
		||||
    byte[] oid = oids[
 | 
			
		||||
                      (r_array.length>=64) ? 2 :
 | 
			
		||||
                       ((r_array.length>=48) ? 1 : 0)
 | 
			
		||||
                     ];
 | 
			
		||||
 | 
			
		||||
    byte[] point = toPoint(r_array, s_array);
 | 
			
		||||
 | 
			
		||||
    int bar = ((point.length+1)&0x80)==0 ? 3 : 4;
 | 
			
		||||
    byte[] foo = new byte[point.length+bar];
 | 
			
		||||
    System.arraycopy(point, 0, foo, bar, point.length);
 | 
			
		||||
    foo[0]=0x03;                     // BITSTRING 
 | 
			
		||||
    if(bar==3){
 | 
			
		||||
      foo[1]=(byte)(point.length+1);
 | 
			
		||||
    }
 | 
			
		||||
    else {
 | 
			
		||||
      foo[1]=(byte)0x81;
 | 
			
		||||
      foo[2]=(byte)(point.length+1);
 | 
			
		||||
    }
 | 
			
		||||
    point = foo;
 | 
			
		||||
 | 
			
		||||
    int content=
 | 
			
		||||
      1+countLength(tmp.length) + tmp.length +
 | 
			
		||||
      1+countLength(prv_array.length) + prv_array.length +
 | 
			
		||||
      1+countLength(oid.length) + oid.length +
 | 
			
		||||
      1+countLength(point.length) + point.length;
 | 
			
		||||
 | 
			
		||||
    int total=
 | 
			
		||||
      1+countLength(content)+content;   // SEQUENCE
 | 
			
		||||
 | 
			
		||||
    byte[] plain=new byte[total];
 | 
			
		||||
    int index=0;
 | 
			
		||||
    index=writeSEQUENCE(plain, index, content);
 | 
			
		||||
    index=writeINTEGER(plain, index, tmp);
 | 
			
		||||
    index=writeOCTETSTRING(plain, index, prv_array);
 | 
			
		||||
    index=writeDATA(plain, (byte)0xa0, index, oid);
 | 
			
		||||
    index=writeDATA(plain, (byte)0xa1, index, point);
 | 
			
		||||
 | 
			
		||||
    return plain;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  boolean parse(byte[] plain){
 | 
			
		||||
    try{
 | 
			
		||||
 | 
			
		||||
      if(vendor==VENDOR_FSECURE){
 | 
			
		||||
        /*
 | 
			
		||||
	if(plain[0]!=0x30){              // FSecure
 | 
			
		||||
	  return true;
 | 
			
		||||
	}
 | 
			
		||||
	return false;
 | 
			
		||||
        */
 | 
			
		||||
	return false;
 | 
			
		||||
      }
 | 
			
		||||
      else if(vendor==VENDOR_PUTTY){
 | 
			
		||||
        /*
 | 
			
		||||
        Buffer buf=new Buffer(plain);
 | 
			
		||||
        buf.skip(plain.length);
 | 
			
		||||
 | 
			
		||||
        try {
 | 
			
		||||
          byte[][] tmp = buf.getBytes(1, "");
 | 
			
		||||
          prv_array = tmp[0];
 | 
			
		||||
        }
 | 
			
		||||
        catch(JSchException e){
 | 
			
		||||
          return false;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        return true;
 | 
			
		||||
        */
 | 
			
		||||
	return false;
 | 
			
		||||
      }
 | 
			
		||||
 | 
			
		||||
      int index=0;
 | 
			
		||||
      int length=0;
 | 
			
		||||
 | 
			
		||||
      if(plain[index]!=0x30)return false;
 | 
			
		||||
      index++; // SEQUENCE
 | 
			
		||||
      length=plain[index++]&0xff;
 | 
			
		||||
      if((length&0x80)!=0){
 | 
			
		||||
        int foo=length&0x7f; length=0;
 | 
			
		||||
        while(foo-->0){ length=(length<<8)+(plain[index++]&0xff); }
 | 
			
		||||
      }
 | 
			
		||||
 | 
			
		||||
      if(plain[index]!=0x02)return false;
 | 
			
		||||
      index++; // INTEGER
 | 
			
		||||
 | 
			
		||||
      length=plain[index++]&0xff;
 | 
			
		||||
      if((length&0x80)!=0){
 | 
			
		||||
        int foo=length&0x7f; length=0;
 | 
			
		||||
        while(foo-->0){ length=(length<<8)+(plain[index++]&0xff); }
 | 
			
		||||
      }
 | 
			
		||||
 | 
			
		||||
      index+=length;
 | 
			
		||||
      index++;   // 0x04
 | 
			
		||||
 | 
			
		||||
      length=plain[index++]&0xff;
 | 
			
		||||
      if((length&0x80)!=0){
 | 
			
		||||
        int foo=length&0x7f; length=0;
 | 
			
		||||
        while(foo-->0){ length=(length<<8)+(plain[index++]&0xff); }
 | 
			
		||||
      }
 | 
			
		||||
 | 
			
		||||
      prv_array=new byte[length];
 | 
			
		||||
      System.arraycopy(plain, index, prv_array, 0, length);
 | 
			
		||||
 | 
			
		||||
      index+=length;
 | 
			
		||||
 | 
			
		||||
      index++;  // 0xa0
 | 
			
		||||
 | 
			
		||||
      length=plain[index++]&0xff;
 | 
			
		||||
      if((length&0x80)!=0){
 | 
			
		||||
        int foo=length&0x7f; length=0;
 | 
			
		||||
        while(foo-->0){ length=(length<<8)+(plain[index++]&0xff); }
 | 
			
		||||
      }
 | 
			
		||||
 | 
			
		||||
      byte[] oid_array=new byte[length];
 | 
			
		||||
      System.arraycopy(plain, index, oid_array, 0, length);
 | 
			
		||||
      index+=length;
 | 
			
		||||
 | 
			
		||||
      for(int i = 0; i<oids.length; i++){
 | 
			
		||||
        if(Util.array_equals(oids[i], oid_array)){
 | 
			
		||||
          name = Util.str2byte(names[i]);
 | 
			
		||||
          break;
 | 
			
		||||
        }
 | 
			
		||||
      }
 | 
			
		||||
 | 
			
		||||
      index++;  // 0xa1
 | 
			
		||||
 | 
			
		||||
      length=plain[index++]&0xff;
 | 
			
		||||
      if((length&0x80)!=0){
 | 
			
		||||
        int foo=length&0x7f; length=0;
 | 
			
		||||
        while(foo-->0){ length=(length<<8)+(plain[index++]&0xff); }
 | 
			
		||||
      }
 | 
			
		||||
 | 
			
		||||
      byte[] Q_array=new byte[length];
 | 
			
		||||
      System.arraycopy(plain, index, Q_array, 0, length);
 | 
			
		||||
      index+=length;
 | 
			
		||||
 | 
			
		||||
      byte[][] tmp = fromPoint(Q_array);
 | 
			
		||||
      r_array = tmp[0];
 | 
			
		||||
      s_array = tmp[1];
 | 
			
		||||
 | 
			
		||||
      if(prv_array!=null)
 | 
			
		||||
        key_size = prv_array.length>=64 ? 521 : 
 | 
			
		||||
                    (prv_array.length>=48 ? 384 : 256);
 | 
			
		||||
    }
 | 
			
		||||
    catch(Exception e){
 | 
			
		||||
      //System.err.println(e);
 | 
			
		||||
      //e.printStackTrace();
 | 
			
		||||
      return false;
 | 
			
		||||
    }
 | 
			
		||||
    return true;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  public byte[] getPublicKeyBlob(){
 | 
			
		||||
    byte[] foo = super.getPublicKeyBlob();
 | 
			
		||||
 | 
			
		||||
    if(foo!=null) return foo;
 | 
			
		||||
 | 
			
		||||
    if(r_array==null) return null;
 | 
			
		||||
 | 
			
		||||
    byte[][] tmp = new byte[3][];
 | 
			
		||||
    tmp[0] = Util.str2byte("ecdsa-sha2-"+new String(name));
 | 
			
		||||
    tmp[1] = name;
 | 
			
		||||
    tmp[2] = new byte[1+r_array.length+s_array.length];
 | 
			
		||||
    tmp[2][0] = 4;   // POINT_CONVERSION_UNCOMPRESSED
 | 
			
		||||
    System.arraycopy(r_array, 0, tmp[2], 1, r_array.length);
 | 
			
		||||
    System.arraycopy(s_array, 0, tmp[2], 1+r_array.length, s_array.length);
 | 
			
		||||
 | 
			
		||||
    return Buffer.fromBytes(tmp).buffer;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  byte[] getKeyTypeName(){
 | 
			
		||||
    return Util.str2byte("ecdsa-sha2-"+new String(name));
 | 
			
		||||
  }
 | 
			
		||||
  public int getKeyType(){
 | 
			
		||||
    return ECDSA;
 | 
			
		||||
  }
 | 
			
		||||
  public int getKeySize(){
 | 
			
		||||
    return key_size;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  public byte[] getSignature(byte[] data){
 | 
			
		||||
    try{      
 | 
			
		||||
      Class c=Class.forName((String)jsch.getConfig("signature.ecdsa"));
 | 
			
		||||
      SignatureECDSA ecdsa=(SignatureECDSA)(c.newInstance());
 | 
			
		||||
      ecdsa.init();
 | 
			
		||||
      ecdsa.setPrvKey(prv_array);
 | 
			
		||||
 | 
			
		||||
      ecdsa.update(data);
 | 
			
		||||
      byte[] sig = ecdsa.sign();
 | 
			
		||||
 | 
			
		||||
      byte[][] tmp = new byte[2][];
 | 
			
		||||
      tmp[0] = Util.str2byte("ecdsa-sha2-"+new String(name));
 | 
			
		||||
      tmp[1] = sig;
 | 
			
		||||
      return Buffer.fromBytes(tmp).buffer;
 | 
			
		||||
    }
 | 
			
		||||
    catch(Exception e){
 | 
			
		||||
      //System.err.println("e "+e);
 | 
			
		||||
    }
 | 
			
		||||
    return null;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  public Signature getVerifier(){
 | 
			
		||||
    try{      
 | 
			
		||||
      Class c=Class.forName((String)jsch.getConfig("signature.ecdsa"));
 | 
			
		||||
      final SignatureECDSA ecdsa=(SignatureECDSA)(c.newInstance());
 | 
			
		||||
      ecdsa.init();
 | 
			
		||||
 | 
			
		||||
      if(r_array == null && s_array == null && getPublicKeyBlob()!=null){
 | 
			
		||||
        Buffer buf = new Buffer(getPublicKeyBlob());
 | 
			
		||||
        buf.getString();    // ecdsa-sha2-nistp256
 | 
			
		||||
        buf.getString();    // nistp256
 | 
			
		||||
        byte[][] tmp = fromPoint(buf.getString());
 | 
			
		||||
        r_array = tmp[0];
 | 
			
		||||
        s_array = tmp[1];
 | 
			
		||||
      } 
 | 
			
		||||
      ecdsa.setPubKey(r_array, s_array);
 | 
			
		||||
      return ecdsa;
 | 
			
		||||
    }
 | 
			
		||||
    catch(Exception e){
 | 
			
		||||
      //System.err.println("e "+e);
 | 
			
		||||
    }
 | 
			
		||||
    return null;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  static KeyPair fromSSHAgent(JSch jsch, Buffer buf) throws JSchException {
 | 
			
		||||
 | 
			
		||||
    byte[][] tmp = buf.getBytes(5, "invalid key format");
 | 
			
		||||
 | 
			
		||||
    byte[] name = tmp[1];       // nistp256
 | 
			
		||||
    byte[][] foo = fromPoint(tmp[2]);
 | 
			
		||||
    byte[] r_array = foo[0];
 | 
			
		||||
    byte[] s_array = foo[1];
 | 
			
		||||
 | 
			
		||||
    byte[] prv_array = tmp[3];
 | 
			
		||||
    KeyPairECDSA kpair = new KeyPairECDSA(jsch,
 | 
			
		||||
                                          name,
 | 
			
		||||
                                          r_array, s_array,
 | 
			
		||||
                                          prv_array);
 | 
			
		||||
    kpair.publicKeyComment = new String(tmp[4]);
 | 
			
		||||
    kpair.vendor=VENDOR_OPENSSH;
 | 
			
		||||
    return kpair;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  public byte[] forSSHAgent() throws JSchException {
 | 
			
		||||
    if(isEncrypted()){
 | 
			
		||||
      throw new JSchException("key is encrypted.");
 | 
			
		||||
    }
 | 
			
		||||
    Buffer buf = new Buffer();
 | 
			
		||||
    buf.putString(Util.str2byte("ecdsa-sha2-"+new String(name)));
 | 
			
		||||
    buf.putString(name);
 | 
			
		||||
    buf.putString(toPoint(r_array, s_array));
 | 
			
		||||
    buf.putString(prv_array);
 | 
			
		||||
    buf.putString(Util.str2byte(publicKeyComment));
 | 
			
		||||
    byte[] result = new byte[buf.getLength()];
 | 
			
		||||
    buf.getByte(result, 0, result.length);
 | 
			
		||||
    return result;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  static byte[] toPoint(byte[] r_array, byte[] s_array) {
 | 
			
		||||
    byte[] tmp = new byte[1+r_array.length+s_array.length];
 | 
			
		||||
    tmp[0]=0x04;
 | 
			
		||||
    System.arraycopy(r_array, 0, tmp, 1, r_array.length);
 | 
			
		||||
    System.arraycopy(s_array, 0, tmp, 1+r_array.length, s_array.length);
 | 
			
		||||
    return tmp;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  static byte[][] fromPoint(byte[] point) {
 | 
			
		||||
    int i = 0;
 | 
			
		||||
    while(point[i]!=4) i++;
 | 
			
		||||
    i++;
 | 
			
		||||
    byte[][] tmp = new byte[2][];
 | 
			
		||||
    byte[] r_array = new byte[(point.length-i)/2];
 | 
			
		||||
    byte[] s_array = new byte[(point.length-i)/2];
 | 
			
		||||
    // point[0] == 0x04 == POINT_CONVERSION_UNCOMPRESSED
 | 
			
		||||
    System.arraycopy(point, i, r_array, 0, r_array.length);
 | 
			
		||||
    System.arraycopy(point, i+r_array.length, s_array, 0, s_array.length);
 | 
			
		||||
    tmp[0] = r_array;
 | 
			
		||||
    tmp[1] = s_array;
 | 
			
		||||
 | 
			
		||||
    return tmp;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  public void dispose(){
 | 
			
		||||
    super.dispose();
 | 
			
		||||
    Util.bzero(prv_array);
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
@@ -1,6 +1,6 @@
 | 
			
		||||
/* -*-mode:java; c-basic-offset:2; indent-tabs-mode:nil -*- */
 | 
			
		||||
/*
 | 
			
		||||
Copyright (c) 2002-2012 ymnk, JCraft,Inc. All rights reserved.
 | 
			
		||||
Copyright (c) 2002-2016 ymnk, JCraft,Inc. All rights reserved.
 | 
			
		||||
 | 
			
		||||
Redistribution and use in source and binary forms, with or without
 | 
			
		||||
modification, are permitted provided that the following conditions are met:
 | 
			
		||||
 
 | 
			
		||||
@@ -0,0 +1,37 @@
 | 
			
		||||
/* -*-mode:java; c-basic-offset:2; indent-tabs-mode:nil -*- */
 | 
			
		||||
/*
 | 
			
		||||
Copyright (c) 2015-2016 ymnk, JCraft,Inc. All rights reserved.
 | 
			
		||||
 | 
			
		||||
Redistribution and use in source and binary forms, with or without
 | 
			
		||||
modification, are permitted provided that the following conditions are met:
 | 
			
		||||
 | 
			
		||||
  1. Redistributions of source code must retain the above copyright notice,
 | 
			
		||||
     this list of conditions and the following disclaimer.
 | 
			
		||||
 | 
			
		||||
  2. Redistributions in binary form must reproduce the above copyright 
 | 
			
		||||
     notice, this list of conditions and the following disclaimer in 
 | 
			
		||||
     the documentation and/or other materials provided with the distribution.
 | 
			
		||||
 | 
			
		||||
  3. The names of the authors may not be used to endorse or promote products
 | 
			
		||||
     derived from this software without specific prior written permission.
 | 
			
		||||
 | 
			
		||||
THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES,
 | 
			
		||||
INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
 | 
			
		||||
FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JCRAFT,
 | 
			
		||||
INC. OR ANY CONTRIBUTORS TO THIS SOFTWARE BE LIABLE FOR ANY DIRECT, INDIRECT,
 | 
			
		||||
INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
 | 
			
		||||
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
 | 
			
		||||
OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
 | 
			
		||||
LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
 | 
			
		||||
NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
 | 
			
		||||
EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 | 
			
		||||
*/
 | 
			
		||||
 | 
			
		||||
package com.jcraft.jsch;
 | 
			
		||||
 | 
			
		||||
public interface KeyPairGenECDSA{
 | 
			
		||||
  void init(int key_size) throws Exception;
 | 
			
		||||
  byte[] getD();
 | 
			
		||||
  byte[] getR();
 | 
			
		||||
  byte[] getS();
 | 
			
		||||
}
 | 
			
		||||
@@ -1,6 +1,6 @@
 | 
			
		||||
/* -*-mode:java; c-basic-offset:2; indent-tabs-mode:nil -*- */
 | 
			
		||||
/*
 | 
			
		||||
Copyright (c) 2002-2012 ymnk, JCraft,Inc. All rights reserved.
 | 
			
		||||
Copyright (c) 2002-2016 ymnk, JCraft,Inc. All rights reserved.
 | 
			
		||||
 | 
			
		||||
Redistribution and use in source and binary forms, with or without
 | 
			
		||||
modification, are permitted provided that the following conditions are met:
 | 
			
		||||
 
 | 
			
		||||
@@ -0,0 +1,363 @@
 | 
			
		||||
/* -*-mode:java; c-basic-offset:2; indent-tabs-mode:nil -*- */
 | 
			
		||||
/*
 | 
			
		||||
Copyright (c) 2013-2016 ymnk, JCraft,Inc. All rights reserved.
 | 
			
		||||
 | 
			
		||||
Redistribution and use in source and binary forms, with or without
 | 
			
		||||
modification, are permitted provided that the following conditions are met:
 | 
			
		||||
 | 
			
		||||
  1. Redistributions of source code must retain the above copyright notice,
 | 
			
		||||
     this list of conditions and the following disclaimer.
 | 
			
		||||
 | 
			
		||||
  2. Redistributions in binary form must reproduce the above copyright 
 | 
			
		||||
     notice, this list of conditions and the following disclaimer in 
 | 
			
		||||
     the documentation and/or other materials provided with the distribution.
 | 
			
		||||
 | 
			
		||||
  3. The names of the authors may not be used to endorse or promote products
 | 
			
		||||
     derived from this software without specific prior written permission.
 | 
			
		||||
 | 
			
		||||
THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES,
 | 
			
		||||
INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
 | 
			
		||||
FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JCRAFT,
 | 
			
		||||
INC. OR ANY CONTRIBUTORS TO THIS SOFTWARE BE LIABLE FOR ANY DIRECT, INDIRECT,
 | 
			
		||||
INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
 | 
			
		||||
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
 | 
			
		||||
OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
 | 
			
		||||
LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
 | 
			
		||||
NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
 | 
			
		||||
EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 | 
			
		||||
*/
 | 
			
		||||
 | 
			
		||||
package com.jcraft.jsch;
 | 
			
		||||
 | 
			
		||||
import java.util.Vector;
 | 
			
		||||
import java.math.BigInteger;
 | 
			
		||||
 | 
			
		||||
public class KeyPairPKCS8 extends KeyPair {
 | 
			
		||||
  private static final byte[] rsaEncryption = {
 | 
			
		||||
    (byte)0x2a, (byte)0x86, (byte)0x48, (byte)0x86,
 | 
			
		||||
    (byte)0xf7, (byte)0x0d, (byte)0x01, (byte)0x01, (byte)0x01
 | 
			
		||||
  };
 | 
			
		||||
 | 
			
		||||
  private static final byte[] dsaEncryption = {
 | 
			
		||||
    (byte)0x2a, (byte)0x86, (byte)0x48, (byte)0xce,
 | 
			
		||||
    (byte)0x38, (byte)0x04, (byte)0x1
 | 
			
		||||
  };
 | 
			
		||||
 | 
			
		||||
  private static final byte[] pbes2 = {
 | 
			
		||||
    (byte)0x2a, (byte)0x86, (byte)0x48, (byte)0x86, (byte)0xf7,
 | 
			
		||||
    (byte)0x0d, (byte)0x01, (byte)0x05, (byte)0x0d 
 | 
			
		||||
  };
 | 
			
		||||
 | 
			
		||||
  private static final byte[] pbkdf2 = {
 | 
			
		||||
    (byte)0x2a, (byte)0x86, (byte)0x48, (byte)0x86, (byte)0xf7,
 | 
			
		||||
    (byte)0x0d, (byte)0x01, (byte)0x05, (byte)0x0c 
 | 
			
		||||
  };
 | 
			
		||||
 | 
			
		||||
  private static final byte[] aes128cbc = {
 | 
			
		||||
    (byte)0x60, (byte)0x86, (byte)0x48, (byte)0x01, (byte)0x65,
 | 
			
		||||
    (byte)0x03, (byte)0x04, (byte)0x01, (byte)0x02 
 | 
			
		||||
  };
 | 
			
		||||
 | 
			
		||||
  private static final byte[] aes192cbc = {
 | 
			
		||||
    (byte)0x60, (byte)0x86, (byte)0x48, (byte)0x01, (byte)0x65,
 | 
			
		||||
    (byte)0x03, (byte)0x04, (byte)0x01, (byte)0x16 
 | 
			
		||||
  };
 | 
			
		||||
 | 
			
		||||
  private static final byte[] aes256cbc = {
 | 
			
		||||
    (byte)0x60, (byte)0x86, (byte)0x48, (byte)0x01, (byte)0x65,
 | 
			
		||||
    (byte)0x03, (byte)0x04, (byte)0x01, (byte)0x2a 
 | 
			
		||||
  };
 | 
			
		||||
 | 
			
		||||
  private static final byte[] pbeWithMD5AndDESCBC = {
 | 
			
		||||
    (byte)0x2a, (byte)0x86, (byte)0x48, (byte)0x86, (byte)0xf7,
 | 
			
		||||
    (byte)0x0d, (byte)0x01, (byte)0x05, (byte)0x03
 | 
			
		||||
  };
 | 
			
		||||
 | 
			
		||||
  private KeyPair kpair = null;
 | 
			
		||||
 | 
			
		||||
  public KeyPairPKCS8(JSch jsch){
 | 
			
		||||
    super(jsch);
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  void generate(int key_size) throws JSchException{
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  private static final byte[] begin=Util.str2byte("-----BEGIN DSA PRIVATE KEY-----");
 | 
			
		||||
  private static final byte[] end=Util.str2byte("-----END DSA PRIVATE KEY-----");
 | 
			
		||||
 | 
			
		||||
  byte[] getBegin(){ return begin; }
 | 
			
		||||
  byte[] getEnd(){ return end; }
 | 
			
		||||
 | 
			
		||||
  byte[] getPrivateKey(){
 | 
			
		||||
    return null;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  boolean parse(byte[] plain){
 | 
			
		||||
 | 
			
		||||
    /* from RFC5208
 | 
			
		||||
      PrivateKeyInfo ::= SEQUENCE {
 | 
			
		||||
        version                   Version,
 | 
			
		||||
        privateKeyAlgorithm       PrivateKeyAlgorithmIdentifier,
 | 
			
		||||
        privateKey                PrivateKey,
 | 
			
		||||
        attributes           [0]  IMPLICIT Attributes OPTIONAL 
 | 
			
		||||
      }
 | 
			
		||||
      Version ::= INTEGER
 | 
			
		||||
      PrivateKeyAlgorithmIdentifier ::= AlgorithmIdentifier
 | 
			
		||||
      PrivateKey ::= OCTET STRING
 | 
			
		||||
      Attributes ::= SET OF Attribute
 | 
			
		||||
    }
 | 
			
		||||
    */
 | 
			
		||||
 | 
			
		||||
    try{
 | 
			
		||||
      Vector values = new Vector();
 | 
			
		||||
 | 
			
		||||
      ASN1[] contents = null;
 | 
			
		||||
      ASN1 asn1 = new ASN1(plain);
 | 
			
		||||
      contents = asn1.getContents();
 | 
			
		||||
 | 
			
		||||
      ASN1 privateKeyAlgorithm = contents[1];
 | 
			
		||||
      ASN1 privateKey = contents[2];
 | 
			
		||||
 | 
			
		||||
      contents = privateKeyAlgorithm.getContents();
 | 
			
		||||
      byte[] privateKeyAlgorithmID = contents[0].getContent();
 | 
			
		||||
      contents = contents[1].getContents();
 | 
			
		||||
      if(contents.length>0){
 | 
			
		||||
        for(int i = 0; i < contents.length; i++){
 | 
			
		||||
          values.addElement(contents[i].getContent());
 | 
			
		||||
        }
 | 
			
		||||
      }
 | 
			
		||||
 | 
			
		||||
      byte[] _data = privateKey.getContent();
 | 
			
		||||
 | 
			
		||||
      KeyPair _kpair = null;
 | 
			
		||||
      if(Util.array_equals(privateKeyAlgorithmID, rsaEncryption)){
 | 
			
		||||
        _kpair = new KeyPairRSA(jsch);
 | 
			
		||||
        _kpair.copy(this);
 | 
			
		||||
        if(_kpair.parse(_data)){
 | 
			
		||||
          kpair = _kpair;
 | 
			
		||||
        } 
 | 
			
		||||
      }
 | 
			
		||||
      else if(Util.array_equals(privateKeyAlgorithmID, dsaEncryption)){
 | 
			
		||||
        asn1 = new ASN1(_data);
 | 
			
		||||
        if(values.size() == 0) {  // embedded DSA parameters format
 | 
			
		||||
          /*
 | 
			
		||||
             SEQUENCE
 | 
			
		||||
               SEQUENCE
 | 
			
		||||
                 INTEGER    // P_array
 | 
			
		||||
                 INTEGER    // Q_array
 | 
			
		||||
                 INTEGER    // G_array
 | 
			
		||||
               INTEGER      // prv_array
 | 
			
		||||
          */
 | 
			
		||||
          contents = asn1.getContents();
 | 
			
		||||
          byte[] bar = contents[1].getContent();
 | 
			
		||||
          contents = contents[0].getContents();
 | 
			
		||||
          for(int i = 0; i < contents.length; i++){
 | 
			
		||||
            values.addElement(contents[i].getContent());
 | 
			
		||||
          }
 | 
			
		||||
          values.addElement(bar);
 | 
			
		||||
        }
 | 
			
		||||
        else {
 | 
			
		||||
          /*
 | 
			
		||||
             INTEGER      // prv_array
 | 
			
		||||
          */
 | 
			
		||||
          values.addElement(asn1.getContent());
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        byte[] P_array = (byte[])values.elementAt(0);
 | 
			
		||||
        byte[] Q_array = (byte[])values.elementAt(1);
 | 
			
		||||
        byte[] G_array = (byte[])values.elementAt(2);
 | 
			
		||||
        byte[] prv_array = (byte[])values.elementAt(3);
 | 
			
		||||
        // Y = g^X mode p
 | 
			
		||||
        byte[] pub_array =
 | 
			
		||||
          (new BigInteger(G_array)).
 | 
			
		||||
            modPow(new BigInteger(prv_array), new BigInteger(P_array)).
 | 
			
		||||
            toByteArray();
 | 
			
		||||
 | 
			
		||||
        KeyPairDSA _key = new KeyPairDSA(jsch,
 | 
			
		||||
                                         P_array, Q_array, G_array,
 | 
			
		||||
                                         pub_array, prv_array);
 | 
			
		||||
        plain = _key.getPrivateKey();
 | 
			
		||||
 | 
			
		||||
        _kpair = new KeyPairDSA(jsch);
 | 
			
		||||
        _kpair.copy(this);
 | 
			
		||||
        if(_kpair.parse(plain)){
 | 
			
		||||
          kpair = _kpair;
 | 
			
		||||
        }
 | 
			
		||||
      }
 | 
			
		||||
    }
 | 
			
		||||
    catch(ASN1Exception e){
 | 
			
		||||
      return false;
 | 
			
		||||
    }
 | 
			
		||||
    catch(Exception e){
 | 
			
		||||
      //System.err.println(e);
 | 
			
		||||
      return false;
 | 
			
		||||
    }
 | 
			
		||||
    return kpair != null;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  public byte[] getPublicKeyBlob(){
 | 
			
		||||
    return kpair.getPublicKeyBlob();
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  byte[] getKeyTypeName(){ return kpair.getKeyTypeName();}
 | 
			
		||||
  public int getKeyType(){return kpair.getKeyType();}
 | 
			
		||||
 | 
			
		||||
  public int getKeySize(){
 | 
			
		||||
    return kpair.getKeySize();
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  public byte[] getSignature(byte[] data){
 | 
			
		||||
    return kpair.getSignature(data);
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  public Signature getVerifier(){
 | 
			
		||||
    return kpair.getVerifier();
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  public byte[] forSSHAgent() throws JSchException {
 | 
			
		||||
    return kpair.forSSHAgent();
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  public boolean decrypt(byte[] _passphrase){
 | 
			
		||||
    if(!isEncrypted()){
 | 
			
		||||
      return true;
 | 
			
		||||
    }
 | 
			
		||||
    if(_passphrase==null){
 | 
			
		||||
      return !isEncrypted();
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /*
 | 
			
		||||
      SEQUENCE
 | 
			
		||||
        SEQUENCE
 | 
			
		||||
          OBJECT            :PBES2
 | 
			
		||||
          SEQUENCE
 | 
			
		||||
            SEQUENCE
 | 
			
		||||
              OBJECT            :PBKDF2
 | 
			
		||||
              SEQUENCE
 | 
			
		||||
                OCTET STRING      [HEX DUMP]:E4E24ADC9C00BD4D
 | 
			
		||||
                INTEGER           :0800
 | 
			
		||||
            SEQUENCE
 | 
			
		||||
              OBJECT            :aes-128-cbc
 | 
			
		||||
              OCTET STRING      [HEX DUMP]:5B66E6B3BF03944C92317BC370CC3AD0
 | 
			
		||||
        OCTET STRING      [HEX DUMP]:
 | 
			
		||||
 | 
			
		||||
or
 | 
			
		||||
 | 
			
		||||
      SEQUENCE
 | 
			
		||||
        SEQUENCE
 | 
			
		||||
          OBJECT            :pbeWithMD5AndDES-CBC
 | 
			
		||||
          SEQUENCE
 | 
			
		||||
            OCTET STRING      [HEX DUMP]:DBF75ECB69E3C0FC
 | 
			
		||||
            INTEGER           :0800
 | 
			
		||||
        OCTET STRING      [HEX DUMP]
 | 
			
		||||
    */
 | 
			
		||||
 | 
			
		||||
    try{
 | 
			
		||||
 | 
			
		||||
      ASN1[] contents = null;
 | 
			
		||||
      ASN1 asn1 = new ASN1(data);
 | 
			
		||||
 | 
			
		||||
      contents =  asn1.getContents();
 | 
			
		||||
 | 
			
		||||
      byte[] _data = contents[1].getContent();
 | 
			
		||||
 | 
			
		||||
      ASN1 pbes = contents[0];
 | 
			
		||||
      contents = pbes.getContents();
 | 
			
		||||
      byte[] pbesid = contents[0].getContent();
 | 
			
		||||
      ASN1 pbesparam = contents[1];
 | 
			
		||||
 | 
			
		||||
      byte[] salt = null;
 | 
			
		||||
      int iterations = 0;
 | 
			
		||||
      byte[] iv = null;
 | 
			
		||||
      byte[] encryptfuncid = null;
 | 
			
		||||
 | 
			
		||||
      if(Util.array_equals(pbesid, pbes2)){
 | 
			
		||||
        contents = pbesparam.getContents();
 | 
			
		||||
        ASN1 pbkdf = contents[0];
 | 
			
		||||
        ASN1 encryptfunc = contents[1];
 | 
			
		||||
        contents = pbkdf.getContents();
 | 
			
		||||
        byte[] pbkdfid = contents[0].getContent();
 | 
			
		||||
        ASN1 pbkdffunc = contents[1];
 | 
			
		||||
        contents = pbkdffunc.getContents();
 | 
			
		||||
        salt = contents[0].getContent();
 | 
			
		||||
        iterations = 
 | 
			
		||||
          Integer.parseInt((new BigInteger(contents[1].getContent())).toString());
 | 
			
		||||
 | 
			
		||||
        contents = encryptfunc.getContents();
 | 
			
		||||
        encryptfuncid = contents[0].getContent();
 | 
			
		||||
        iv = contents[1].getContent();
 | 
			
		||||
      }
 | 
			
		||||
      else if(Util.array_equals(pbesid, pbeWithMD5AndDESCBC)){
 | 
			
		||||
        // not supported
 | 
			
		||||
        return false;
 | 
			
		||||
      }
 | 
			
		||||
      else {
 | 
			
		||||
        return false;
 | 
			
		||||
      }
 | 
			
		||||
 | 
			
		||||
      Cipher cipher=getCipher(encryptfuncid);
 | 
			
		||||
      if(cipher==null) return false;
 | 
			
		||||
 | 
			
		||||
      byte[] key=null;
 | 
			
		||||
      try{
 | 
			
		||||
        Class c=Class.forName((String)jsch.getConfig("pbkdf"));
 | 
			
		||||
        PBKDF tmp=(PBKDF)(c.newInstance());
 | 
			
		||||
        key = tmp.getKey(_passphrase, salt, iterations, cipher.getBlockSize());
 | 
			
		||||
      }
 | 
			
		||||
      catch(Exception ee){
 | 
			
		||||
      }
 | 
			
		||||
 | 
			
		||||
      if(key==null){
 | 
			
		||||
        return false;
 | 
			
		||||
      }
 | 
			
		||||
 | 
			
		||||
      cipher.init(Cipher.DECRYPT_MODE, key, iv);
 | 
			
		||||
      Util.bzero(key);
 | 
			
		||||
      byte[] plain=new byte[_data.length];
 | 
			
		||||
      cipher.update(_data, 0, _data.length, plain, 0);
 | 
			
		||||
      if(parse(plain)){
 | 
			
		||||
        encrypted=false;
 | 
			
		||||
        return true;
 | 
			
		||||
      }
 | 
			
		||||
    }
 | 
			
		||||
    catch(ASN1Exception e){
 | 
			
		||||
      // System.err.println(e);
 | 
			
		||||
    }
 | 
			
		||||
    catch(Exception e){
 | 
			
		||||
      // System.err.println(e);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    return false;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  Cipher getCipher(byte[] id){
 | 
			
		||||
    Cipher cipher=null;
 | 
			
		||||
    String name = null;
 | 
			
		||||
    try{
 | 
			
		||||
      if(Util.array_equals(id, aes128cbc)){
 | 
			
		||||
        name="aes128-cbc";
 | 
			
		||||
      }
 | 
			
		||||
      else if(Util.array_equals(id, aes192cbc)){
 | 
			
		||||
        name="aes192-cbc";
 | 
			
		||||
      }
 | 
			
		||||
      else if(Util.array_equals(id, aes256cbc)){
 | 
			
		||||
        name="aes256-cbc";
 | 
			
		||||
      }
 | 
			
		||||
      Class c=Class.forName((String)jsch.getConfig(name));
 | 
			
		||||
      cipher=(Cipher)(c.newInstance());
 | 
			
		||||
    }
 | 
			
		||||
    catch(Exception e){
 | 
			
		||||
      if(JSch.getLogger().isEnabled(Logger.FATAL)){
 | 
			
		||||
        String message="";
 | 
			
		||||
        if(name==null){
 | 
			
		||||
          message="unknown oid: "+Util.toHex(id);
 | 
			
		||||
        }
 | 
			
		||||
        else {
 | 
			
		||||
          message="function "+name+" is not supported";
 | 
			
		||||
        }
 | 
			
		||||
        JSch.getLogger().log(Logger.FATAL, "PKCS8: "+message);
 | 
			
		||||
      }
 | 
			
		||||
    }
 | 
			
		||||
    return cipher;
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
@@ -1,6 +1,6 @@
 | 
			
		||||
/* -*-mode:java; c-basic-offset:2; indent-tabs-mode:nil -*- */
 | 
			
		||||
/*
 | 
			
		||||
Copyright (c) 2002-2012 ymnk, JCraft,Inc. All rights reserved.
 | 
			
		||||
Copyright (c) 2002-2016 ymnk, JCraft,Inc. All rights reserved.
 | 
			
		||||
 | 
			
		||||
Redistribution and use in source and binary forms, with or without
 | 
			
		||||
modification, are permitted provided that the following conditions are met:
 | 
			
		||||
 
 | 
			
		||||
@@ -1,6 +1,6 @@
 | 
			
		||||
/* -*-mode:java; c-basic-offset:2; indent-tabs-mode:nil -*- */
 | 
			
		||||
/*
 | 
			
		||||
Copyright (c) 2002-2012 ymnk, JCraft,Inc. All rights reserved.
 | 
			
		||||
Copyright (c) 2002-2016 ymnk, JCraft,Inc. All rights reserved.
 | 
			
		||||
 | 
			
		||||
Redistribution and use in source and binary forms, with or without
 | 
			
		||||
modification, are permitted provided that the following conditions are met:
 | 
			
		||||
@@ -35,12 +35,6 @@ public
 | 
			
		||||
class KnownHosts implements HostKeyRepository{
 | 
			
		||||
  private static final String _known_hosts="known_hosts";
 | 
			
		||||
 | 
			
		||||
  /*
 | 
			
		||||
  static final int SSHDSS=0;
 | 
			
		||||
  static final int SSHRSA=1;
 | 
			
		||||
  static final int UNKNOWN=2;
 | 
			
		||||
  */
 | 
			
		||||
 | 
			
		||||
  private JSch jsch=null;
 | 
			
		||||
  private String known_hosts=null;
 | 
			
		||||
  private java.util.Vector pool=null;
 | 
			
		||||
@@ -50,26 +44,28 @@ class KnownHosts implements HostKeyRepository{
 | 
			
		||||
  KnownHosts(JSch jsch){
 | 
			
		||||
    super();
 | 
			
		||||
    this.jsch=jsch;
 | 
			
		||||
    this.hmacsha1 = getHMACSHA1();
 | 
			
		||||
    pool=new java.util.Vector();
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  void setKnownHosts(String foo) throws JSchException{
 | 
			
		||||
  void setKnownHosts(String filename) throws JSchException{
 | 
			
		||||
    try{
 | 
			
		||||
      known_hosts = foo;
 | 
			
		||||
      FileInputStream fis=new FileInputStream(Util.checkTilde(foo));
 | 
			
		||||
      known_hosts = filename;
 | 
			
		||||
      FileInputStream fis=new FileInputStream(Util.checkTilde(filename));
 | 
			
		||||
      setKnownHosts(fis);
 | 
			
		||||
    }
 | 
			
		||||
    catch(FileNotFoundException e){
 | 
			
		||||
      // The non-existing file should be allowed.
 | 
			
		||||
    } 
 | 
			
		||||
  }
 | 
			
		||||
  void setKnownHosts(InputStream foo) throws JSchException{
 | 
			
		||||
  void setKnownHosts(InputStream input) throws JSchException{
 | 
			
		||||
    pool.removeAllElements();
 | 
			
		||||
    StringBuffer sb=new StringBuffer();
 | 
			
		||||
    byte i;
 | 
			
		||||
    int j;
 | 
			
		||||
    boolean error=false;
 | 
			
		||||
    try{
 | 
			
		||||
      InputStream fis=foo;
 | 
			
		||||
      InputStream fis=input;
 | 
			
		||||
      String host;
 | 
			
		||||
      String key=null;
 | 
			
		||||
      int type;
 | 
			
		||||
@@ -158,8 +154,10 @@ loop:
 | 
			
		||||
          if(i==0x20 || i=='\t'){ break; }
 | 
			
		||||
          sb.append((char)i);
 | 
			
		||||
	}
 | 
			
		||||
	if(sb.toString().equals("ssh-dss")){ type=HostKey.SSHDSS; }
 | 
			
		||||
	else if(sb.toString().equals("ssh-rsa")){ type=HostKey.SSHRSA; }
 | 
			
		||||
	String tmp = sb.toString();
 | 
			
		||||
	if(HostKey.name2type(tmp)!=HostKey.UNKNOWN){
 | 
			
		||||
	  type=HostKey.name2type(tmp);
 | 
			
		||||
	}
 | 
			
		||||
	else { j=bufl; }
 | 
			
		||||
	if(j>=bufl){
 | 
			
		||||
	  addInvalidLine(Util.byte2str(buf, 0, bufl));
 | 
			
		||||
@@ -223,7 +221,6 @@ loop:
 | 
			
		||||
                                               key.length()), comment);
 | 
			
		||||
	pool.addElement(hk);
 | 
			
		||||
      }
 | 
			
		||||
      fis.close();
 | 
			
		||||
      if(error){
 | 
			
		||||
	throw new JSchException("KnownHosts: invalid format");
 | 
			
		||||
      }
 | 
			
		||||
@@ -235,6 +232,12 @@ loop:
 | 
			
		||||
        throw new JSchException(e.toString(), (Throwable)e);
 | 
			
		||||
      throw new JSchException(e.toString());
 | 
			
		||||
    }
 | 
			
		||||
    finally {
 | 
			
		||||
      try{ input.close(); }
 | 
			
		||||
      catch(IOException e){
 | 
			
		||||
        throw new JSchException(e.toString(), (Throwable)e);
 | 
			
		||||
      }
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
  private void addInvalidLine(String line) throws JSchException {
 | 
			
		||||
    HostKey hk = new HostKey(line, HostKey.UNKNOWN, null);
 | 
			
		||||
@@ -249,14 +252,19 @@ loop:
 | 
			
		||||
      return result;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    int type=getType(key);
 | 
			
		||||
    HostKey hk;
 | 
			
		||||
    HostKey hk = null;
 | 
			
		||||
    try {
 | 
			
		||||
      hk = new HostKey(host, HostKey.GUESS, key);
 | 
			
		||||
    }
 | 
			
		||||
    catch(JSchException e){  // unsupported key
 | 
			
		||||
      return result;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    synchronized(pool){
 | 
			
		||||
      for(int i=0; i<pool.size(); i++){
 | 
			
		||||
        hk=(HostKey)(pool.elementAt(i));
 | 
			
		||||
        if(hk.isMatched(host) && hk.type==type){
 | 
			
		||||
          if(Util.array_equals(hk.key, key)){
 | 
			
		||||
        HostKey _hk=(HostKey)(pool.elementAt(i));
 | 
			
		||||
        if(_hk.isMatched(host) && _hk.type==hk.type){
 | 
			
		||||
          if(Util.array_equals(_hk.key, key)){
 | 
			
		||||
            return OK;
 | 
			
		||||
          }
 | 
			
		||||
          else{
 | 
			
		||||
@@ -347,27 +355,29 @@ loop:
 | 
			
		||||
  }
 | 
			
		||||
  public HostKey[] getHostKey(String host, String type){
 | 
			
		||||
    synchronized(pool){
 | 
			
		||||
      int count=0;
 | 
			
		||||
      java.util.ArrayList v = new java.util.ArrayList();
 | 
			
		||||
      for(int i=0; i<pool.size(); i++){
 | 
			
		||||
	HostKey hk=(HostKey)pool.elementAt(i);
 | 
			
		||||
	if(hk.type==HostKey.UNKNOWN) continue;
 | 
			
		||||
	if(host==null || 
 | 
			
		||||
	   (hk.isMatched(host) && 
 | 
			
		||||
	    (type==null || hk.getType().equals(type)))){
 | 
			
		||||
	  count++;
 | 
			
		||||
          v.add(hk);
 | 
			
		||||
	}
 | 
			
		||||
      }
 | 
			
		||||
      if(count==0)return null;
 | 
			
		||||
      HostKey[] foo=new HostKey[count];
 | 
			
		||||
      int j=0;
 | 
			
		||||
      for(int i=0; i<pool.size(); i++){
 | 
			
		||||
	HostKey hk=(HostKey)pool.elementAt(i);
 | 
			
		||||
	if(hk.type==HostKey.UNKNOWN) continue;
 | 
			
		||||
	if(host==null || 
 | 
			
		||||
	   (hk.isMatched(host) && 
 | 
			
		||||
	    (type==null || hk.getType().equals(type)))){
 | 
			
		||||
	  foo[j++]=hk;
 | 
			
		||||
	}
 | 
			
		||||
      HostKey[] foo = new HostKey[v.size()];
 | 
			
		||||
      for(int i=0; i<v.size(); i++){
 | 
			
		||||
        foo[i] = (HostKey)v.get(i);
 | 
			
		||||
      }
 | 
			
		||||
      if(host != null && host.startsWith("[") && host.indexOf("]:")>1){
 | 
			
		||||
        HostKey[] tmp =
 | 
			
		||||
          getHostKey(host.substring(1, host.indexOf("]:")), type);
 | 
			
		||||
        if(tmp.length > 0){
 | 
			
		||||
          HostKey[] bar = new HostKey[foo.length + tmp.length];
 | 
			
		||||
          System.arraycopy(foo, 0, bar, 0, foo.length);
 | 
			
		||||
          System.arraycopy(tmp, 0, bar, foo.length, tmp.length);
 | 
			
		||||
          foo = bar;
 | 
			
		||||
        }
 | 
			
		||||
      }
 | 
			
		||||
      return foo;
 | 
			
		||||
    }
 | 
			
		||||
@@ -452,11 +462,7 @@ loop:
 | 
			
		||||
      System.err.println(e);
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
  private int getType(byte[] key){
 | 
			
		||||
    if(key[8]=='d') return HostKey.SSHDSS;
 | 
			
		||||
    if(key[8]=='r') return HostKey.SSHRSA;
 | 
			
		||||
    return HostKey.UNKNOWN;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  private String deleteSubString(String hosts, String host){
 | 
			
		||||
    int i=0;
 | 
			
		||||
    int hostlen=host.length();
 | 
			
		||||
@@ -477,7 +483,7 @@ loop:
 | 
			
		||||
    return hosts;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  private synchronized MAC getHMACSHA1(){
 | 
			
		||||
  private MAC getHMACSHA1(){
 | 
			
		||||
    if(hmacsha1==null){
 | 
			
		||||
      try{
 | 
			
		||||
        Class c=Class.forName(jsch.getConfig("hmac-sha1"));
 | 
			
		||||
@@ -503,7 +509,6 @@ loop:
 | 
			
		||||
    byte[] salt=null;
 | 
			
		||||
    byte[] hash=null;
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
    HashedHostKey(String host, byte[] key) throws JSchException {
 | 
			
		||||
      this(host, GUESS, key);
 | 
			
		||||
    }
 | 
			
		||||
 
 | 
			
		||||
@@ -1,6 +1,6 @@
 | 
			
		||||
/* -*-mode:java; c-basic-offset:2; indent-tabs-mode:nil -*- */
 | 
			
		||||
/*
 | 
			
		||||
Copyright (c) 2012 ymnk, JCraft,Inc. All rights reserved.
 | 
			
		||||
Copyright (c) 2012-2016 ymnk, JCraft,Inc. All rights reserved.
 | 
			
		||||
 | 
			
		||||
Redistribution and use in source and binary forms, with or without
 | 
			
		||||
modification, are permitted provided that the following conditions are met:
 | 
			
		||||
@@ -50,6 +50,7 @@ class LocalIdentityRepository implements IdentityRepository {
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  public synchronized Vector getIdentities() {
 | 
			
		||||
    removeDupulicates();
 | 
			
		||||
    Vector v = new Vector();
 | 
			
		||||
    for(int i=0; i<identities.size(); i++){
 | 
			
		||||
      v.addElement(identities.elementAt(i));
 | 
			
		||||
@@ -59,6 +60,23 @@ class LocalIdentityRepository implements IdentityRepository {
 | 
			
		||||
 | 
			
		||||
  public synchronized void add(Identity identity) {
 | 
			
		||||
    if(!identities.contains(identity)) {
 | 
			
		||||
      byte[] blob1 = identity.getPublicKeyBlob();
 | 
			
		||||
      if(blob1 == null) {
 | 
			
		||||
        identities.addElement(identity);
 | 
			
		||||
        return;
 | 
			
		||||
      }
 | 
			
		||||
      for(int i = 0; i<identities.size(); i++){
 | 
			
		||||
        byte[] blob2 = ((Identity)identities.elementAt(i)).getPublicKeyBlob();
 | 
			
		||||
        if(blob2 != null && Util.array_equals(blob1, blob2)){
 | 
			
		||||
          if(!identity.isEncrypted() && 
 | 
			
		||||
             ((Identity)identities.elementAt(i)).isEncrypted()){
 | 
			
		||||
            remove(blob2);
 | 
			
		||||
          }
 | 
			
		||||
          else {  
 | 
			
		||||
            return;
 | 
			
		||||
          }
 | 
			
		||||
        }
 | 
			
		||||
      }
 | 
			
		||||
      identities.addElement(identity);
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
@@ -67,7 +85,7 @@ class LocalIdentityRepository implements IdentityRepository {
 | 
			
		||||
    try{
 | 
			
		||||
      Identity _identity =
 | 
			
		||||
        IdentityFile.newInstance("from remote:", identity, null, jsch);
 | 
			
		||||
      identities.addElement(_identity);
 | 
			
		||||
      add(_identity);
 | 
			
		||||
      return true;
 | 
			
		||||
    }
 | 
			
		||||
    catch(JSchException e){
 | 
			
		||||
@@ -76,7 +94,13 @@ class LocalIdentityRepository implements IdentityRepository {
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  synchronized void remove(Identity identity) {
 | 
			
		||||
    identities.removeElement(identity);
 | 
			
		||||
    if(identities.contains(identity)) {
 | 
			
		||||
      identities.removeElement(identity);
 | 
			
		||||
      identity.clear();
 | 
			
		||||
    }
 | 
			
		||||
    else {
 | 
			
		||||
      remove(identity.getPublicKeyBlob());
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  public synchronized boolean remove(byte[] blob) {
 | 
			
		||||
@@ -100,4 +124,28 @@ class LocalIdentityRepository implements IdentityRepository {
 | 
			
		||||
    }
 | 
			
		||||
    identities.removeAllElements();
 | 
			
		||||
  } 
 | 
			
		||||
 | 
			
		||||
  private void removeDupulicates(){
 | 
			
		||||
    Vector v = new Vector();
 | 
			
		||||
    int len = identities.size();
 | 
			
		||||
    if(len == 0) return;
 | 
			
		||||
    for(int i=0; i<len; i++){
 | 
			
		||||
      Identity foo = (Identity)identities.elementAt(i);
 | 
			
		||||
      byte[] foo_blob = foo.getPublicKeyBlob();
 | 
			
		||||
      if(foo_blob == null) continue;
 | 
			
		||||
      for(int j=i+1; j<len; j++){
 | 
			
		||||
        Identity bar = (Identity)identities.elementAt(j);
 | 
			
		||||
        byte[] bar_blob = bar.getPublicKeyBlob();
 | 
			
		||||
        if(bar_blob == null) continue;
 | 
			
		||||
        if(Util.array_equals(foo_blob, bar_blob) &&
 | 
			
		||||
           foo.isEncrypted() == bar.isEncrypted()){
 | 
			
		||||
          v.addElement(foo_blob);
 | 
			
		||||
          break;
 | 
			
		||||
        }
 | 
			
		||||
      }
 | 
			
		||||
    }
 | 
			
		||||
    for(int i=0; i<v.size(); i++){
 | 
			
		||||
      remove((byte[])v.elementAt(i));
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -1,6 +1,6 @@
 | 
			
		||||
/* -*-mode:java; c-basic-offset:2; indent-tabs-mode:nil -*- */
 | 
			
		||||
/*
 | 
			
		||||
Copyright (c) 2006-2012 ymnk, JCraft,Inc. All rights reserved.
 | 
			
		||||
Copyright (c) 2006-2016 ymnk, JCraft,Inc. All rights reserved.
 | 
			
		||||
 | 
			
		||||
Redistribution and use in source and binary forms, with or without
 | 
			
		||||
modification, are permitted provided that the following conditions are met:
 | 
			
		||||
 
 | 
			
		||||
@@ -1,6 +1,6 @@
 | 
			
		||||
/* -*-mode:java; c-basic-offset:2; indent-tabs-mode:nil -*- */
 | 
			
		||||
/*
 | 
			
		||||
Copyright (c) 2002-2012 ymnk, JCraft,Inc. All rights reserved.
 | 
			
		||||
Copyright (c) 2002-2016 ymnk, JCraft,Inc. All rights reserved.
 | 
			
		||||
 | 
			
		||||
Redistribution and use in source and binary forms, with or without
 | 
			
		||||
modification, are permitted provided that the following conditions are met:
 | 
			
		||||
 
 | 
			
		||||
@@ -1,6 +1,6 @@
 | 
			
		||||
/* -*-mode:java; c-basic-offset:2; indent-tabs-mode:nil -*- */
 | 
			
		||||
/*
 | 
			
		||||
Copyright (c) 2013 ymnk, JCraft,Inc. All rights reserved.
 | 
			
		||||
Copyright (c) 2013-2016 ymnk, JCraft,Inc. All rights reserved.
 | 
			
		||||
 | 
			
		||||
Redistribution and use in source and binary forms, with or without
 | 
			
		||||
modification, are permitted provided that the following conditions are met:
 | 
			
		||||
@@ -30,10 +30,9 @@ EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 | 
			
		||||
package com.jcraft.jsch;
 | 
			
		||||
 | 
			
		||||
import java.io.InputStream;
 | 
			
		||||
import java.io.File;
 | 
			
		||||
import java.io.FileInputStream;
 | 
			
		||||
import java.io.ByteArrayInputStream;
 | 
			
		||||
import java.io.InputStreamReader;
 | 
			
		||||
import java.io.Reader;
 | 
			
		||||
import java.io.StringReader;
 | 
			
		||||
import java.io.FileReader;
 | 
			
		||||
import java.io.BufferedReader;
 | 
			
		||||
import java.io.IOException;
 | 
			
		||||
import java.util.Hashtable;
 | 
			
		||||
@@ -78,12 +77,12 @@ public class OpenSSHConfig implements ConfigRepository {
 | 
			
		||||
   * @return an instanceof OpenSSHConfig
 | 
			
		||||
   */
 | 
			
		||||
  public static OpenSSHConfig parse(String conf) throws IOException {
 | 
			
		||||
    InputStream in = new ByteArrayInputStream(Util.str2byte(conf));
 | 
			
		||||
    Reader r = new StringReader(conf);
 | 
			
		||||
    try {
 | 
			
		||||
      return new OpenSSHConfig(in);
 | 
			
		||||
      return new OpenSSHConfig(r);
 | 
			
		||||
    }
 | 
			
		||||
    finally {
 | 
			
		||||
      in.close();
 | 
			
		||||
      r.close();
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
@@ -94,25 +93,24 @@ public class OpenSSHConfig implements ConfigRepository {
 | 
			
		||||
   * @return an instanceof OpenSSHConfig
 | 
			
		||||
   */
 | 
			
		||||
  public static OpenSSHConfig parseFile(String file) throws IOException {
 | 
			
		||||
    byte[] conf = Util.fromFile(file);
 | 
			
		||||
    InputStream in = new ByteArrayInputStream(conf);
 | 
			
		||||
    Reader r = new FileReader(Util.checkTilde(file));
 | 
			
		||||
    try {
 | 
			
		||||
      return new OpenSSHConfig(in);
 | 
			
		||||
      return new OpenSSHConfig(r);
 | 
			
		||||
    }
 | 
			
		||||
    finally {
 | 
			
		||||
      in.close();
 | 
			
		||||
      r.close();
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  OpenSSHConfig(InputStream in) throws IOException {
 | 
			
		||||
    _parse(in);
 | 
			
		||||
  OpenSSHConfig(Reader r) throws IOException {
 | 
			
		||||
    _parse(r);
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  private final Hashtable config = new Hashtable();
 | 
			
		||||
  private final Vector hosts = new Vector();
 | 
			
		||||
 | 
			
		||||
  private void _parse(InputStream in) throws IOException {
 | 
			
		||||
    BufferedReader br = new BufferedReader(new InputStreamReader(in));
 | 
			
		||||
  private void _parse(Reader r) throws IOException {
 | 
			
		||||
    BufferedReader br = new BufferedReader(r);
 | 
			
		||||
 | 
			
		||||
    String host = "";
 | 
			
		||||
    Vector/*<String[]>*/ kv = new Vector();
 | 
			
		||||
@@ -200,12 +198,13 @@ public class OpenSSHConfig implements ConfigRepository {
 | 
			
		||||
      if(keymap.get(key)!=null) {
 | 
			
		||||
        key = (String)keymap.get(key);
 | 
			
		||||
      }
 | 
			
		||||
      key = key.toUpperCase();
 | 
			
		||||
      String value = null;
 | 
			
		||||
      for(int i = 0; i < _configs.size(); i++) {
 | 
			
		||||
        Vector v = (Vector)_configs.elementAt(i);
 | 
			
		||||
        for(int j = 0; j < v.size(); j++) {
 | 
			
		||||
          String[] kv = (String[])v.elementAt(j);
 | 
			
		||||
          if(kv[0].equals(key)) {
 | 
			
		||||
          if(kv[0].toUpperCase().equals(key)) {
 | 
			
		||||
            value = kv[1];
 | 
			
		||||
            break;
 | 
			
		||||
          }
 | 
			
		||||
@@ -217,12 +216,13 @@ public class OpenSSHConfig implements ConfigRepository {
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    private String[] multiFind(String key) {
 | 
			
		||||
      key = key.toUpperCase();
 | 
			
		||||
      Vector value = new Vector();
 | 
			
		||||
      for(int i = 0; i < _configs.size(); i++) {
 | 
			
		||||
        Vector v = (Vector)_configs.elementAt(i);
 | 
			
		||||
        for(int j = 0; j < v.size(); j++) {
 | 
			
		||||
          String[] kv = (String[])v.elementAt(j);
 | 
			
		||||
          if(kv[0].equals(key)) {
 | 
			
		||||
          if(kv[0].toUpperCase().equals(key)) {
 | 
			
		||||
            String foo = kv[1];
 | 
			
		||||
            if(foo != null) {
 | 
			
		||||
              value.remove(foo);
 | 
			
		||||
 
 | 
			
		||||
@@ -0,0 +1,34 @@
 | 
			
		||||
/* -*-mode:java; c-basic-offset:2; indent-tabs-mode:nil -*- */
 | 
			
		||||
/*
 | 
			
		||||
Copyright (c) 2013-2016 ymnk, JCraft,Inc. All rights reserved.
 | 
			
		||||
 | 
			
		||||
Redistribution and use in source and binary forms, with or without
 | 
			
		||||
modification, are permitted provided that the following conditions are met:
 | 
			
		||||
 | 
			
		||||
  1. Redistributions of source code must retain the above copyright notice,
 | 
			
		||||
     this list of conditions and the following disclaimer.
 | 
			
		||||
 | 
			
		||||
  2. Redistributions in binary form must reproduce the above copyright 
 | 
			
		||||
     notice, this list of conditions and the following disclaimer in 
 | 
			
		||||
     the documentation and/or other materials provided with the distribution.
 | 
			
		||||
 | 
			
		||||
  3. The names of the authors may not be used to endorse or promote products
 | 
			
		||||
     derived from this software without specific prior written permission.
 | 
			
		||||
 | 
			
		||||
THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES,
 | 
			
		||||
INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
 | 
			
		||||
FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JCRAFT,
 | 
			
		||||
INC. OR ANY CONTRIBUTORS TO THIS SOFTWARE BE LIABLE FOR ANY DIRECT, INDIRECT,
 | 
			
		||||
INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
 | 
			
		||||
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
 | 
			
		||||
OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
 | 
			
		||||
LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
 | 
			
		||||
NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
 | 
			
		||||
EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 | 
			
		||||
*/
 | 
			
		||||
 | 
			
		||||
package com.jcraft.jsch;
 | 
			
		||||
 | 
			
		||||
public interface PBKDF {
 | 
			
		||||
  byte[] getKey(byte[] pass, byte[] salt, int iteration, int size);
 | 
			
		||||
}
 | 
			
		||||
@@ -1,6 +1,6 @@
 | 
			
		||||
/* -*-mode:java; c-basic-offset:2; indent-tabs-mode:nil -*- */
 | 
			
		||||
/*
 | 
			
		||||
Copyright (c) 2002-2012 ymnk, JCraft,Inc. All rights reserved.
 | 
			
		||||
Copyright (c) 2002-2016 ymnk, JCraft,Inc. All rights reserved.
 | 
			
		||||
 | 
			
		||||
Redistribution and use in source and binary forms, with or without
 | 
			
		||||
modification, are permitted provided that the following conditions are met:
 | 
			
		||||
 
 | 
			
		||||
@@ -1,6 +1,6 @@
 | 
			
		||||
/* -*-mode:java; c-basic-offset:2; indent-tabs-mode:nil -*- */
 | 
			
		||||
/*
 | 
			
		||||
Copyright (c) 2002-2012 ymnk, JCraft,Inc. All rights reserved.
 | 
			
		||||
Copyright (c) 2002-2016 ymnk, JCraft,Inc. All rights reserved.
 | 
			
		||||
 | 
			
		||||
Redistribution and use in source and binary forms, with or without
 | 
			
		||||
modification, are permitted provided that the following conditions are met:
 | 
			
		||||
 
 | 
			
		||||
@@ -1,6 +1,6 @@
 | 
			
		||||
/* -*-mode:java; c-basic-offset:2; indent-tabs-mode:nil -*- */
 | 
			
		||||
/*
 | 
			
		||||
Copyright (c) 2002-2012 ymnk, JCraft,Inc. All rights reserved.
 | 
			
		||||
Copyright (c) 2002-2016 ymnk, JCraft,Inc. All rights reserved.
 | 
			
		||||
 | 
			
		||||
Redistribution and use in source and binary forms, with or without
 | 
			
		||||
modification, are permitted provided that the following conditions are met:
 | 
			
		||||
 
 | 
			
		||||
Some files were not shown because too many files have changed in this diff Show More
		Reference in New Issue
	
	Block a user