首页 文章 精选 留言 我的

精选列表

搜索[加密解密],共10003篇文章
优秀的个人博客,低调大师

微服务治理解密

EDAS 是什么 有很多读者问我在阿里是做什么的,我一般会回答:“我在阿里主要负责 Dubbo、HSF、SpringCloud Alibaba 这几个微服务框架研发和商业化相关的工作”,这样回答,如果对方是 Java 开发,一般都能知道个大概。熟悉阿里云的朋友会了解到阿里云上有很多的 PaaS 产品,我主要就是负责开发 “企业级分布式应用服务 EDAS” 这款产品;不熟悉阿里云的朋友,会对阿里云上一堆产品、一堆名词感到奇怪,什么 EDAS、MSE、ACM、OAM… 我开始接触 EDAS 时,也是吐槽了一下这次名词,但随着逐渐了解,也就觉得这些云产品像 Redis、DB、MQ 这些东西一样亲切了。这篇文章将围绕 EDAS 这款阿里云云产品进行介绍。 企业级分布式应用服务 EDAS(Enterprise Distributed Application Service)是一个应用托管和微服务管理的 PaaS 平台,提供应用开发、部署、监控、运维等全栈式解决方案,同时支持 Spring Cloud、Apache Dubbo(以下简称 Dubbo )、HSF 等微服务运行环境,助力您的各类应用轻松上云。 可以从简介中提取出 EDAS 的核心能力:应用开发、应用部署、应用监控、应用运维。我这一篇文章自然是没办法介绍整个 PaaS 平台的能力,而且说实话,应用部署和应用监控等等能力也都是我同事们开发的,我真的一无所知,想介绍都难,所以在设计到细节时,我会主要介绍 EDAS 和微服务治理相关的那部分能力。 为什么用 EDAS 上图中,我将微服务框架的不同部署方式和云计算进行了绑定,以方便下面的介绍。 “种子”用户最容易理解了,例如使用开源的 Apache Dubbo 作为微服务框架,部署在自建机房的机器上,通常以中小公司为主,会有专门的运维搭建操作系统,设计网络拓扑,这也是云计算之前大多数公司的玩法。 但大家都知道,在现实生活中,“种子”变成“小麦”一般是农民伯伯的活,应该很少有人会因为想吃一个馒头,而去播撒一波种子的。例如很多互联网创业公司肯定接受不了这种玩法,想要尽快落地产品,第一步一定不是搞一堆机器,于是 IaaS 成了他们的救星,很多云计算公司提供了云服务器(ECS),解决了基础硬件问题,剩下的东西研发工程师都能搞定,所以“我有一个很好的 idea,就差一个程序员了”就变得流行了起来。在 IaaS 阶段,可以用 ECS 部署数据库,部署 Redis,部署 Dubbo 节点,机器出了问题可以提工单给云厂商,大大减少了运维成本,可以让研发人员更加专注在业务开发上。 很多 Dubbo 用户都是在“种子”和“小麦”阶段,还有人跟我说:我们公司在腾讯云上使用 Dubbo。老铁没毛病,开源框架没有强制跟任何云厂商绑定,Pivotal 的 SpringCloud 和 Alibaba 主导的 Dubbo 都是如此。可是,那我又有什么理由去进阶为“面粉”阶段的用户呢?我从 Dubbo 微信交流群的一些讨论去尝试回答这个问题: 请教大家一个问题,开源的 Dubbo 控制台有一个 xx 的问题,大家有遇到吗? 请教一下大家,Dubbo 的限流你们是怎么做的? 有没有人做过 Dubbo 的全链路跟踪的? Dubbo 的灰度发布有人在生产实践过吗? Dubbo 的分布式事务怎么做? Dubbo 的网关怎么做?······ 以 Dubbo 为例,大家可以看到一些端倪,开源框架也会存在一些问题。例如开源框架优先考虑的是功能的普适性,对例如灰度发布这种定制化的需求支持较少,且功能越高端,越难以支持。再例如 Dubbo 的全链路跟踪,基本上是每次 Dubbo Meetup 之后收集到的高频问题。有一些公司有基础架构团队,虽然使用的是开源 Dubbo,但他们有能力去进行改造,例如当当、考拉都拉了自己的分支在进行迭代,但我相信,他们自己的扩展也一定是优先适配各自公司的场景。还有一类问题,开源产品也会存在 bug,有时候自己定位出了 bug 提给社区,还得等其他人 review & merge request,必然会有时间成本,这也是很多公司自己拉分支自己维护的重要原因。说了这么多,其实都是在说“小麦”的缺点,“面粉”阶段又是如何解决这些问题的呢? 我在图中将 EDAS 这款阿里云的产品定位在了“面粉”阶段,主要原因便是: IaaS 层解决的问题,它都解决了,甚至做的更好。EDAS 甚至不需要用户去购买机器,可以进行诸如:弹性伸缩,限流降级,优雅上下线等应用生命周期的管理在微服务侧,它支持 Dubbo、SpringCloud、HSF 等主流的微服务框架,并且对微服务能力进行了增强。有很多商业化的特性,例如:白屏化的服务治理界面、分布式链路追踪、灰度发布、离群摘除、服务限流、注册中心的高可用…等等,并且随着后续的迭代,会继续支持分布式事务、网关等特性背靠阿里云,有专门的团队保障微服务的稳定性,让专业的人做专业的事我认为”面粉“是一个恰到好处的阶段,你可以烹饪成面包、面条、馒头,却又不会束缚你的产品形态。 EDAS 支持微服务的发展史 在阿里云的角度,如何吸引用户使用阿里云的服务呢?阿里云的服务实在太多了,还是来看微服务这个点。在 N 年前,EDAS 刚刚公测时,EDAS 主打的微服务框架是 HSF(High Speed Framework),熟悉它的朋友知道 HSF 是阿里集团内部使用的自研微服务框架,在历年双 11 支持整个阿里各个产品的平稳运行,有了双 11 这样量级的考验和阿里的背书,EDAS 支持 HSF 也就成了理所当然的事。这时候玩法是这样的: 如果是 Dubbo 既存用户想要上云使用 EDAS,就必须要改用 HSF 框架改写自己的业务代码,这个迁移成本是很高的。那如果是全新的业务使用 HSF,是不是就没有这个问题了呢?也不尽然。站在开发的角度,开源 Dubbo 的社区非常活跃,文档详细,遇到问题时,搜索引擎也基本能提供解决方案。但 HSF 不同,它是一款闭源的框架,即使是阿里内部用户,可能对其也是一知半解,遇到问题,只能借助于工单、答疑群解决,看不到源码是原罪。尽管 HSF 非常稳定,但用户把自己的代码托管在一个黑匣子中,多多少少会有所顾忌。 很多云平台都有类似的问题,业务上云往往意味着迁移技术栈,这个成本可想而知。 随着阿里重启了 Dubbo 的开源,EDAS 开始支持了开源 Dubbo,这一下子解决了很多上面提到的问题。对于那些处于”种子“、”小麦“阶段的 Dubbo 用户而言,使用 EDAS 不需要修改任何一行代码,即可获得 EDAS 承诺的诸多增强能力。 紧接着是 SpringCloud Alibaba 的开源,EDAS 也提供了 100% 的兼容。至此,Dubbo 和 SpringCloud 应用上云,EDAS 都能够 cover。 开源与商业化与云原生 从刚刚的发展史可以发现云厂商的一个玩法,Dubbo、SpringCloud Alibaba 最早都是由阿里主导开源的,在商业化云产品上都得到了优先的支持,不仅阿里这一家这么玩,华为开源了 ServiceComb,蚂蚁开源了 Sofa Stack,腾讯开源了 Tars,这几家都有各自的云平台,基本都会让用户迁移至自家的微服务框架。开源一方面是培养了用户习惯,积累影响力,一方面也是在为商业化铺路。 对接开源 SDK 逐渐成为了云厂商们的共识,只不过这里的开源 SDK 现如今没有统一,各家都有各自的玩法。不过这已经是一个很大的进步了,因为开源不会绑架用户,哪一天这家云厂商用的不爽了,随时迁走。相比使用云厂商提供的 SDK 来说,使用开源 SDK 这个理念不知道先进到哪里去了。 说道这里,不免会有人提出云原生的概念,开源 SDK 实在太多了,如果只有一套大家都遵守的规范就好了,云原生大概就是在做这么一件事。俗话说的好,三等码农写代码,二等码农写框架,一等码农定规范。但目前来说,还没有一统江湖的”云原生开源 SDK“,但已经有人再按照这样的思路再推进了,有兴趣的可以去了解下阿里提出的 OAM。 EDAS 微服务治理的难点 前面我们介绍到 EDAS 不仅仅是作为一个跑微服务框架的运行时容器,还为微服务框架提供了很多增强能力。科普完发展史之后,下面对微服务增强的细节进行介绍,但在此之前,为了不让读者知其然而不知其所以然,我先梳理下 EDAS 微服务治理的难点。 难点一EDAS 支持的微服务框架种类多,目前支持三种微服务框架:Dubbo、SpringCloud、HSF。 难点二微服务框架版本多: Dubbo 支持 2.5.x,2.6.x,2.7.x SpringCloud 支持 D 以上的版本 难点三例如传统的服务查询,需要访问注册中心,但用户使用的注册中心种类多: Zookeeper Nacos Eureka 难点四部署形态多,EDAS 支持两种部署形态: ECS Jar 包部署 K8s 镜像部署 难点五需要考虑存量用户的迁移问题和改造成本。 总而言之,EDAS 微服务增强的实现方式必须要考虑以上众多因素,在不得不进行 trade off 时,也应该尽可能解决较多的痛点,避免用户进行过多的改造。 EDAS 微服务增强实现 用户部署在 EDAS 中的代码使用的是开源的 SDK,EDAS 又承诺用户不需要改动代码,那是如何做到微服务能力增强的呢?满足这个要求的正是 JDK 提供的 Instrument 机制,熟悉 pinpoint 和 skywalking 等分布式链路追踪框架的读者应该对这个技术不会感到陌生。很久之前我曾经写过一篇文章对它进行过介绍:JAVA 拾遗 – Instrument 机制。 借助一个 Demo,通过 Instrument 来实现无侵入式的 AOP。 MicroServiceTransformer public class MicroServiceTransformer implements ClassFileTransformer { @Override public byte[] transform(ClassLoader loader, String className, Class<?> classBeingRedefined, ProtectionDomain protectionDomain, byte[] classfileBuffer) throws IllegalClassFormatException { if ("org/apache/dubbo/config/ReferenceConfig".equals(className)) { System.out.println("microservice improve"); } return null; } } 对类进行装配的第一步是编写一个 GreetingTransformer 类,其继承自:java.lang.instrument.ClassFileTransformer。 MicroServiceAgent 除了上述的 Transformer,我们还需要有一个容器去加载它。 public class MicroService { public static void premain(String options, Instrumentation ins) { ins.addTransformer(new MicroServiceTransformer()); } } MicroServiceAgent 便是最终用户的 Jar 运行时挂载的 agent。具体如何加载 agent ,可以参考上述的文章链接,有完整的 demo 和教程。这里主要是为了引出装配机制。 EDAS 的微服务增强逻辑便如同 AOP 一样,利用无侵入式的挂载,以达到增强的逻辑,这个过程需要 agent 对不同版本进行逐一的适配,从而实现服务查询、灰度发布、分布式链路跟踪、离群摘除等能力。 总结 本文其实也是一个主观视角,从一个对 EDAS 一无所知的角度,侧重于 EDAS 的微服务能力介绍了一遍 EDAS。EDAS 本身是一个商业化的云产品,但结合开源我们可以从它的演进历史看到一些软件架构演进的规律,这对于我们把握今后的技术发展趋势也有一定的指导意义。 作者信息:徐靖峰(花名:岛风),GitHub ID lexburner,阿里巴巴高级开发工程师,负责阿里巴巴服务治理框架的研发工作,关注微服务、服务治理和软件设计等领域。

优秀的个人博客,低调大师

解密IFTTT的数据架构

什么是IFTTT? IFTTT是“if this then that”的缩写,如果这样就那样。this 称为 trigger,而 that 称为 action。每条 if this then that 称为 task。IFTTT可以实现多种互联网应用的协同工作。 为了实现 IFTTT的功能,IFTTT必须获得授权。 走近IFTTT 随着信息技术的发展,人们在日常生活和工作中都不可避免的要用到邮箱、聊天工具、云存储等网络服务。然而,这些服务很多时候都是单独运行的,不能很好的实现资源共享。针对该问题,IFTTT提出了“让互联网为你服务”的概念,利用各网站和应用的开放API,实现了不同服务间的信息关联。 例如,IFTTT可以把指定号码发送的短信自动转发邮箱等。为了实现这些功能,IFTTT搭建了高性能的数据架构。近期,IFTTT的工程师Anuj Goyal对数据架构的概况进行了介绍,并分享了在操作数据时的一些经验和教训。 在IFTTT,数据非常重要——业务研发和营销团队依赖数据进行关键性业务决策;产品团队依赖数据运行测试/了解产品的使用情况,从而进行产品决策;数据团队本身也依赖数据来构建类似Recipe推荐系统和探测垃圾邮件的工具等;甚至合作伙伴也需要依赖数据来实时了解Channel的性能。鉴于数据如此重要,而IFTTT的服务每天又会产生超过数十亿个事件,IFTTT的数据框架具备了高度可扩展性、稳定性和灵活性等特点。接下来,本文就对数据架构进行详细分析。 1.数据源 在IFTTT,共有三种数据源对于理解用户行为和Channel性能非常重要。首先,AWS RDS中的MySQL集群负责维护用户、Channel、Recipe及其相互之间的关系等核心应用。运行在其Rails应用中的IFTTT.com和移动应用所产生的数据就通过AWS Data Pipeline,导出到S3和Redshift中。其次,用户和IFTTT产品交互时,通过Rails应用所产生的时间数据流入到Kafka集群中。最后,为了帮助监控上百个合作API的行为,IFTTT收集在运行Recipe时所产生的API请求的信息。这些包括反应时间和HTTP状态代码的信息同样流入到了Kafka集群中。 2.IFTTT的Kafka IFTTT利用Kafka作为数据传输层来取得数据产生者和消费者之间的松耦合。数据产生者首先把数据发送给Kafka。然后,数据消费者再从Kafka读取数据。因此,数据架构可以很方便的添加新的数据消费者。 由于Kafka扮演着基于日志的事件流的角色,数据消费者在事件流中保留着自己位置的轨迹。这使得消费者可以以实时和批处理的方式来操作数据。例如,批处理的消费者可以利用Secor将每个小时的数据拷贝发送到S3中;而实时消费者则利用即将开源的库将数据发送到Elasticsearch集群中。而且,在出现错误时,消费者还可以对数据进行重新处理。 3.商务智能 S3中的数据经过ETL平台Cranium的转换和归一化后,输出到AWS Redshift中。Cranium允许利用SQL和Ruby编写ETL任务、定义这些任务之间的依赖性以及调度这些任务的执行。Cranium支持利用Ruby和D3进行的即席报告。但是,绝大部分的可视化工作还是发生在Chartio中。 而且,Chartio对于只了解很少SQL的用户也非常友好。在这些工具的帮助下,从工程人员到业务研发人员和社区人员都可以对数据进行挖掘。 4.机器学习 IFTTT的研发团队利用了很多机器学习技术来保证用户体验。对于Recipe推荐和问题探测,IFTTT使用了运行在EC2上的Apache Spark,并将S3当作其数据存储。 5.实时监控和提醒 API事件存储在Elasticsearch中,用于监控和提醒。IFTTT使用Kibana来实时显示工作进程和合作API的性能。在API出现问题时,IFTTT的合作者可以访问专门的Developer Channel,创建Recipe,从而提醒实际行动(SMS、Email和Slack等)的进行。 在开发者视图内,合作者可以在Elasticsearch的帮助的帮助下访问Channel健康相关的实时日志和可视化图表。开发者也可以通过这些有力的分析来了解Channel的使用情况。 6.经验与教训 最后,Anuj表示,IFTTT从数据架构中得到的教训主要包括以下几点: 为了完全信任数据,在处理流中加入若干自动化的数据验证步骤非常重要!例如,IFTTT开发了一个服务来比较产品表和Redshift表中的行数,并在出现异常情况时发出提醒。 在类似的复杂架构中,设置合适的警告来保证系统工作正常是非常关键的!IFTTT使用Sematext来监控Kafka集群和消费者,并分别使用Pingdom和Pagerduty进行监控和提醒。 从一开始就要使用集群,方便以后的扩展!但是,在因为性能问题投入更多节点之前,一定要先认定系统的性能瓶颈。例如,在Elasticsearch中,如果碎片太多,添加更多的节点或许并 不会加速查询。最好先减少碎片大小来观察性能是否改善。 通过Kafka这样的数据传输层实现的生产者和消费者的隔离非常有用,且使得Data Pipeline的适应性更强。例如,一些比较慢的消费者也不会影响其他消费者或者生产者的性能。 在长期存储中使用基于日期的文件夹结构(YYYY/MM/DD)来存储事件数据。这样存储的事件数据可以很方便的进行处理。例如,如果想读取某一天的数据,只需要从一个文件夹中获取数 据即可。 在Elasticsearch中创建基于时间(例如,以小时为单位)的索引。这样,如果试图在Elasticsearch中寻找过去一小时中的所有API错误,只需要根据单个索引进行查询即可。 不要把单个数据马上发送到Elasticsearch中,最好成批进行处理。这样可以提高IO的效率。 根据数据和查询的类型,优化节点数、碎片数以及每个碎片和重复因子的最大尺寸都非常重要。 本文作者:以墨茄data 来源:51CTO

优秀的个人博客,低调大师

iOS NSString 加密

NSString+Hash.h #import <Foundation/Foundation.h> @interface NSString (Hash) #pragma mark - 散列函数 /** * 计算MD5散列结果 * * 终端测试命令: * @code * md5 -s "string" * @endcode * * <p>提示:随着 MD5 碰撞生成器的出现,MD5 算法不应被用于任何软件完整性检查或代码签名的用途。<p> * * @return 32个字符的MD5散列字符串 */ - (NSString *)md5String; /** * 计算SHA1散列结果 * * 终端测试命令: * @code * echo -n "string" | openssl sha -sha1 * @endcode * * @return 40个字符的SHA1散列字符串 */ - (NSString *)sha1String; /** * 计算SHA256散列结果 * * 终端测试命令: * @code * echo -n "string" | openssl sha -sha256 * @endcode * * @return 64个字符的SHA256散列字符串 */ - (NSString *)sha256String; /** * 计算SHA 512散列结果 * * 终端测试命令: * @code * echo -n "string" | openssl sha -sha512 * @endcode * * @return 128个字符的SHA 512散列字符串 */ - (NSString *)sha512String; #pragma mark - HMAC 散列函数 /** * 计算HMAC MD5散列结果 * * 终端测试命令: * @code * echo -n "string" | openssl dgst -md5 -hmac "key" * @endcode * * @return 32个字符的HMAC MD5散列字符串 */ - (NSString *)hmacMD5StringWithKey:(NSString *)key; /** * 计算HMAC SHA1散列结果 * * 终端测试命令: * @code * echo -n "string" | openssl sha -sha1 -hmac "key" * @endcode * * @return 40个字符的HMAC SHA1散列字符串 */ - (NSString *)hmacSHA1StringWithKey:(NSString *)key; /** * 计算HMAC SHA256散列结果 * * 终端测试命令: * @code * echo -n "string" | openssl sha -sha256 -hmac "key" * @endcode * * @return 64个字符的HMAC SHA256散列字符串 */ - (NSString *)hmacSHA256StringWithKey:(NSString *)key; /** * 计算HMAC SHA512散列结果 * * 终端测试命令: * @code * echo -n "string" | openssl sha -sha512 -hmac "key" * @endcode * * @return 128个字符的HMAC SHA512散列字符串 */ - (NSString *)hmacSHA512StringWithKey:(NSString *)key; #pragma mark - 文件散列函数 /** * 计算文件的MD5散列结果 * * 终端测试命令: * @code * md5 file.dat * @endcode * * @return 32个字符的MD5散列字符串 */ - (NSString *)fileMD5Hash; /** * 计算文件的SHA1散列结果 * * 终端测试命令: * @code * openssl sha -sha1 file.dat * @endcode * * @return 40个字符的SHA1散列字符串 */ - (NSString *)fileSHA1Hash; /** * 计算文件的SHA256散列结果 * * 终端测试命令: * @code * openssl sha -sha256 file.dat * @endcode * * @return 64个字符的SHA256散列字符串 */ - (NSString *)fileSHA256Hash; /** * 计算文件的SHA512散列结果 * * 终端测试命令: * @code * openssl sha -sha512 file.dat * @endcode * * @return 128个字符的SHA512散列字符串 */ - (NSString *)fileSHA512Hash; @end NSString+Hash.m #import "NSString+Hash.h" #import <CommonCrypto/CommonCrypto.h> @implementation NSString (Hash) #pragma mark - 散列函数 - (NSString *)md5String { const char *str = self.UTF8String; uint8_t buffer[CC_MD5_DIGEST_LENGTH]; CC_MD5(str, (CC_LONG)strlen(str), buffer); return [self stringFromBytes:buffer length:CC_MD5_DIGEST_LENGTH]; } - (NSString *)sha1String { const char *str = self.UTF8String; uint8_t buffer[CC_SHA1_DIGEST_LENGTH]; CC_SHA1(str, (CC_LONG)strlen(str), buffer); return [self stringFromBytes:buffer length:CC_SHA1_DIGEST_LENGTH]; } - (NSString *)sha256String { const char *str = self.UTF8String; uint8_t buffer[CC_SHA256_DIGEST_LENGTH]; CC_SHA256(str, (CC_LONG)strlen(str), buffer); return [self stringFromBytes:buffer length:CC_SHA256_DIGEST_LENGTH]; } - (NSString *)sha512String { const char *str = self.UTF8String; uint8_t buffer[CC_SHA512_DIGEST_LENGTH]; CC_SHA512(str, (CC_LONG)strlen(str), buffer); return [self stringFromBytes:buffer length:CC_SHA512_DIGEST_LENGTH]; } #pragma mark - HMAC 散列函数 - (NSString *)hmacMD5StringWithKey:(NSString *)key { const char *keyData = key.UTF8String; const char *strData = self.UTF8String; uint8_t buffer[CC_MD5_DIGEST_LENGTH]; CCHmac(kCCHmacAlgMD5, keyData, strlen(keyData), strData, strlen(strData), buffer); return [self stringFromBytes:buffer length:CC_MD5_DIGEST_LENGTH]; } - (NSString *)hmacSHA1StringWithKey:(NSString *)key { const char *keyData = key.UTF8String; const char *strData = self.UTF8String; uint8_t buffer[CC_SHA1_DIGEST_LENGTH]; CCHmac(kCCHmacAlgSHA1, keyData, strlen(keyData), strData, strlen(strData), buffer); return [self stringFromBytes:buffer length:CC_SHA1_DIGEST_LENGTH]; } - (NSString *)hmacSHA256StringWithKey:(NSString *)key { const char *keyData = key.UTF8String; const char *strData = self.UTF8String; uint8_t buffer[CC_SHA256_DIGEST_LENGTH]; CCHmac(kCCHmacAlgSHA256, keyData, strlen(keyData), strData, strlen(strData), buffer); return [self stringFromBytes:buffer length:CC_SHA256_DIGEST_LENGTH]; } - (NSString *)hmacSHA512StringWithKey:(NSString *)key { const char *keyData = key.UTF8String; const char *strData = self.UTF8String; uint8_t buffer[CC_SHA512_DIGEST_LENGTH]; CCHmac(kCCHmacAlgSHA512, keyData, strlen(keyData), strData, strlen(strData), buffer); return [self stringFromBytes:buffer length:CC_SHA512_DIGEST_LENGTH]; } #pragma mark - 文件散列函数 #define FileHashDefaultChunkSizeForReadingData 4096 - (NSString *)fileMD5Hash { NSFileHandle *fp = [NSFileHandle fileHandleForReadingAtPath:self]; if (fp == nil) { return nil; } CC_MD5_CTX hashCtx; CC_MD5_Init(&hashCtx); while (YES) { @autoreleasepool { NSData *data = [fp readDataOfLength:FileHashDefaultChunkSizeForReadingData]; CC_MD5_Update(&hashCtx, data.bytes, (CC_LONG)data.length); if (data.length == 0) { break; } } } [fp closeFile]; uint8_t buffer[CC_MD5_DIGEST_LENGTH]; CC_MD5_Final(buffer, &hashCtx); return [self stringFromBytes:buffer length:CC_MD5_DIGEST_LENGTH]; } - (NSString *)fileSHA1Hash { NSFileHandle *fp = [NSFileHandle fileHandleForReadingAtPath:self]; if (fp == nil) { return nil; } CC_SHA1_CTX hashCtx; CC_SHA1_Init(&hashCtx); while (YES) { @autoreleasepool { NSData *data = [fp readDataOfLength:FileHashDefaultChunkSizeForReadingData]; CC_SHA1_Update(&hashCtx, data.bytes, (CC_LONG)data.length); if (data.length == 0) { break; } } } [fp closeFile]; uint8_t buffer[CC_SHA1_DIGEST_LENGTH]; CC_SHA1_Final(buffer, &hashCtx); return [self stringFromBytes:buffer length:CC_SHA1_DIGEST_LENGTH]; } - (NSString *)fileSHA256Hash { NSFileHandle *fp = [NSFileHandle fileHandleForReadingAtPath:self]; if (fp == nil) { return nil; } CC_SHA256_CTX hashCtx; CC_SHA256_Init(&hashCtx); while (YES) { @autoreleasepool { NSData *data = [fp readDataOfLength:FileHashDefaultChunkSizeForReadingData]; CC_SHA256_Update(&hashCtx, data.bytes, (CC_LONG)data.length); if (data.length == 0) { break; } } } [fp closeFile]; uint8_t buffer[CC_SHA256_DIGEST_LENGTH]; CC_SHA256_Final(buffer, &hashCtx); return [self stringFromBytes:buffer length:CC_SHA256_DIGEST_LENGTH]; } - (NSString *)fileSHA512Hash { NSFileHandle *fp = [NSFileHandle fileHandleForReadingAtPath:self]; if (fp == nil) { return nil; } CC_SHA512_CTX hashCtx; CC_SHA512_Init(&hashCtx); while (YES) { @autoreleasepool { NSData *data = [fp readDataOfLength:FileHashDefaultChunkSizeForReadingData]; CC_SHA512_Update(&hashCtx, data.bytes, (CC_LONG)data.length); if (data.length == 0) { break; } } } [fp closeFile]; uint8_t buffer[CC_SHA512_DIGEST_LENGTH]; CC_SHA512_Final(buffer, &hashCtx); return [self stringFromBytes:buffer length:CC_SHA512_DIGEST_LENGTH]; } #pragma mark - 助手方法 /** * 返回二进制 Bytes 流的字符串表示形式 * * @param bytes 二进制 Bytes 数组 * @param length 数组长度 * * @return 字符串表示形式 */ - (NSString *)stringFromBytes:(uint8_t *)bytes length:(int)length { NSMutableString *strM = [NSMutableString string]; for (int i = 0; i < length; i++) { [strM appendFormat:@"%02x", bytes[i]]; } return [strM copy]; } @end

资源下载

更多资源
Mario

Mario

马里奥是站在游戏界顶峰的超人气多面角色。马里奥靠吃蘑菇成长,特征是大鼻子、头戴帽子、身穿背带裤,还留着胡子。与他的双胞胎兄弟路易基一起,长年担任任天堂的招牌角色。

Nacos

Nacos

Nacos /nɑ:kəʊs/ 是 Dynamic Naming and Configuration Service 的首字母简称,一个易于构建 AI Agent 应用的动态服务发现、配置管理和AI智能体管理平台。Nacos 致力于帮助您发现、配置和管理微服务及AI智能体应用。Nacos 提供了一组简单易用的特性集,帮助您快速实现动态服务发现、服务配置、服务元数据、流量管理。Nacos 帮助您更敏捷和容易地构建、交付和管理微服务平台。

Spring

Spring

Spring框架(Spring Framework)是由Rod Johnson于2002年提出的开源Java企业级应用框架,旨在通过使用JavaBean替代传统EJB实现方式降低企业级编程开发的复杂性。该框架基于简单性、可测试性和松耦合性设计理念,提供核心容器、应用上下文、数据访问集成等模块,支持整合Hibernate、Struts等第三方框架,其适用范围不仅限于服务器端开发,绝大多数Java应用均可从中受益。

Sublime Text

Sublime Text

Sublime Text具有漂亮的用户界面和强大的功能,例如代码缩略图,Python的插件,代码段等。还可自定义键绑定,菜单和工具栏。Sublime Text 的主要功能包括:拼写检查,书签,完整的 Python API , Goto 功能,即时项目切换,多选择,多窗口等等。Sublime Text 是一个跨平台的编辑器,同时支持Windows、Linux、Mac OS X等操作系统。

用户登录
用户注册