Android API Guides---Host-based Card Emulation
Host-based Card Emulation
很多提供NFC功能的Android手机已经支持NFC卡模拟。在大多数情况下。该卡是由在该装置的单独芯片仿真,称为安全元件。
无线运营商提供了非常多的SIM卡还包括一个安全元件。
Android 4.4系统的介绍卡仿真的一个额外的方法,不涉及安全的元素,称为基于主机的卡仿真。
这同意不论什么Android应用程序来模拟卡。并直接交谈的NFC读取器。本文介绍了基于主机的卡模拟(HCE)怎样适用于Android以及怎样开发模拟使用这样的技术的NFC卡的应用程序。
卡仿真与安全元素
当使用一个安全元件提供的NFC卡模拟。要被模仿的卡通过Android应用程序供应到设备上的安全元件。
然后。当用户将器件保持在的NFC终端中,NFC控制器在设备路由来自读取器直接到安全元件的全部数据。图1示出了这个概念。
图1. NFC卡模拟与安全元件。
安全元件本身运行与NFC终端的通信。而且没有Android应用是參与交易的。该交易完毕后,Android应用程序能够直接查询安全元件的交易状态,并通知用户。
基于主机的卡仿真
当NFC卡使用基于主机的卡模拟仿真,数据被路由到其上Android应用直接执行的主机的CPU,而不是路由NFC协议帧的安全元件。图2显示了基于主机的卡仿真怎样工作的。
图2. NFC卡模拟没有一个安全元件。
支持NFC卡和协议
图3. Android的HCE协议栈。
在NFC标准提供很多不同的协议的支持,而且有可模拟不同类型的卡。
Android 4.4系统支持多种协议,今天在市场上非经常见。很多现有的非接触式卡已经依据这些协议,如非接触式支付卡。这些协议也被当今市场上的很多读者NFC。包含Android NFC设备作为读者工作本身(见IsoDep类)的支持。
这使您能够构建和部署各地HCE仅仅使用Android手机的终端到终端的NFC解决方式。
详细地。机器人4.4支架模拟卡,基于NFC的论坛的ISO-DEP规范(依据ISO / IEC 14443-4)和如在ISO / IEC 7816-4规格定义的过程的应用协议数据单元(PDU)。 Android的授权仅仅在NFC-A(ISO / IEC 14443-3 A型)技术之上模仿ISO-DEP。对于NFC-B(ISO / IEC 14443-4 B型)的技术支持是可选的。全部这些规范的分层显示在图3中。
HCE服务
在Android上的HCE架构基于Android的左右Service组件(称为“HCE服务”)。
一个的服务的主要长处是。它能够在没有不论什么用户界面的后台执行。
这是天作之合很多HCE应用,如忠诚或过境卡。与用户应该不须要启动的应用程序来使用它。相反,轻敲设备对NFC读取器启动正确的服务(假设没有执行),并在后台执行事务。当然,你能够自由地从服务推出很多其它的UI(如用户通知)假设是有道理的。
服务选择
当用户点击一个设备的NFC读写器,Android系统须要知道HCE服务的NFC读卡器竟然想跟。这就是ISO / IEC 7816-4规格进来:它定义了一种方法来选择应用程序。环绕一个应用程序ID(AID)居中。援助最多由16个字节。假设你是模拟卡现有的NFC阅读器的基础设施。艾滋病。这些读者都在寻找一般知名及公开注冊的(比如。支付网络。如Visa和万事达卡的艾滋病)。
假设你想为自己的应用程序部署新的基础设施的读者。您将须要注冊自己的AID(S)。
艾滋病的注冊过程在ISO / IEC 7816-5规范中定义。
谷歌建议。假设你正在为Android部署HCE申请注冊一个AID按7816-5,由于这将避免与其它应用程序冲突。
援助团体
在一些情况下,HCE服务可能须要注冊多个艾滋病实现一定的应用。它须要以确保它是全部这些艾滋病的默认处理(相对于该组中的一些艾滋病到还有一个服务) 。
一个AID基是艾滋病的列表应被视为由OS一起属于。对于AID组中的全部艾滋病,Android的保障下列之中的一个:
该组中的全部艾滋病被路由到该HCE服务
该组中没有艾滋病被路由到这个HCE服务(比如,因为用户优选的哪个请求的一个或多个艾滋病的组中的还有一个服务以及)
换句话说,没有中间状态,当中,该组中的某些助剂能够被路由给一个HCE服务。一些到还有一个。
援助团体和类别
每一个AID基团可与一个类别相关联。这使得Android的分组HCE服务结合在一起按类别,而这又使用户能够在类别级别而不是AID级别设置默认值。
普通情况下。避免在您的应用程序的不论什么面向用户的部分提的艾滋病:他们并不意味着不论什么普通用户。
Android 4.4系统支持两类:CATEGORY_PAYMENT(包含行业标准的支付应用程序)和CATEGORY_OTHER(对于全部其它应用HCE)。
注意:仅仅有一个在CATEGORY_PAYMENT类别AID基团能够在该系统中的不论什么给定的时间被激活。通常情况下,这将是了解基本的信用卡支付protcols并能够在不论什么商户工作的应用程序。
对于闭环支付应用程序,仅仅在一个商人的工作(如储值卡),你应该使用CATEGORY_OTHER。此类别中的AID团能够是总是活动的,而且能够在必要时通过NFC阅读器的AID选择期间给予优先权。
实现一个HCE服务
要使用基于主机的卡仿真模拟的NFC卡,你须要创建一个处理NFC交易服务组件。
检查HCE支持
您的应用程序能够检查通过检查FEATURE_NFC_HOST_CARD_EMULATION功能的设备是否支持HCE。
您应该使用<用途特征>标签在你的应用程序的清单,宣布你的应用程序使用HCE功能。它是否须要为应用程序的功能或没有。
服务实现
Android 4.4系统配备了便民服务类,它能够被用来作为一个基础,实现HCE服务:HostApduService类。
因此。第一步骤是扩展HostApduService。
public class MyHostApduService extends HostApduService {
@Override
public byte[] processCommandApdu(byte[] apdu, Bundle extras) {
...
}
@Override
public void onDeactivated(int reason) {
...
}
}
HostApduService声明须要重写和实施两个抽象方法。
流程CommandApdu()当一个NFC读写器发送一个应用协议数据单元(APDU)到您的服务调用。
的APDU是在ISO / IEC 7816-4规格定义为好。 APDU的是NFC读写器和您的HCE服务之间交换的应用级的数据包。这样的应用层协议是半双工的:在NFC读写器会送你一个APDU命令,它会等待你的回报发送响应APDU。
注:ISO / IEC 7816-4规范还定义了多个逻辑通道。在那里你能够在不同的逻辑通道多路并行APDU交换的概念。
然而。Android的HCE实现仅仅支持一个单一的逻辑通道。所以有唯一的APDU单线程交流。
正如前面提到的。Android使用的AID来确定读者想与哪个HCE服务。
典型地,第一APDU的NFC读取器发送至设备是一个“SELECT AID”APDU;这个APDU包括了读者想要交谈的帮助。
Android的提取从APDU AID,它解析为HCE服务,那么APDU到解决服务前锋。
您能够通过从processCommandApdu返回响应APDU的字节发送响应APDU()。注意,此方法将您的应用程序,它不应该被阻止的主线程中调用。所以,假设你不能立即计算并返回响应APDU。返回null。然后,您能够做还有一个线程必要的工作。并使用在HostApduService类中定义的sendResponseApdu()方法来发送响应。当你完毕。
Android将保持从读者服务的新转发的APDU,直到:
在NFC读取器发送还有一个“SELECT AID”APDU。该操作系统解析为不同的服务;
在NFC读写器和设备之间的NFC链路中断。
在这两种情况下,你的类onDeactivated()实现调用參数指示哪个两个发生了。
假设您正在使用现有的基础设施读者工作。你须要实现现有应用级协议。读者在你的HCE服务的期望。
假设您正在部署,你控制,以及新的读者基础设施,您能够定义自己的协议和APDU序列。一般试图限制的APDU的量和须要被交换的数据的大小:这使得确保用户将仅仅须要在NFC读取器持有他们的设备的时间短量。
一个理智的上限是数据。这通常300ms以内进行交换约1KB。
服务清单申报和登记AID
你的服务必须在清单照常被声明,但一些附加件必须被加入到该服务声明为好。
首先,要告诉这个平台,这是实现HostApduService接口的HCE服务。您的服务声明必须包括SERVICE_INTERFACE操作的意图过滤器。
另外。告诉这是由该服务要求艾滋病群体平台,SERVICE_META_DATA <元数据>标签必须包括在服务的声明,指出有关的HCE服务的附加信息的XML资源。
出口属性设置为true,并要求在服务声明中的“android.permission.BIND_NFC_SERVICE”权限:最后,你必须在Android设置。前者能够确保该服务能够通过外部应用程序绑定。
后者则强制运行该举办“android.permission.BIND_NFC_SERVICE”仅仅同意外部应用程序能够绑定到你的服务。因为“android.permission.BIND_NFC_SERVICE”是一个系统的权限。这有效地强制运行,仅仅有Android操作系统能够绑定到你的服务。
这里有一个HostApduService舱单申报的例子:
<service android:name=".MyHostApduService" android:exported="true"
android:permission="android.permission.BIND_NFC_SERVICE">
<intent-filter>
<action android:name="android.nfc.cardemulation.action.HOST_APDU_SERVICE"/>
</intent-filter>
<meta-data android:name="android.nfc.cardemulation.host_apdu_service"
android:resource="@xml/apduservice"/>
</service>
这种元数据标记指向一个APDU service.xml文件。
与含有两个专有艾滋病单个AID组声明这种文件的一个样例例如以下所看到的:
<host-apdu-service xmlns:android="http://schemas.android.com/apk/res/android"
android:description="@string/servicedesc"
android:requireDeviceUnlock="false">
<aid-group android:description="@string/aiddescription"
android:category="other">
<aid-filter android:name="F0010203040506"/>
<aid-filter android:name="F0394148148100"/>
</aid-group>
</host-apdu-service>
他<主机-APDU服务>标签必须包括<安卓说明>包括了能够在用户界面中显示的服务的用户友好的描写叙述属性。该requireDeviceUnlock属性能够用来指定设备必须解锁之前该服务能够被调用来处理APDU的。
在<主机-APDU服务>必须包括一个或多个<援助团>标记。每一个<援助团>标签要求:
包括一个机器人:包括AID组的一个用户友好的描写叙述。适合在UI显示描写叙述属性。
有它的android:类属性设置为指示AID集团所属。比如类别通过CATEGORY_PAYMENT或CATEGORY_OTHER定义字符串常量。
每一个<援助组>必须包括一个或多个<援助滤波器>标记。每一个都包括一个帮助。
援助必须以十六进制格式指定,并包括偶数个字符。
最后要注意。你的应用程序也须要持有NFC权限才干作为HCE服务注冊。
AID解决冲突
多个HostApduService部件能够被安装在单个设备上,和同样的AID能够由一个以上的服务进行注冊。
Android平台的解决依赖于哪一类援助属于AID冲突。每一个类别能够有不同的解决冲突的政策。
比如,对于一些类别(比如支付)的用户可以在Android设置界面。选择默认服务。对于其它类别的政策可能是总是问这服务是在发生冲突时要调用的用户。要查询某一类的解决冲突的策略。请參阅getSelectionModeForCategory()。
检查,假设你的服务是默认
应用程序能够检查通过使用isDefaultServiceForCategory(单元名,字符串)的API的HCE服务是否为特定类别的默认服务。
假设您的服务是不是默认的。能够要求其进行预设。
见ACTION_CHANGE_DEFAULT。
支付应用程序
Android的觉得,已经宣布的“支付”类别作为支付应用的AID组HCE服务。
而Android 4.4版本号包括被称为“感应付款”顶层设置菜单项,当中列举了全部此类支付应用。
在此设置菜单中,用户能够选择当一个支付终端被窃听。将调用默认的支付应用。
支付应用所需的资产
为了提供更加视觉吸引力的用户体验,HCE支付应用都须要为他们提供服务的额外资产:所谓服务的一面旗帜。
该资产的大小应260x96 DP。可在您的元数据的XML文件里加入了android指定:apduServiceBanner属性加入到<主机-APDU服务>标签,它指向绘制资源。
一个样例例如以下所看到的:
<host-apdu-service xmlns:android="http://schemas.android.com/apk/res/android"
android:description="@string/servicedesc"
android:requireDeviceUnlock="false"
android:apduServiceBanner="@drawable/my_banner">
<aid-group android:description="@string/aiddescription"
android:category="payment">
<aid-filter android:name="F0010203040506"/>
<aid-filter android:name="F0394148148100"/>
</aid-group>
</host-apdu-service>
屏幕关闭和锁定屏幕行为
眼下Android实现打开在NFC控制器和应用处理器全然关闭时,设备的屏幕被关闭。
当屏幕处于关闭状态HCE服务会因此无法正常工作。
HCE服务能够可是锁屏功能:在requireDeviceUnlock属性<主机-APDU服务>您HCE服务标签:这是由机器人控制的。
缺省情况下,不要求设备解锁。而且即使该设备被锁定的服务将被调用。
假设你设置了android:requireDeviceUnlock属性为“true”为您服务HCE,Android将提示用户解锁,当你点击一个选择被解析为您服务援助的NFC阅读器的设备。
解锁之后,Android将显示一个对话框,提示用户再次点击就可以完毕交易。这是必要的,由于用户可能会以解锁移动该设备远离NFC阅读器。
共存安全元素卡
这部分是已部署了赖以卡仿真的安全元件上的应用程序开发者的兴趣。 Android的HCE实现设计平行实施卡模拟的其它方法。包含使用安全元件的工作。
注意:Android不用于与安全元件本身直接通信提供的API。
此共存是基于一个所谓的“AID路由”的原则:在NFC控制器保持一个包括的路由规则(有限的)列表的路由表。每一个路由规则包括一个AID和目标。目标能够是主机CPU(如Android应用程序正在执行),或连接的安全元件。
当NFC读写器发送一个APDU一个“SELECT AID”中,NFC控制器解析它,并检查是否艾滋病在其路由表中的不论什么引援。
假设匹配,该APDU和其后的全部的APDU将被发送到与AID相关联的目的地,直到还有一个“SELECT AID”APDU被接收或在NFC链路断开。
注意:在ISO / IEC 7816-4定义“部分匹配”的概念,那么,这是不是眼下由Android HCE设备支持。
这样的架构在图4中示出。
图4. Android的既安全元件和主机卡仿真执行。
该NFC控制器通常还包括APDU的默认路由。当在路由表中没有找到一个AID,则使用缺省路由。与Android 4.4開始,须要默认路由设置为主机CPU。这意味着。在路由表通常仅包括该须要去的安全元件艾滋病条目。
实现一个HCE服务或使用的安全元件不必操心配置路由表的Android应用程序 - 由Android的自己主动照应。机器人只须要知道哪个助剂能够由HCE服务来处理和哪些能够通过安全元件来处理。在此基础上的服务的安装和用户已配置为优选的,路由表被自己主动配置。
我们已经介绍了怎样申报艾滋病HCE服务。
下面部分说明怎样声明艾滋病使用安全元素为卡仿真应用。
安全元件AID登记
使用卡模拟的安全元件的应用程序可在其清单中声明一个所谓的“关主机服务”。这样的服务的声明差点儿是同样的一个HCE服务的声明。
例外的是:
在意向滤波器中使用的动作必须被设置为SERVICE_INTERFACE。
元数据的名称属性必须设置为SERVICE_META_DATA。
元数据的XML文件必须使用<脱离主机-APDU服务>根标签。
<service android:name=".MyOffHostApduService" android:exported="true"
android:permission="android.permission.BIND_NFC_SERVICE">
<intent-filter>
<action android:name="android.nfc.cardemulation.action.OFF_HOST_APDU_SERVICE"/>
</intent-filter>
<meta-data android:name="android.nfc.cardemulation.off_host_apdu_ervice"
android:resource="@xml/apduservice"/>
</service>
对应的APDU service.xml文件注冊二援助的一个样例:
<offhost-apdu-service xmlns:android="http://schemas.android.com/apk/res/android"
android:description="@string/servicedesc">
<aid-group android:description="@string/subscription" android:category="other">
<aid-filter android:name="F0010203040506"/>
<aid-filter android:name="F0394148148100"/>
</aid-group>
</offhost-apdu-service>
Android的:requireDeviceUnlock属性并不适用于过主机服务,由于主机CPU不參与交易,因此无法阻止运行交易安全元件时,该设备已被锁定。
Android的:apduServiceBanner属性必须被用于那些支付应用,以及,以便选择作为默认支付应用关闭主机服务。
关闭主机服务调用
Android的本身永远不会启动或绑定到被声明为“关主”的服务。这是由于实际的事务是由安全元件,而不是由在Android服务本身运行。该服务声明仅仅是同意应用程序注冊艾滋病存在的安全元素。
HCE和安全
该HCE架构本身提供了一个核心片的安全性:由于你的服务是由BIND_NFC_SERVICE系统权限保护,仅仅有操作系统能够结合并与您的服务进行通信。这可确保您收到不论什么APDU实际上是一个由来自NFC控制器操作系统收到APDU。不论什么APDU你送回仅仅会去操作系统。这又直接转发的APDU到NFC控制器。
核心剩下的部分是你在哪里得到你的数据,你的应用程序发送到NFC阅读器。
这是分离有意在HCE设计:它并不关心那里的数据从何而来,它仅仅是确保它安全地运送到NFC控制器和输出到NFC阅读器。
为了安全地存储和检索,你想从你的HCE服务发送的数据,就能够了,比如,依靠Android应用程序沙箱。它从其它应用程序隔离应用程序数据。有关Android安全的很多其它具体信息,请阅读安全提示。
协议參数和细节
这部分是为希望了解什么协议參数HCE设备中的NFC协议的防碰撞和激活阶段使用的开发者的兴趣。
这样就能够建立一个阅读器的基础设施。与Android HCE设备兼容。
NFC-A(ISO / IEC 14443 A类)协议,防冲突和激活
随着NFC-A协议激活的一部分,多个帧交换。
在这次交易中HCE设备将展示其UID的第一部分; HCE设备应当被假定为具有随机UID。这意味着,在每个抽头。即呈现给读者将UID将随机生成的UID。正由于如此,NFC读取器不应该依赖于HCE设备的UID作为认证或识别的一种形式。
该NFC阅读器能够通过发送一个命令SEL_REQ随后选择HCE设备。该HCE器件的响应SEL_RES将至少有6位(0x20的)集。表示该设备支持ISO-DEP。
注意。在SEL_RES其他位能够被设置为好,指示为NFC-DEP(P2P)协议演示样例的支持。由于其他位可设置,想与HCE设备进行交互的读者应该明白检查仅第6位,而不是完整的SEL_RES用0x20的值进行比較。
ISO-DEP激活
在NFC-A协议被激活后,将ISO-DEP协议激活由NFC读取器启动。
它发出了一个“老鼠”(请求应答来选择)命令。的大鼠的反应中,ATS,全然是由NFC控制器产生,而不是由HCE服务配置。然而,HCE实现都必须以满足ATS响应NFC论坛的要求。因此NFC读者能够对这些參数依照不论什么HCE设备NFC论坛的要求被设置计数。
下面部分提供了一个HCE设备上的NFC控制器提供的ATS响应的各个字节的具体信息:
TL:ATS的响应长度。不能表明长度大于20个字节。
T0:比特5,6和7必须在全部HCE设备进行设置,指示的TA(1)。TB(1)和TC(1)包含在ATS响应。位1至4指示FSCI。编码的帧的最大尺寸。在HCE设备FSCI的值必须在0H和8h之间。
T(A)1:定义码率阅读器和仿真器之间,以及他们能否够是不正确称的。有没有比特率要求或担保HCE设备。
T(B)1:1位到4指示启动帧保护时间整数(SFGI)。在HCE设备,SFGI必须<= 8小时。位5至8指示帧的等待时间整数(FWI)和编码帧的等待时间(FWT)。
在HCE设备,FWI必须<= 8小时。
T(C)1:5位指示“高级功能协议”的支持。 HCE设备可能支持或不支持“高级协议功能”。第2位表示支持DID。 HCE设备能够支持或不支持DID。
位1指示NAD的支持。
HCE设备必须不支持NAD和设置位1至零。
历史字节:HCE设备最多能够返回15历史字节。 NFC读者愿意与HCE服务交互。不应对历史字节或他们的存在内容的如果。
请注意,很多HCE设备都有可能做出符合在EMVCo标准统一了支付网络在他们的“非接触式通信协议”规范中指定的协议的要求。尤其是:
FSCI在T0必须2H和8h之间。
T(A)1必须设置为0x80,表示仅仅有106千比特/秒的比特率被支持,而且不支持阅读器和仿真器之间的非对称比特率。
FWI在T(B)1必须<= 7小时。
APDU数据交换
如前所述,HCE实现仅仅支持一个单一的逻辑通道。尝试选择不同的逻辑通道的应用将不是一个HCE设备上执行。
Android API Guides---Host-based Card Emulation的更多相关文章
- Android API Guides 学习笔记---Application Fundamentals(一)
今天开始学习google官网上的API guides ,主要读了Application Fundamentals这一章节,此章节介绍了一个App的基本组成,共包括四大部分内容. 1. App ...
- Android API Guides 安卓API指导----第一部分:Introduction(介绍)
第一部分: Introduction(介绍) 目录包含:APP Fundamentals (应用程序基础) Device Compatibility(设备兼容性) System Perm ...
- Android API Guides –System Permissions
系统权限 声明: 本文由Gordon翻译 公布于www.dlvoice.com 欢迎转载,但请保留此声明 原文地址:http://developer.android.com/guide/topics/ ...
- Android API 指南
原文链接:http://android.eoe.cn/topic/android_sdk Android API 指南 - Android API Guides 应用的组成部分 - Applicati ...
- Instant Buy Android API Tutorial
转自:https://developers.google.com/wallet/instant-buy/android/tutorial This tutorial guides you throug ...
- 【译】基于主机的卡仿真(Host-based Card Emulation)
基于主机的卡仿真(Host-based Card Emulation) 能提供NFC功能很多Android手机已经支持NFC卡模拟.在大多数情况下,该卡是由设备中的单独的芯片仿真,所谓的安全元件.由无 ...
- Android UI开发第三十三篇——Navigation Drawer For Android API 7
Creating a Navigation Drawer中使用的Navigation Drawer的android:minSdkVersion="14",现在Android API ...
- Android Dev Guides
Android Dev Guides Google Java编程风格指南中文版 英文地址:http://google-styleguide.googlecode.com/svn/trunk/javag ...
- 【Android Api 翻译1】Android Texting(2)Testing Fundamentals 测试基础篇
Testing Fundamentals The Android testing framework, an integral part of the development environment, ...
随机推荐
- 一个关于Java 多线程问题的知识点
这个程序运行结果会是什么? public class Main {static class ListAdd { private static List list = new ArrayList(); ...
- redis的持久化(RDB&AOF的区别)
RDB 是什么? 在指定的时间间隔内将内存中的数据集快照写入磁盘, 也就是行话讲的Snapshot快照,它恢复时是将快照文件直接读到内存里. Redis会单独创建(fork)一个子进程来进行持久化,会 ...
- AC日记——Red and Blue Balls codeforces 399b
399B - Red and Blue Balls 思路: 惊讶的发现,所有的蓝球的消除都是独立的: 对于在栈中深度为i的蓝球消除需要2^i次操作: 代码: #include <cstdio&g ...
- Jquery学习之路(三) 实现弹出层插件
弹出层的应用还是比较多的,登陆,一些同页面的操作,别人的总归是别人的,自己的才是自己的,所以一直以来想写个弹出层插件.不多废话,直接开始吧! 不想看可以在这里直接下载源码xsPop.zip 1:遮罩层 ...
- Python3中的新特性(2)——常见陷阱
1.文本与字节 Python3对文本字符串(字符)和二进制数据(字节)进行了严格区分,'hello'表示一个以Unicode编码保存的文本字符串,而b'hello'表示一个字节字符串. 在Python ...
- vs2012将项目同步到github
http://www.cnblogs.com/SmallZL/p/3637613.html 大神作品,亲测可用
- Dijkstra算法解决单源最短路径
单源最短路径问题:给定一个带权有向图 G = (V, E), 其中每条边的权是一个实数.另外,还给定 V 中的一个顶点,称为源.现在要计算从源到其他所有各顶点的最短路径长度.这里的长度是指路上各边权之 ...
- lunux多线程编程
1.进程与线程 1)用户空间角度: 进程:fork()创建进程,在创建时,重新申请了内存空间,copy了父进程的所有信息. 线程:pthread_create()创建进程时,只申请自己的栈空间. 2) ...
- python3爬虫爬取煎蛋网妹纸图片(下篇)2018.6.25有效
分析完了真实图片链接地址,下面要做的就是写代码去实现了.想直接看源代码的可以点击这里 大致思路是:获取一个页面的的html---->使用正则表达式提取出图片hash值并进行base64解码--- ...
- [haoi2009]巧克力
鉴于河南是oi弱省,所以想来这道题也没什么人会翻出来写吧,而且这还是haoi2009的一道简单题目,所以估计也没几个人会写博客的,那么看在我这么弱的份上,我觉得是应该写一篇出来的. 这道题我是按照贪心 ...