Index: wp-admin/includes/class-wp-filesystem-base.php
===================================================================
--- wp-admin/includes/class-wp-filesystem-base.php	(revision 25195)
+++ wp-admin/includes/class-wp-filesystem-base.php	(working copy)
@@ -39,6 +39,15 @@
 	var $method = '';
 
 	/**
+	 * Whether this filesystem supports file MD5s
+	 *
+	 * @since 3.7
+	 * @access public
+	 * @var bool
+	 */
+	var $supports_md5 = false;
+
+	/**
 	 * Returns the path on the remote filesystem of ABSPATH
 	 *
 	 * @since 2.7
Index: wp-admin/includes/class-wp-filesystem-ftpsockets.php
===================================================================
--- wp-admin/includes/class-wp-filesystem-ftpsockets.php	(revision 25195)
+++ wp-admin/includes/class-wp-filesystem-ftpsockets.php	(working copy)
@@ -266,6 +266,10 @@
 		return false;
 	}
 
+	function md5( $file ) {
+		return false;
+	}
+
 	function mkdir($path, $chmod = false, $chown = false, $chgrp = false ) {
 		$path = untrailingslashit($path);
 		if ( empty($path) )
Index: wp-admin/includes/update-core.php
===================================================================
--- wp-admin/includes/update-core.php	(revision 25195)
+++ wp-admin/includes/update-core.php	(working copy)
@@ -656,6 +656,22 @@
 		return new WP_Error( 'insane_distro', __('The update could not be unpacked') );
 	}
 
+	// Check if we have the correct files
+	include_once( $from . $distro . 'wp-admin/includes/update-core-file-hashes.php' );
+	if ( empty( $file_hashes ) ) {
+		$wp_filesystem->delete( $from, true );
+		return new WP_Error( 'no_file_hashes', __( 'The update did not contain file hashes' ) );
+	}
+
+	if ( $wp_filesystem->supports_md5 ) {
+		foreach ( $file_hashes as $file => $hash ) {
+			if ( $hash !== $wp_filesystem->md5( $file ) ) {
+				$wp_filesystem->delete( $from, true );
+				return new WP_Error( 'bad_file_hashes', __( 'The update did not match the included file hashes' ) );
+			}
+		}
+	}
+
 	// Import $wp_version, $required_php_version, and $required_mysql_version from the new version
 	// $wp_filesystem->wp_content_dir() returned unslashed pre-2.8
 	$versions_file = trailingslashit( $wp_filesystem->wp_content_dir() ) . 'upgrade/version-current.php';
Index: wp-admin/includes/class-wp-filesystem-direct.php
===================================================================
--- wp-admin/includes/class-wp-filesystem-direct.php	(revision 25195)
+++ wp-admin/includes/class-wp-filesystem-direct.php	(working copy)
@@ -22,8 +22,9 @@
 	 * @param mixed $arg ignored argument
 	 */
 	function __construct($arg) {
-		$this->method = 'direct';
-		$this->errors = new WP_Error();
+		$this->method       = 'direct';
+		$this->errors       = new WP_Error();
+		$this->supports_md5 = true;
 	}
 	/**
 	 * connect filesystem.
@@ -283,6 +284,10 @@
 		return @touch($file, $time, $atime);
 	}
 
+	function md5( $file ) {
+		return @md5_file( $file );
+	}
+
 	function mkdir($path, $chmod = false, $chown = false, $chgrp = false) {
 		// safe mode fails with a trailing slash under certain PHP versions.
 		$path = untrailingslashit($path);
@@ -346,6 +351,7 @@
 			$struc['lastmod']   = date('M j',$struc['lastmodunix']);
 			$struc['time']    	= date('h:i:s',$struc['lastmodunix']);
 			$struc['type']		= $this->is_dir($path.'/'.$entry) ? 'd' : 'f';
+			$struc['md5']       = $this->md5( $path . '/' . $entry );
 
 			if ( 'd' == $struc['type'] ) {
 				if ( $recursive )
Index: wp-admin/includes/class-wp-filesystem-ftpext.php
===================================================================
--- wp-admin/includes/class-wp-filesystem-ftpext.php	(revision 25195)
+++ wp-admin/includes/class-wp-filesystem-ftpext.php	(working copy)
@@ -246,6 +246,11 @@
 	function touch($file, $time = 0, $atime = 0) {
 		return false;
 	}
+
+	function md5( $file ) {
+		return false;
+	}
+
 	function mkdir($path, $chmod = false, $chown = false, $chgrp = false) {
 		$path = untrailingslashit($path);
 		if ( empty($path) )
Index: wp-admin/includes/class-wp-filesystem-ssh2.php
===================================================================
--- wp-admin/includes/class-wp-filesystem-ssh2.php	(revision 25195)
+++ wp-admin/includes/class-wp-filesystem-ssh2.php	(working copy)
@@ -49,8 +49,9 @@
 	var $options = array();
 
 	function __construct($opt='') {
-		$this->method = 'ssh2';
-		$this->errors = new WP_Error();
+		$this->method       = 'ssh2';
+		$this->errors       = new WP_Error();
+		$this->supports_md5 = true;
 
 		//Check if possible to use ssh2 functions.
 		if ( ! extension_loaded('ssh2') ) {
@@ -309,6 +310,11 @@
 		//Not implemented.
 	}
 
+	function md5( $file ) {
+		$file = ltrim( $file, '/' );
+		return md5_file( 'ssh2.sftp://' . $this->sftp_link . '/' . $file );
+	}
+
 	function mkdir($path, $chmod = false, $chown = false, $chgrp = false) {
 		$path = untrailingslashit($path);
 		if ( empty($path) )
@@ -369,6 +375,7 @@
 			$struc['lastmod']   = date('M j',$struc['lastmodunix']);
 			$struc['time']    	= date('h:i:s',$struc['lastmodunix']);
 			$struc['type']		= $this->is_dir($path.'/'.$entry) ? 'd' : 'f';
+			$struc['md5']       = $this->md5( $path . '/' . $entry );
 
 			if ( 'd' == $struc['type'] ) {
 				if ( $recursive )
